Skip to content

Commit

Permalink
Move getSubstitutionMap to KernelClassBuilder
Browse files Browse the repository at this point in the history
Also, change the signature to return a kernel substitution map.

This prepares for fixing issue dart-lang/sdk#34856,
as DillClassBuilders don't have builder wrappers for type variables and
supertypes.

Change-Id: Ia3f2458852ffaad766c44f62fd93e68234650126
Reviewed-on: https://dart-review.googlesource.com/c/81002
Reviewed-by: Kevin Millikin <[email protected]>
  • Loading branch information
peter-ahe-google authored and [email protected] committed Oct 22, 2018
1 parent af8e291 commit 704a435
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 121 deletions.
96 changes: 1 addition & 95 deletions pkg/front_end/lib/src/fasta/builder/class_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,14 @@ import 'builder.dart'
LibraryBuilder,
MemberBuilder,
MetadataBuilder,
MixinApplicationBuilder,
NamedTypeBuilder,
Scope,
ScopeBuilder,
TypeBuilder,
TypeDeclarationBuilder,
TypeVariableBuilder;

import '../fasta_codes.dart'
show
LocatedMessage,
Message,
templateInternalProblemNotFoundIn,
templateInternalProblemSuperclassNotFound;
show LocatedMessage, Message, templateInternalProblemNotFoundIn;

abstract class ClassBuilder<T extends TypeBuilder, R>
extends TypeDeclarationBuilder<T, R> {
Expand Down Expand Up @@ -129,94 +123,6 @@ abstract class ClassBuilder<T extends TypeBuilder, R>
return constructors.lookup(name, charOffset, uri);
}

/// Returns a map which maps the type variables of [superclass] to their
/// respective values as defined by the superclass clause of this class (and
/// its superclasses).
///
/// It's assumed that [superclass] is a superclass of this class.
///
/// For example, given:
///
/// class Box<T> {}
/// class BeatBox extends Box<Beat> {}
/// class Beat {}
///
/// We have:
///
/// [[BeatBox]].getSubstitutionMap([[Box]]) -> {[[Box::T]]: Beat]]}.
///
/// This method returns null if the map is empty, and it's an error if
/// [superclass] isn't a superclass.
Map<TypeVariableBuilder, TypeBuilder> getSubstitutionMap(
ClassBuilder superclass,
Uri fileUri,
int charOffset,
TypeBuilder dynamicType) {
TypeBuilder supertype = this.supertype;
Map<TypeVariableBuilder, TypeBuilder> substitutionMap;
List arguments;
List variables;
Declaration declaration;

/// If [application] is mixing in [superclass] directly or via other named
/// mixin applications, return it.
NamedTypeBuilder findSuperclass(MixinApplicationBuilder application) {
for (TypeBuilder t in application.mixins) {
if (t is NamedTypeBuilder) {
if (t.declaration == superclass) return t;
} else if (t is MixinApplicationBuilder) {
NamedTypeBuilder s = findSuperclass(t);
if (s != null) return s;
}
}
return null;
}

void handleNamedTypeBuilder(NamedTypeBuilder t) {
declaration = t.declaration;
arguments = t.arguments ?? const [];
if (declaration is ClassBuilder) {
ClassBuilder cls = declaration;
variables = cls.typeVariables;
supertype = cls.supertype;
}
}

while (declaration != superclass) {
variables = null;
if (supertype is NamedTypeBuilder) {
handleNamedTypeBuilder(supertype);
} else if (supertype is MixinApplicationBuilder) {
MixinApplicationBuilder t = supertype;
NamedTypeBuilder s = findSuperclass(t);
if (s != null) {
handleNamedTypeBuilder(s);
}
supertype = t.supertype;
} else {
internalProblem(
templateInternalProblemSuperclassNotFound
.withArguments(superclass.fullNameForErrors),
charOffset,
fileUri);
}
if (variables != null) {
Map<TypeVariableBuilder, TypeBuilder> directSubstitutionMap =
<TypeVariableBuilder, TypeBuilder>{};
for (int i = 0; i < variables.length; i++) {
TypeBuilder argument =
i < arguments.length ? arguments[i] : dynamicType;
if (substitutionMap != null) {
argument = argument.subst(substitutionMap);
}
directSubstitutionMap[variables[i]] = argument;
}
substitutionMap = directSubstitutionMap;
}
}
return substitutionMap;
}

