Index: sdk/lib/_internal/compiler/implementation/elements/elements.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart |
index df07e95ef89fddb49fd694ded8c548b74f16c6fb..b77dd98b1ae6fec89b8a6eafa31804db3ee845ee 100644 |
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart |
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart |
@@ -838,6 +838,19 @@ class PrefixElement extends Element { |
class TypedefElement extends Element implements TypeDeclarationElement { |
Typedef cachedNode; |
TypedefType cachedType; |
+ |
+ /** |
+ * Canonicalize raw version of [cachedType]. |
+ * |
+ * See [ClassElement.rawType] for motivation. |
+ * |
+ * The [rawType] is computed together with [cachedType] in [computeType]. |
+ */ |
+ TypedefType rawType; |
+ |
+ /** |
+ * The type annotation which defines this typedef. |
+ */ |
DartType alias; |
bool isResolved = false; |
@@ -862,6 +875,16 @@ class TypedefElement extends Element implements TypeDeclarationElement { |
Link<DartType> parameters = |
TypeDeclarationElement.createTypeVariables(this, node.typeParameters); |
cachedType = new TypedefType(this, parameters); |
+ if (parameters.isEmpty) { |
+ rawType = cachedType; |
+ } else { |
+ var dynamicParameters = const Link<DartType>(); |
+ parameters.forEach((_) { |
+ dynamicParameters = |
+ dynamicParameters.prepend(compiler.types.dynamicType); |
+ }); |
+ rawType = new TypedefType(this, dynamicParameters); |
+ } |
compiler.resolveTypedef(this); |
return cachedType; |
} |
@@ -1383,7 +1406,36 @@ abstract class TypeDeclarationElement implements Element { |
abstract class ClassElement extends ScopeContainerElement |
implements TypeDeclarationElement { |
final int id; |
- InterfaceType type; |
+ /** |
+ * The type of [:this:] for this class declaration. |
+ * |
+ * The type of [:this:] is the interface type based on this element in which |
+ * the type arguments are the declared type variables. For instance, |
+ * [:List<E>:] for [:List:] and [:Map<K,V>:] for [:Map:]. |
+ * |
+ * This type is computed in [computeType]. |
+ */ |
+ InterfaceType thisType; |
+ |
+ /** |
+ * The raw type for this class declaration. |
+ * |
+ * The raw type is the interface type base on this element in which the type |
+ * arguments are all [dynamic]. For instance [:List<dynamic>:] for [:List:] |
+ * and [:Map<dynamic,dynamic>:] for [:Map:]. For non-generic classes [rawType] |
+ * is the same as [thisType]. |
+ * |
+ * The [rawType] field is a canonicalization of the raw type and should be |
+ * used to distinguish explicit and implicit uses of the [dynamic] |
+ * type arguments. For instance should [:List:] be the [rawType] of the |
+ * [:List:] class element whereas [:List<dynamic>:] should be its own |
+ * instantiation of [InterfaceType] with [:dynamic:] as type argument. Using |
+ * this distinction, we can print the raw type with type arguments only when |
+ * the input source has used explicit type arguments. |
+ * |
+ * This type is computed together with [thisType] in [computeType]. |
+ */ |
+ InterfaceType rawType; |
DartType supertype; |
DartType defaultClass; |
Link<DartType> interfaces; |
@@ -1409,18 +1461,29 @@ abstract class ClassElement extends ScopeContainerElement |
ClassNode parseNode(Compiler compiler); |
InterfaceType computeType(compiler) { |
- if (type == null) { |
+ if (thisType == null) { |
if (origin == null) { |
ClassNode node = parseNode(compiler); |
Link<DartType> parameters = |
TypeDeclarationElement.createTypeVariables(this, |
node.typeParameters); |
- type = new InterfaceType(this, parameters); |
+ thisType = new InterfaceType(this, parameters); |
+ if (parameters.isEmpty) { |
+ rawType = thisType; |
+ } else { |
+ var dynamicParameters = const Link<DartType>(); |
+ parameters.forEach((_) { |
+ dynamicParameters = |
+ dynamicParameters.prepend(compiler.types.dynamicType); |
+ }); |
+ rawType = new InterfaceType(this, dynamicParameters); |
+ } |
} else { |
- type = origin.computeType(compiler); |
+ thisType = origin.computeType(compiler); |
+ rawType = origin.rawType; |
} |
} |
- return type; |
+ return thisType; |
} |
bool get isPatched => patch != null; |
@@ -1435,7 +1498,7 @@ abstract class ClassElement extends ScopeContainerElement |
bool isObject(Compiler compiler) => |
identical(declaration, compiler.objectClass); |
- Link<DartType> get typeVariables => type.typeArguments; |
+ Link<DartType> get typeVariables => thisType.typeArguments; |
ClassElement ensureResolved(Compiler compiler) { |
if (resolutionState == STATE_NOT_STARTED) { |
@@ -1729,10 +1792,6 @@ abstract class ClassElement extends ScopeContainerElement |
Scope buildScope() => new ClassScope(enclosingElement.buildScope(), this); |
- Link<DartType> get allSupertypesAndSelf { |
- return allSupertypes.prepend(new InterfaceType(this)); |
- } |
- |
String toString() { |
if (origin != null) { |
return 'patch ${super.toString()}'; |