Index: sdk/lib/_internal/compiler/implementation/typechecker.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart |
index 22c0ad92c14fca1bd4270a2f076cd2b8dd17f848..88f30dd27d477a3b5e3c899d3bc24ba7f314ba33 100644 |
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart |
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart |
@@ -51,7 +51,7 @@ abstract class ElementAccess { |
/// Returns [: true :] if the element can be access as an invocation. |
bool isCallable(Compiler compiler) { |
- if (element.isAbstractField) { |
+ if (element != null && element.isAbstractField) { |
AbstractFieldElement abstractFieldElement = element; |
if (abstractFieldElement.getter == null) { |
// Setters cannot be invoked as function invocations. |
@@ -82,7 +82,7 @@ class DynamicAccess implements ElementAccess { |
Element get element => null; |
- DartType computeType(Compiler compiler) => compiler.types.dynamicType; |
+ DartType computeType(Compiler compiler) => const DynamicType(); |
bool isCallable(Compiler compiler) => true; |
@@ -151,14 +151,17 @@ class TypeAccess extends ElementAccess { |
* An access of a type literal. |
*/ |
class TypeLiteralAccess extends ElementAccess { |
- final Element element; |
- TypeLiteralAccess(Element this.element) { |
- assert(element != null); |
+ final DartType type; |
+ |
+ TypeLiteralAccess(this.type) { |
+ assert(type != null); |
} |
+ Element get element => type.element; |
+ |
DartType computeType(Compiler compiler) => compiler.typeClass.rawType; |
- String toString() => 'TypeLiteralAccess($element)'; |
+ String toString() => 'TypeLiteralAccess($type)'; |
} |
@@ -349,7 +352,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} |
// TODO(karlklose): remove these functions. |
- DartType unhandledExpression() => types.dynamicType; |
+ DartType unhandledExpression() => const DynamicType(); |
DartType analyzeNonVoid(Node node) { |
DartType type = analyze(node); |
@@ -557,10 +560,10 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
final FunctionElement element = elements[node]; |
assert(invariant(node, element != null, |
message: 'FunctionExpression with no element')); |
- if (Elements.isUnresolved(element)) return types.dynamicType; |
+ if (Elements.isUnresolved(element)) return const DynamicType(); |
if (identical(element.kind, ElementKind.GENERATIVE_CONSTRUCTOR) || |
identical(element.kind, ElementKind.GENERATIVE_CONSTRUCTOR_BODY)) { |
- type = types.dynamicType; |
+ type = const DynamicType(); |
returnType = const VoidType(); |
element.functionSignature.forEachParameter((ParameterElement parameter) { |
@@ -659,8 +662,8 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
type = compiler.objectClass.rawType; |
} |
} |
- if (type.kind == TypeKind.MALFORMED_TYPE) { |
- return types.dynamicType; |
+ if (type.isMalformed) { |
+ return const DynamicType(); |
} |
return type.unalias(compiler); |
} |
@@ -669,10 +672,10 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
// interface type of the bound, for function types and typedefs it is the |
// `Function` type. |
InterfaceType computeInterfaceType(DartType type) { |
- if (type.kind == TypeKind.FUNCTION) { |
+ if (type.isFunctionType) { |
type = compiler.functionClass.rawType; |
} |
- assert(invariant(node, type.kind == TypeKind.INTERFACE, |
+ assert(invariant(node, type.isInterfaceType, |
message: "unexpected type kind ${type.kind}.")); |
return type; |
} |
@@ -690,15 +693,12 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
// 'call' method into account. |
ElementAccess getAccess(Name name, |
DartType unaliasedBound, InterfaceType interface) { |
- if (interface.treatAsDynamic) { |
- return new DynamicAccess(); |
- } |
MemberSignature member = lookupMemberSignature(memberName, interface); |
if (member != null) { |
return new MemberAccess(member); |
} |
if (name == const PublicName('call')) { |
- if (unaliasedBound.kind == TypeKind.FUNCTION) { |
+ if (unaliasedBound.isFunctionType) { |
// This is an access the implicit 'call' method of a function type. |
return new FunctionCallAccess(receiverElement, unaliasedBound); |
} |
@@ -706,13 +706,16 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
// This is an access of the special 'call' method implicitly defined |
// on 'Function'. This method can be called with any arguments, which |
// we ensure by giving it the type 'dynamic'. |
- return new FunctionCallAccess(null, types.dynamicType); |
+ return new FunctionCallAccess(null, const DynamicType()); |
} |
} |
return null; |
} |
DartType unaliasedBound = computeUnaliasedBound(receiverType); |
+ if (unaliasedBound.treatAsDynamic) { |
+ return new DynamicAccess(); |
+ } |
InterfaceType interface = computeInterfaceType(unaliasedBound); |
ElementAccess access = getAccess(memberName, unaliasedBound, interface); |
if (access != null) { |
@@ -726,9 +729,11 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
TypePromotion typePromotion = typePromotions.head; |
if (!typePromotion.isValid) { |
DartType unaliasedBound = computeUnaliasedBound(typePromotion.type); |
- InterfaceType interface = computeInterfaceType(unaliasedBound); |
- if (getAccess(memberName, unaliasedBound, interface) != null) { |
- reportTypePromotionHint(typePromotion); |
+ if (!unaliasedBound.treatAsDynamic) { |
+ InterfaceType interface = computeInterfaceType(unaliasedBound); |
+ if (getAccess(memberName, unaliasedBound, interface) != null) { |
+ reportTypePromotionHint(typePromotion); |
+ } |
} |
} |
typePromotions = typePromotions.tail; |
@@ -902,7 +907,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} else { |
reportTypeWarning(node, MessageKind.NOT_CALLABLE, |
{'elementName': elementAccess.element.name}); |
- analyzeArguments(node, elementAccess.element, types.dynamicType, |
+ analyzeArguments(node, elementAccess.element, const DynamicType(), |
argumentTypes); |
} |
type = type.unalias(compiler); |
@@ -910,7 +915,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
FunctionType funType = type; |
return funType.returnType; |
} else { |
- return types.dynamicType; |
+ return const DynamicType(); |
} |
} |
@@ -964,11 +969,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} else if (element.impliesType) { |
// The literal `Foo` where Foo is a class, a typedef, or a type variable. |
if (elements.isTypeLiteral(node)) { |
- assert(invariant(node, identical(compiler.typeClass, |
- elements.getType(node).element), |
- message: 'Expected type literal type: ' |
- '${elements.getType(node)}')); |
- return new TypeLiteralAccess(element); |
+ return new TypeLiteralAccess(elements.getTypeLiteralType(node)); |
} |
return createResolvedAccess(node, name, element); |
} else if (element.isMember) { |
@@ -1030,8 +1031,8 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
/// we suggest the use of `List<int>`, which would make promotion valid. |
DartType computeMoreSpecificType(DartType shownType, |
DartType knownType) { |
- if (knownType.kind == TypeKind.INTERFACE && |
- shownType.kind == TypeKind.INTERFACE && |
+ if (knownType.isInterfaceType && |
+ shownType.isInterfaceType && |
types.isSubtype(shownType.asRaw(), knownType)) { |
// For the comments in the block, assume the hierarchy: |
// class A<T, V> {} |
@@ -1075,7 +1076,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} |
DartType constructorType = computeConstructorType(element, receiverType); |
analyzeArguments(node, element, constructorType); |
- return types.dynamicType; |
+ return const DynamicType(); |
} |
if (Elements.isClosureSend(node, element)) { |
@@ -1235,7 +1236,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
/// Returns the first type in the list or [:dynamic:] if the list is empty. |
DartType firstType(Link<DartType> link) { |
- return link.isEmpty ? types.dynamicType : link.head; |
+ return link.isEmpty ? const DynamicType() : link.head; |
} |
/** |
@@ -1244,7 +1245,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
*/ |
DartType secondType(Link<DartType> link) { |
return link.isEmpty || link.tail.isEmpty |
- ? types.dynamicType : link.tail.head; |
+ ? const DynamicType() : link.tail.head; |
} |
/** |
@@ -1280,7 +1281,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} |
return node.isPostfix ? getter : result; |
} |
- return types.dynamicType; |
+ return const DynamicType(); |
} |
/** |
@@ -1342,7 +1343,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
return node.isPostfix ? element : result; |
} |
} |
- return types.dynamicType; |
+ return const DynamicType(); |
} |
visitSendSet(SendSet node) { |
@@ -1455,7 +1456,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} |
DartType visitLiteralNull(LiteralNull node) { |
- return types.dynamicType; |
+ return const DynamicType(); |
} |
DartType visitLiteralSymbol(LiteralSymbol node) { |
@@ -1463,7 +1464,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} |
DartType computeConstructorType(Element constructor, DartType type) { |
- if (Elements.isUnresolved(constructor)) return types.dynamicType; |
+ if (Elements.isUnresolved(constructor)) return const DynamicType(); |
DartType constructorType = constructor.computeType(compiler); |
if (identical(type.kind, TypeKind.INTERFACE)) { |
if (constructor.isSynthesized) { |
@@ -1485,7 +1486,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
DartType visitNewExpression(NewExpression node) { |
Element element = elements[node.send]; |
- if (Elements.isUnresolved(element)) return types.dynamicType; |
+ if (Elements.isUnresolved(element)) return const DynamicType(); |
checkPrivateAccess(node, element, element.name); |
@@ -1579,7 +1580,7 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
DartType visitThrow(Throw node) { |
// TODO(johnniwinther): Handle reachability. |
analyze(node.expression); |
- return types.dynamicType; |
+ return const DynamicType(); |
} |
DartType visitTypeAnnotation(TypeAnnotation node) { |
@@ -1587,10 +1588,10 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
} |
DartType visitVariableDefinitions(VariableDefinitions node) { |
- DartType type = analyzeWithDefault(node.type, types.dynamicType); |
+ DartType type = analyzeWithDefault(node.type, const DynamicType()); |
if (type.isVoid) { |
reportTypeWarning(node.type, MessageKind.VOID_VARIABLE); |
- type = types.dynamicType; |
+ type = const DynamicType(); |
} |
for (Link<Node> link = node.definitions.nodes; !link.isEmpty; |
link = link.tail) { |