void forEach(void f(String name, MemberBuilder builder)) {
scope.forEach(f);
}
Expand Down
117 changes: 109 additions & 8 deletions pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ import 'package:kernel/clone.dart' show CloneWithoutBody;

import 'package:kernel/core_types.dart' show CoreTypes;

import 'package:kernel/type_algebra.dart' show Substitution, getSubstitutionMap;
import 'package:kernel/type_algebra.dart' show Substitution;

import 'package:kernel/type_algebra.dart' as type_algebra
show getSubstitutionMap;

import 'package:kernel/type_environment.dart' show TypeEnvironment;

Expand All @@ -61,15 +64,16 @@ import '../fasta_codes.dart'
templateFactoryRedirecteeHasTooFewPositionalParameters,
templateFactoryRedirecteeInvalidReturnType,
templateGenericFunctionTypeInferredAsActualTypeArgument,
templateIllegalMixinDueToConstructors,
templateIllegalMixinDueToConstructorsCause,
templateImplementsRepeated,
templateImplementsSuperClass,
templateImplicitMixinOverrideContext,
templateInterfaceCheckContext,
templateIncorrectTypeArgument,
templateIncorrectTypeArgumentInSupertype,
templateIncorrectTypeArgumentInSupertypeInferred,
templateIllegalMixinDueToConstructors,
templateIllegalMixinDueToConstructorsCause,
templateInterfaceCheckContext,
templateInternalProblemSuperclassNotFound,
templateMissingImplementationCause,
templateMissingImplementationNotAbstract,
templateMixinApplicationIncompatibleSupertype,
Expand All @@ -92,7 +96,8 @@ import '../fasta_codes.dart'

import '../names.dart' show noSuchMethodName;

import '../problems.dart' show unexpected, unhandled, unimplemented;
import '../problems.dart'
show internalProblem, unexpected, unhandled, unimplemented;

import '../type_inference/type_schema.dart' show UnknownType;

Expand All @@ -101,18 +106,21 @@ import 'kernel_builder.dart'
ClassBuilder,
ConstructorReferenceBuilder,
Declaration,
KernelLibraryBuilder,
KernelFunctionBuilder,
KernelLibraryBuilder,
KernelNamedTypeBuilder,
KernelProcedureBuilder,
KernelRedirectingFactoryBuilder,
KernelNamedTypeBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
LibraryBuilder,
MemberBuilder,
MetadataBuilder,
MixinApplicationBuilder,
NamedTypeBuilder,
ProcedureBuilder,
Scope,
TypeBuilder,
TypeVariableBuilder;

import 'redirecting_factory_body.dart'
Expand Down Expand Up @@ -723,7 +731,7 @@ abstract class KernelClassBuilder
void addNoSuchMethodForwarderForProcedure(Member noSuchMethod,
KernelTarget target, Procedure procedure, ClassHierarchy hierarchy) {
CloneWithoutBody cloner = new CloneWithoutBody(
typeSubstitution: getSubstitutionMap(
typeSubstitution: type_algebra.getSubstitutionMap(
hierarchy.getClassAsInstanceOf(cls, procedure.enclosingClass)),
cloneAnnotations: false);
Procedure cloned = cloner.clone(procedure)..isExternal = false;
Expand Down Expand Up @@ -1716,4 +1724,97 @@ abstract class KernelClassBuilder
}
}
}

