Index: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (revision 22743) |
+++ sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (working copy) |
@@ -113,6 +113,10 @@ |
throw 'Unsupported operation'; |
} |
+ TypeMask intersection(TypeMask other, Compiler compiler) { |
+ return other; |
+ } |
+ |
bool get isNullable => true; |
String toString() => '$name sentinel type mask'; |
@@ -649,6 +653,15 @@ |
bool internalRecordType(Element analyzedElement, |
TypeMask newType, |
Map<Element, TypeMask> types) { |
+ if (compiler.trustTypeAnnotations) { |
+ var annotation = analyzedElement.computeType(compiler); |
+ if (types == returnTypeOf) { |
+ assert(annotation is FunctionType); |
+ annotation = annotation.returnType; |
+ } |
+ newType = narrowType(newType, annotation); |
+ } |
+ |
// Fields and native methods of native classes are handled |
// specially when querying for their type or return type. |
if (isNativeElement(analyzedElement)) return false; |
@@ -684,7 +697,15 @@ |
} |
TypeMask returnType = returnTypeOf[element]; |
if (returnType == null) { |
- return dynamicType; |
+ if (compiler.trustTypeAnnotations |
+ && (element.isFunction() |
+ || element.isGetter() |
+ || element.isFactoryConstructor())) { |
+ returnType = narrowType( |
kasperl
2013/05/16 13:17:20
Couldn't you do the narrowing when you record? (li
ngeoffray
2013/05/17 14:34:25
This is in case the element has not been analyzed
|
+ dynamicType, element.computeType(compiler).returnType); |
+ } else { |
+ returnType = dynamicType; |
+ } |
} |
assert(returnType != null); |
return returnType; |
@@ -749,7 +770,13 @@ |
} |
TypeMask type = typeOf[element]; |
if (type == null) { |
- return dynamicType; |
+ if (compiler.trustTypeAnnotations |
+ && (element.isField() |
+ || element.isParameter())) { |
+ type = narrowType(dynamicType, element.computeType(compiler)); |
+ } else { |
+ type = dynamicType; |
+ } |
} |
assert(type != null); |
return type; |
@@ -1246,6 +1273,20 @@ |
return union.containsAll(compiler) ? dynamicType : union; |
} |
} |
+ |
+ TypeMask narrowType(TypeMask type, DartType annotation) { |
+ if (annotation.isDynamic) return type; |
+ TypeMask otherType; |
+ if (annotation.kind == TypeKind.TYPEDEF |
+ || annotation.kind == TypeKind.FUNCTION) { |
+ otherType = functionType.nullable(); |
+ } else if (annotation.kind != TypeKind.INTERFACE) { |
+ return type; |
+ } else { |
+ otherType = new TypeMask.subtype(annotation); |
+ } |
+ return type.intersection(otherType, compiler); |
+ } |
} |
/** |
@@ -2028,14 +2069,7 @@ |
} else if (const SourceString("as") == op.source) { |
TypeMask receiverType = visit(node.receiver); |
DartType type = elements.getType(node.arguments.head); |
- if (type.isDynamic) return receiverType; |
- TypeMask asType = type.kind == TypeKind.TYPEDEF |
- ? inferrer.functionType.nullable() |
- : new TypeMask.subtype(type); |
- // TODO(ngeoffray): Remove when inferrer.dynamicType is a proper |
- // TypeMask. |
- if (inferrer.isDynamicType(receiverType)) return asType; |
- return receiverType.intersection(asType, compiler); |
+ return inferrer.narrowType(receiverType, type); |
} else if (node.isParameterCheck) { |
node.visitChildren(this); |
return inferrer.boolType; |