Skip to content

Commit

Permalink
[cfe] Make API of as-instance-of and legacy LUB/GLB library-specific
Browse files Browse the repository at this point in the history
Change-Id: I1991c66e654ef537243d9f25f17070acbfa13af9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/126380
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
  • Loading branch information
Dmitry Stefantsov authored and commit-bot@chromium.org committed Dec 5, 2019
1 parent ae14121 commit 47a9ebe
Show file tree
Hide file tree
Showing 109 changed files with 869 additions and 538 deletions.
61 changes: 45 additions & 16 deletions pkg/compiler/lib/src/ir/static_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
final ir.ClassHierarchy hierarchy;

ThisInterfaceType _thisType;
ir.Library _currentLibrary;

StaticTypeVisitor(ir.TypeEnvironment typeEnvironment, this.hierarchy)
: super(typeEnvironment);
Expand Down Expand Up @@ -83,6 +84,16 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
_thisType = value;
}

ir.Library get currentLibrary {
assert(_currentLibrary != null);
return _currentLibrary;
}

void set currentLibrary(ir.Library value) {
assert(value == null || _currentLibrary == null);
_currentLibrary = value;
}

bool completes(ir.DartType type) => type != const DoesNotCompleteType();

Set<ir.VariableDeclaration> _currentVariables;
Expand Down Expand Up @@ -173,7 +184,8 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
/// If this is not the case the raw type of [superclass] is returned.
///
/// This method is derived from `ir.Expression.getStaticTypeAsInstanceOf`.
ir.InterfaceType getTypeAsInstanceOf(ir.DartType type, ir.Class superclass) {
ir.InterfaceType getTypeAsInstanceOf(
ir.DartType type, ir.Class superclass, ir.Library clientLibrary) {
// This method assumes the program is correctly typed, so if the superclass
// is not generic, we can just return its raw type without computing the
// type of this expression. It also ensures that all types are considered
Expand All @@ -186,14 +198,16 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
type = (type as ir.TypeParameterType).parameter.bound;
}
if (type == typeEnvironment.nullType) {
return superclass.bottomType;
return typeEnvironment.coreTypes
.bottomInterfaceType(superclass, ir.Nullability.legacy);
}
if (type is ir.InterfaceType) {
ir.InterfaceType upcastType =
typeEnvironment.getTypeAsInstanceOf(type, superclass);
ir.InterfaceType upcastType = typeEnvironment.getTypeAsInstanceOf(
type, superclass, clientLibrary, typeEnvironment.coreTypes);
if (upcastType != null) return upcastType;
} else if (type is ir.BottomType) {
return superclass.bottomType;
return typeEnvironment.coreTypes
.bottomInterfaceType(superclass, ir.Nullability.legacy);
}
// TODO(johnniwinther): Should we assert that this doesn't happen?
return typeEnvironment.coreTypes.legacyRawType(superclass);
Expand All @@ -213,7 +227,8 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
}
if (interfaceTarget != null) {
ir.Class superclass = interfaceTarget.enclosingClass;
receiverType = getTypeAsInstanceOf(receiverType, superclass);
receiverType =
getTypeAsInstanceOf(receiverType, superclass, currentLibrary);
return ir.Substitution.fromInterfaceType(receiverType)
.substituteType(interfaceTarget.getterType);
}
Expand Down Expand Up @@ -283,7 +298,7 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
ir.Class superclass = interfaceTarget.enclosingClass;
ir.Substitution receiverSubstitution =
ir.Substitution.fromInterfaceType(
getTypeAsInstanceOf(receiverType, superclass));
getTypeAsInstanceOf(receiverType, superclass, currentLibrary));
ir.DartType setterType =
receiverSubstitution.substituteType(interfaceTarget.setterType);
if (!typeEnvironment.isSubtypeOf(
Expand Down Expand Up @@ -316,7 +331,8 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
ir.DartType visitDirectPropertyGet(ir.DirectPropertyGet node) {
ir.DartType receiverType = visitNode(node.receiver);
ir.Class superclass = node.target.enclosingClass;
receiverType = getTypeAsInstanceOf(receiverType, superclass);
receiverType =
getTypeAsInstanceOf(receiverType, superclass, currentLibrary);
ir.DartType resultType = ir.Substitution.fromInterfaceType(receiverType)
.substituteType(node.target.getterType);
_expressionTypeCache[node] = resultType;
Expand All @@ -341,7 +357,8 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
receiverType, argumentType);
} else {
ir.Class superclass = node.target.enclosingClass;
receiverType = getTypeAsInstanceOf(receiverType, superclass);
receiverType =
getTypeAsInstanceOf(receiverType, superclass, currentLibrary);
ir.DartType returnType = ir.Substitution.fromInterfaceType(receiverType)
.substituteType(node.target.function.returnType);
returnType = ir.Substitution.fromPairs(
Expand Down Expand Up @@ -597,7 +614,7 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
if (interfaceTarget != null) {
ir.Class superclass = interfaceTarget.enclosingClass;
ir.Substitution receiverSubstitution = ir.Substitution.fromInterfaceType(
getTypeAsInstanceOf(receiverType, superclass));
getTypeAsInstanceOf(receiverType, superclass, currentLibrary));
ir.DartType getterType =
receiverSubstitution.substituteType(interfaceTarget.getterType);
if (getterType is ir.FunctionType) {
Expand Down Expand Up @@ -810,8 +827,8 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
if (declaringClass.typeParameters.isEmpty) {
resultType = node.interfaceTarget.getterType;
} else {
ir.DartType receiver =
typeEnvironment.getTypeAsInstanceOf(thisType, declaringClass);
ir.DartType receiver = typeEnvironment.getTypeAsInstanceOf(thisType,
declaringClass, currentLibrary, typeEnvironment.coreTypes);
resultType = ir.Substitution.fromInterfaceType(receiver)
.substituteType(node.interfaceTarget.getterType);
}
Expand Down Expand Up @@ -843,8 +860,8 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
returnType = const ir.DynamicType();
} else {
ir.Class superclass = node.interfaceTarget.enclosingClass;
ir.InterfaceType receiverType =
typeEnvironment.getTypeAsInstanceOf(thisType, superclass);
ir.InterfaceType receiverType = typeEnvironment.getTypeAsInstanceOf(
thisType, superclass, currentLibrary, typeEnvironment.coreTypes);
returnType = ir.Substitution.fromInterfaceType(receiverType)
.substituteType(node.interfaceTarget.function.returnType);
returnType = ir.Substitution.fromPairs(
Expand Down Expand Up @@ -1216,7 +1233,10 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
if (node.isAsync) {
ir.InterfaceType streamInterfaceType = getInterfaceTypeOf(iterableType);
ir.InterfaceType streamType = typeEnvironment.getTypeAsInstanceOf(
streamInterfaceType, typeEnvironment.coreTypes.streamClass);
streamInterfaceType,
typeEnvironment.coreTypes.streamClass,
currentLibrary,
typeEnvironment.coreTypes);
if (streamType != null) {
iteratorType = new ir.InterfaceType(
typeEnvironment.coreTypes.streamIteratorClass,
Expand All @@ -1230,7 +1250,10 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
if (member != null) {
iteratorType = ir.Substitution.fromInterfaceType(
typeEnvironment.getTypeAsInstanceOf(
iterableInterfaceType, member.enclosingClass))
iterableInterfaceType,
member.enclosingClass,
currentLibrary,
typeEnvironment.coreTypes))
.substituteType(member.getterType);
}
}
Expand Down Expand Up @@ -1382,12 +1405,14 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
thisType = new ThisInterfaceType.from(node.enclosingClass?.getThisType(
typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
_currentVariables = {};
currentLibrary = node.enclosingLibrary;
visitSignature(node.function);
visitNode(node.function.body);
handleProcedure(node);
_invalidatedVariables.removeAll(_currentVariables);
_currentVariables = null;
thisType = null;
currentLibrary = null;
}

void handleConstructor(ir.Constructor node) {}
Expand All @@ -1397,13 +1422,15 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
thisType = new ThisInterfaceType.from(node.enclosingClass.getThisType(
typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
_currentVariables = {};
currentLibrary = node.enclosingLibrary;
visitSignature(node.function);
visitNodes(node.initializers);
visitNode(node.function.body);
handleConstructor(node);
_invalidatedVariables.removeAll(_currentVariables);
_currentVariables = null;
thisType = null;
currentLibrary = null;
}

void handleField(ir.Field node) {}
Expand All @@ -1413,11 +1440,13 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
thisType = new ThisInterfaceType.from(node.enclosingClass?.getThisType(
typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
_currentVariables = {};
currentLibrary = node.enclosingLibrary;
visitNode(node.initializer);
handleField(node);
_invalidatedVariables.removeAll(_currentVariables);
_currentVariables = null;
thisType = null;
currentLibrary = null;
}

void handleVariableDeclaration(ir.VariableDeclaration node) {}
Expand Down
5 changes: 3 additions & 2 deletions pkg/dev_compiler/lib/src/kernel/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2987,8 +2987,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
DartType _expectedReturnType(FunctionNode f, Class expected) {
var type = f.thisFunctionType.returnType;
if (type is InterfaceType) {
var match = _hierarchy.getTypeAsInstanceOf(type, expected);
if (match != null) return match.typeArguments[0];
var matchArguments =
_hierarchy.getTypeArgumentsAsInstanceOf(type, expected);
if (matchArguments != null) return matchArguments[0];
}
return const DynamicType();
}
Expand Down
21 changes: 14 additions & 7 deletions pkg/front_end/lib/src/fasta/builder/class_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ abstract class ClassBuilder implements DeclarationBuilder {
Message message, int fileOffset, int length,
{List<LocatedMessage> context});

void checkMixinApplication(ClassHierarchy hierarchy);
void checkMixinApplication(ClassHierarchy hierarchy, CoreTypes coreTypes);

// Computes the function type of a given redirection target. Returns [null] if
// the type of the target could not be computed.
Expand Down Expand Up @@ -1094,8 +1094,11 @@ abstract class ClassBuilderImpl extends DeclarationBuilderImpl
bool isInterfaceCheck) {
Substitution interfaceSubstitution = Substitution.empty;
if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
interfaceSubstitution = Substitution.fromInterfaceType(types.hierarchy
.getKernelTypeAsInstanceOf(thisType, interfaceMember.enclosingClass));
Class enclosingClass = interfaceMember.enclosingClass;
interfaceSubstitution = Substitution.fromPairs(
enclosingClass.typeParameters,
types.hierarchy
.getKernelTypeArgumentsAsInstanceOf(thisType, enclosingClass));
}
if (declaredFunction?.typeParameters?.length !=
interfaceFunction?.typeParameters?.length) {
Expand Down Expand Up @@ -1166,8 +1169,11 @@ abstract class ClassBuilderImpl extends DeclarationBuilderImpl
Types types, Member declaredMember) {
Substitution declaredSubstitution = Substitution.empty;
if (declaredMember.enclosingClass.typeParameters.isNotEmpty) {
declaredSubstitution = Substitution.fromInterfaceType(types.hierarchy
.getKernelTypeAsInstanceOf(thisType, declaredMember.enclosingClass));
Class enclosingClass = declaredMember.enclosingClass;
declaredSubstitution = Substitution.fromPairs(
enclosingClass.typeParameters,
types.hierarchy
.getKernelTypeArgumentsAsInstanceOf(thisType, enclosingClass));
}
return declaredSubstitution;
}
Expand Down Expand Up @@ -1534,15 +1540,16 @@ abstract class ClassBuilderImpl extends DeclarationBuilderImpl
}

@override
void checkMixinApplication(ClassHierarchy hierarchy) {
void checkMixinApplication(ClassHierarchy hierarchy, CoreTypes coreTypes) {
// A mixin declaration can only be applied to a class that implements all
// the declaration's superclass constraints.
InterfaceType supertype = cls.supertype.asInterfaceType;
Substitution substitution = Substitution.fromSupertype(cls.mixedInType);
for (Supertype constraint in cls.mixedInClass.superclassConstraints()) {
InterfaceType interface =
substitution.substituteSupertype(constraint).asInterfaceType;
if (hierarchy.getTypeAsInstanceOf(supertype, interface.classNode) !=
if (hierarchy.getTypeAsInstanceOf(
supertype, interface.classNode, library.library, coreTypes) !=
interface) {
library.addProblem(
templateMixinApplicationIncompatibleSupertype.withArguments(
Expand Down
Loading

0 comments on commit 47a9ebe

Please sign in to comment.