/// Returns a map which maps the type variables of [superclass] to their
/// respective values as defined by the superclass clause of this class (and
/// its superclasses).
///
/// It's assumed that [superclass] is a superclass of this class.
///
/// For example, given:
///
/// class Box<T> {}
/// class BeatBox extends Box<Beat> {}
/// class Beat {}
///
/// We have:
///
/// [[BeatBox]].getSubstitutionMap([[Box]]) -> {[[Box::T]]: Beat]]}.
///
/// This method returns null if the map is empty, and it's an error if
/// [superclass] isn't a superclass.
Map<TypeParameter, DartType> getSubstitutionMap(ClassBuilder superclass,
Uri fileUri, int charOffset, TypeBuilder dynamicType) {
TypeBuilder supertype = this.supertype;
Map<TypeVariableBuilder, TypeBuilder> substitutionMap;
List arguments;
List variables;
Declaration declaration;

/// If [application] is mixing in [superclass] directly or via other named
/// mixin applications, return it.
NamedTypeBuilder findSuperclass(MixinApplicationBuilder application) {
for (TypeBuilder t in application.mixins) {
if (t is NamedTypeBuilder) {
if (t.declaration == superclass) return t;
} else if (t is MixinApplicationBuilder) {
NamedTypeBuilder s = findSuperclass(t);
if (s != null) return s;
}
}
return null;
}

void handleNamedTypeBuilder(NamedTypeBuilder t) {
declaration = t.declaration;
arguments = t.arguments ?? const [];
if (declaration is ClassBuilder) {
ClassBuilder cls = declaration;
variables = cls.typeVariables;
supertype = cls.supertype;
}
}

while (declaration != superclass) {
variables = null;
if (supertype is NamedTypeBuilder) {
handleNamedTypeBuilder(supertype);
} else if (supertype is MixinApplicationBuilder) {
MixinApplicationBuilder t = supertype;
NamedTypeBuilder s = findSuperclass(t);
if (s != null) {
handleNamedTypeBuilder(s);
}
supertype = t.supertype;
} else {
internalProblem(
templateInternalProblemSuperclassNotFound
.withArguments(superclass.fullNameForErrors),
charOffset,
fileUri);
}
if (variables != null) {
Map<TypeVariableBuilder, TypeBuilder> directSubstitutionMap =
<TypeVariableBuilder, TypeBuilder>{};
for (int i = 0; i < variables.length; i++) {
TypeBuilder argument =
i < arguments.length ? arguments[i] : dynamicType;
if (substitutionMap != null) {
argument = argument.subst(substitutionMap);
}
directSubstitutionMap[variables[i]] = argument;
}
substitutionMap = directSubstitutionMap;
}
}

if (substitutionMap == null) return const <TypeParameter, DartType>{};

Map<TypeParameter, DartType> result = <TypeParameter, DartType>{};
substitutionMap
.forEach((TypeVariableBuilder variable, TypeBuilder argument) {
result[variable.target] = argument.build(library);
});
return result;
}
}
21 changes: 3 additions & 18 deletions pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ import 'kernel_builder.dart'
LibraryBuilder,
NamedTypeBuilder,
TypeBuilder,
TypeDeclarationBuilder,
TypeVariableBuilder;
TypeDeclarationBuilder;

import 'metadata_collector.dart' show MetadataCollector;

Expand Down Expand Up @@ -482,10 +481,8 @@ class KernelTarget extends TargetImplementation {
builder.addSyntheticConstructor(makeDefaultConstructor(builder.target));
} else {
Map<TypeParameter, DartType> substitutionMap =
computeKernelSubstitutionMap(
builder.getSubstitutionMap(supertype, builder.fileUri,
builder.charOffset, dynamicType),
builder.parent);
builder.getSubstitutionMap(
supertype, builder.fileUri, builder.charOffset, dynamicType);
for (Constructor constructor in supertype.cls.constructors) {
builder.addSyntheticConstructor(makeMixinApplicationConstructor(
builder.target, builder.cls.mixin, constructor, substitutionMap));
Expand All @@ -499,18 +496,6 @@ class KernelTarget extends TargetImplementation {
}
}

Map<TypeParameter, DartType> computeKernelSubstitutionMap(
Map<TypeVariableBuilder, TypeBuilder> substitutionMap,
LibraryBuilder library) {
if (substitutionMap == null) return const <TypeParameter, DartType>{};
Map<TypeParameter, DartType> result = <TypeParameter, DartType>{};
substitutionMap
.forEach((TypeVariableBuilder variable, TypeBuilder argument) {
result[variable.target] = argument.build(library);
});
return result;
}

Constructor makeMixinApplicationConstructor(Class cls, Class mixin,
Constructor constructor, Map<TypeParameter, DartType> substitutionMap) {
VariableDeclaration copyFormal(VariableDeclaration formal) {
Expand Down

0 comments on commit 704a435

Please sign in to comment.