Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Unified Diff: pkg/analyzer/lib/src/summary/link.dart

Issue 1850673004: Add support for type inference involving generics. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/summary/link.dart
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index ad9fb88861e6a1a1bd705dd7a89b88da335505b2..a898d6cd776246bcc9d9dcb131075c67c37358a3 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -128,23 +128,47 @@ void relink(Map<String, LinkedLibraryBuilder> libraries,
* is stored in [EntityRefBuilder.slot].
*/
EntityRefBuilder _createLinkedType(
- DartType type, CompilationUnitElementInBuildUnit compilationUnit,
+ DartType type,
+ CompilationUnitElementInBuildUnit compilationUnit,
+ TypeParameterContext typeParameterContext,
{int slot}) {
EntityRefBuilder result = new EntityRefBuilder(slot: slot);
if (type is InterfaceType) {
ClassElementForLink element = type.element;
- int dependency = compilationUnit.library.addDependency(element.library);
- result.reference = compilationUnit.addReference(dependency, element.name,
- element.typeParameters.length, element.enclosingElement.unitNum);
- if (element.typeParameters.isNotEmpty) {
- // TODO(paulberry): implement.
- throw new UnimplementedError();
+ result.reference = compilationUnit.addReference(element);
+ if (type.typeArguments.isNotEmpty) {
+ result.typeArguments = type.typeArguments
+ .map((DartType t) =>
+ _createLinkedType(t, compilationUnit, typeParameterContext))
+ .toList();
}
return result;
} else if (type is VoidTypeImpl) {
- result.reference = compilationUnit.addReference(0, 'void', 0, 0);
+ result.reference = compilationUnit.addRawReference('void');
+ return result;
+ } else if (type is TypeParameterType) {
+ TypeParameterElementForLink element = type.element;
+ result.paramReference =
+ typeParameterContext.typeParameterNestingLevel - element.nestingLevel;
return result;
+ } else if (type is FunctionType) {
+ Element element = type.element;
+ if (element is FunctionElementForLink_FunctionTypedParam) {
+ result.reference =
+ compilationUnit.addReference(element.enclosingExecutable);
+ result.implicitFunctionTypeIndices = element.implicitFunctionTypeIndices;
+ if (type.typeArguments.isNotEmpty) {
+ result.typeArguments = type.typeArguments
+ .map((DartType t) =>
+ _createLinkedType(t, compilationUnit, typeParameterContext))
+ .toList();
+ }
+ return result;
+ }
+ // TODO(paulberry): implement other cases.
+ throw new UnimplementedError('${element.runtimeType}');
}
+ // TODO(paulberry): implement other cases.
throw new UnimplementedError('${type.runtimeType}');
}
@@ -376,6 +400,10 @@ class ClassElementForLink_Class extends ClassElementForLink
}
@override
+ DartType get type =>
+ _type ??= buildType((int i) => typeParameterTypes[i], null);
+
+ @override
ConstructorElementForLink get unnamedConstructor {
if (!_unnamedConstructorComputed) {
for (ConstructorElementForLink constructor in constructors) {
@@ -398,17 +426,14 @@ class ClassElementForLink_Class extends ClassElementForLink
DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
int numTypeParameters = _unlinkedClass.typeParameters.length;
if (numTypeParameters != 0) {
- return new InterfaceTypeImpl(this);
- } else {
- if (_type == null) {
- List<DartType> typeArguments = new List<DartType>(numTypeParameters);
- for (int i = 0; i < numTypeParameters; i++) {
- typeArguments[i] = getTypeArgument(i);
- }
- _type = new InterfaceTypeImpl.elementWithNameAndArgs(
- this, name, typeArguments);
+ List<DartType> typeArguments = new List<DartType>(numTypeParameters);
+ for (int i = 0; i < numTypeParameters; i++) {
+ typeArguments[i] = getTypeArgument(i);
}
- return _type;
+ return new InterfaceTypeImpl.elementWithNameAndArgs(
+ this, name, typeArguments);
+ } else {
+ return _type ??= new InterfaceTypeImpl(this);
}
}
@@ -431,6 +456,9 @@ class ClassElementForLink_Class extends ClassElementForLink
@override
void unlink() {
hasBeenInferred = false;
+ for (ConstructorElementForLink constructorElement in constructors) {
+ constructorElement.unlink();
+ }
for (MethodElementForLink methodElement in methods) {
methodElement.unlink();
}
@@ -732,11 +760,16 @@ class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink {
/**
* If this compilation unit already has a reference in its references table
- * matching [dependency], [name], [numTypeParameters], and [unitNum], return
- * its index. Otherwise add a new reference to table and return its index.
- */
- int addReference(
- int dependency, String name, int numTypeParameters, int unitNum) {
+ * matching [dependency], [name], [numTypeParameters], [unitNum],
+ * [containingReference], and [kind], return its index. Otherwise add a new reference to
+ * the table and return its index.
+ */
+ int addRawReference(String name,
+ {int dependency: 0,
+ int numTypeParameters: 0,
+ int unitNum: 0,
+ int containingReference: 0,
+ ReferenceKind kind: ReferenceKind.classOrEnum}) {
List<LinkedReferenceBuilder> linkedReferences = _linkedUnit.references;
List<UnlinkedReference> unlinkedReferences = _unlinkedUnit.references;
for (int i = 0; i < linkedReferences.length; i++) {
@@ -747,7 +780,12 @@ class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink {
: linkedReference.name) ==
name &&
linkedReference.numTypeParameters == numTypeParameters &&
- linkedReference.unit == unitNum) {
+ linkedReference.unit == unitNum &&
+ (i < unlinkedReferences.length
+ ? unlinkedReferences[i].prefixReference
+ : linkedReference.containingReference) ==
+ containingReference &&
+ linkedReference.kind == kind) {
return i;
}
}
@@ -756,11 +794,49 @@ class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink {
dependency: dependency,
name: name,
numTypeParameters: numTypeParameters,
- unit: unitNum));
+ unit: unitNum,
+ containingReference: containingReference,
+ kind: kind));
return result;
}
/**
+ * If this compilation unit already has a reference in its references table
+ * to [element], return its index. Otherwise add a new reference to the table
+ * and return its index.
+ */
+ int addReference(Element element) {
+ if (element is ClassElementForLink) {
+ return addRawReference(element.name,
+ dependency: library.addDependency(element.library),
+ numTypeParameters: element.typeParameters.length,
+ unitNum: element.enclosingElement.unitNum);
+ } else if (element is ExecutableElementForLink) {
+ // TODO(paulberry): will this code ever be executed for an executable
+ // element that's not inside a class?
+ assert(element.enclosingElement is ClassElementForLink_Class);
+ ReferenceKind kind;
+ switch (element._unlinkedExecutable.kind) {
+ case UnlinkedExecutableKind.functionOrMethod:
+ kind = ReferenceKind.method;
+ break;
+ case UnlinkedExecutableKind.setter:
+ kind = ReferenceKind.propertyAccessor;
+ break;
+ default:
+ // TODO(paulberry): implement other cases as necessary
+ throw new UnimplementedError('${element._unlinkedExecutable.kind}');
+ }
+ return addRawReference(element.name,
+ numTypeParameters: element.typeParameters.length,
+ containingReference: addReference(element.enclosingElement),
+ kind: kind);
+ }
+ // TODO(paulberry): implement other cases
+ throw new UnimplementedError('${element.runtimeType}');
+ }
+
+ /**
* Perform type inference and const cycle detection on this
* compilation unit.
*/
@@ -799,10 +875,13 @@ class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink {
* Store the given [linkedType] in the given [slot] of the this compilation
* unit's linked type list.
*/
- void _storeLinkedType(int slot, DartType linkedType) {
+ void _storeLinkedType(int slot, DartType linkedType,
+ TypeParameterContext typeParameterContext) {
if (slot != 0) {
if (linkedType != null && !linkedType.isDynamic) {
- _linkedUnit.types.add(_createLinkedType(linkedType, this, slot: slot));
+ _linkedUnit.types.add(_createLinkedType(
+ linkedType, this, typeParameterContext,
+ slot: slot));
}
}
}
@@ -1050,26 +1129,18 @@ class ConstParameterNode extends ConstNode {
* Element representing a constructor resynthesized from a summary
* during linking.
*/
-class ConstructorElementForLink
+class ConstructorElementForLink extends ExecutableElementForLink
implements ConstructorElementImpl, ReferenceableElementForLink {
/**
- * The unlinked representation of the constructor in the summary.
- */
- final UnlinkedExecutable _unlinkedExecutable;
-
- /**
* If this is a `const` constructor and the enclosing library is
* part of the build unit being linked, the constructor's node in
* the constant evaluation dependency graph. Otherwise `null`.
*/
ConstConstructorNode _constNode;
- @override
- final ClassElementForLink_Class enclosingElement;
-
- List<ParameterElementForLink> _parameters;
-
- ConstructorElementForLink(this.enclosingElement, this._unlinkedExecutable) {
+ ConstructorElementForLink(ClassElementForLink_Class enclosingElement,
+ UnlinkedExecutable unlinkedExecutable)
+ : super(enclosingElement, unlinkedExecutable) {
if (enclosingElement.enclosingElement.isInBuildUnit &&
_unlinkedExecutable.constCycleSlot != 0) {
_constNode = new ConstConstructorNode(this);
@@ -1091,21 +1162,6 @@ class ConstructorElementForLink
}
@override
- String get name => _unlinkedExecutable.name;
-
- @override
- List<ParameterElementForLink> get parameters {
- if (_parameters == null) {
- _parameters = <ParameterElementForLink>[];
- for (UnlinkedParam unlinkedParam in _unlinkedExecutable.parameters) {
- _parameters.add(new ParameterElementForLink(unlinkedParam,
- enclosingElement, enclosingElement.enclosingElement));
- }
- }
- return _parameters;
- }
-
- @override
DartType buildType(DartType getTypeArgument(int i),
List<int> implicitFunctionTypeIndices) =>
DynamicTypeImpl.instance;
@@ -1121,6 +1177,7 @@ class ConstructorElementForLink
if (_constNode != null && !isCycleFree) {
compilationUnit._storeConstCycle(_unlinkedExecutable.constCycleSlot);
}
+ // TODO(paulberry): call super.
}
@override
@@ -1324,10 +1381,12 @@ abstract class ExecutableElementForLink extends Object
@override
List<ParameterElementForLink> get parameters {
if (_parameters == null) {
- _parameters = <ParameterElementForLink>[];
- for (UnlinkedParam unlinkedParam in _unlinkedExecutable.parameters) {
- _parameters.add(new ParameterElementForLink(
- unlinkedParam, this, enclosingElement.enclosingElement));
+ int numParameters = _unlinkedExecutable.parameters.length;
+ _parameters = new List<ParameterElementForLink>(numParameters);
+ for (int i = 0; i < numParameters; i++) {
+ UnlinkedParam unlinkedParam = _unlinkedExecutable.parameters[i];
+ _parameters[i] = new ParameterElementForLink(
+ this, unlinkedParam, this, enclosingElement.enclosingElement, i);
}
}
return _parameters;
@@ -1339,10 +1398,13 @@ abstract class ExecutableElementForLink extends Object
return _inferredReturnType;
} else if (_declaredReturnType == null) {
if (_unlinkedExecutable.returnType == null) {
- // In strong mode, setters without an explicit return type are
- // considered to return `void`.
- if (_unlinkedExecutable.kind == UnlinkedExecutableKind.setter &&
+ if (_unlinkedExecutable.kind == UnlinkedExecutableKind.constructor) {
+ // TODO(paulberry): implement.
+ throw new UnimplementedError();
+ } else if (_unlinkedExecutable.kind == UnlinkedExecutableKind.setter &&
library._linker.strongMode) {
+ // In strong mode, setters without an explicit return type are
+ // considered to return `void`.
_declaredReturnType = VoidTypeImpl.instance;
} else {
_declaredReturnType = DynamicTypeImpl.instance;
@@ -1365,14 +1427,8 @@ abstract class ExecutableElementForLink extends Object
FunctionTypeImpl get type => _type ??= new FunctionTypeImpl(this);
@override
- List<TypeParameterElementForLink> get typeParameters {
- if (_typeParameters == null) {
- _typeParameters = _unlinkedExecutable.typeParameters
- .map((UnlinkedTypeParam p) => new TypeParameterElementForLink(p))
- .toList();
- }
- return _typeParameters;
- }
+ List<UnlinkedTypeParam> get _unlinkedTypeParams =>
+ _unlinkedExecutable.typeParameters;
@override
bool isAccessibleIn(LibraryElement library) =>
@@ -1383,7 +1439,7 @@ abstract class ExecutableElementForLink extends Object
*/
void link(CompilationUnitElementInBuildUnit compilationUnit) {
compilationUnit._storeLinkedType(
- _unlinkedExecutable.inferredReturnTypeSlot, returnType);
+ _unlinkedExecutable.inferredReturnTypeSlot, returnType, this);
for (ParameterElementForLink parameterElement in parameters) {
parameterElement.link(compilationUnit);
}
@@ -1453,7 +1509,7 @@ class FieldElementForLink_ClassField extends VariableElementForLink
*/
void link(CompilationUnitElementInBuildUnit compilationUnit) {
compilationUnit._storeLinkedType(
- unlinkedVariable.inferredTypeSlot, _inferredType);
+ unlinkedVariable.inferredTypeSlot, _inferredType, enclosingElement);
}
/**
@@ -1511,6 +1567,52 @@ class FieldElementForLink_EnumField extends FieldElementForLink
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
+/**
+ * Element representing a function-typed parameter resynthesied from a summary
+ * during linking.
+ */
+class FunctionElementForLink_FunctionTypedParam implements FunctionElement {
+ @override
+ final ParameterElementForLink enclosingElement;
+
+ /**
+ * The executable element containing this function-typed parameter.
+ */
+ final Element enclosingExecutable;
+
+ /**
+ * The appropriate integer list to store in
+ * [EntityRef.implicitFunctionTypeIndices] to refer to this function-typed
+ * parameter.
+ */
+ final List<int> implicitFunctionTypeIndices;
+
+ DartType _returnType;
+
+ FunctionElementForLink_FunctionTypedParam(this.enclosingElement,
+ this.enclosingExecutable, this.implicitFunctionTypeIndices);
+
+ @override
+ DartType get returnType {
+ if (_returnType == null) {
+ if (enclosingElement._unlinkedParam.type == null) {
+ _returnType = DynamicTypeImpl.instance;
+ } else {
+ _returnType = enclosingElement.compilationUnit._resolveTypeRef(
+ enclosingElement._unlinkedParam.type,
+ enclosingElement._typeParameterContext);
+ }
+ }
+ return _returnType;
+ }
+
+ @override
+ List<TypeParameterElement> get typeParameters => const [];
+
+ @override
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
class FunctionElementForLink_Initializer implements FunctionElementImpl {
@override
DartType get returnType {
@@ -1822,11 +1924,19 @@ class ParameterElementForLink implements ParameterElementImpl {
*/
final CompilationUnitElementForLink compilationUnit;
+ /**
+ * The index of this parameter within [enclosingElement]'s parameter list.
+ */
+ final int _parameterIndex;
+
+ @override
+ final ExecutableElementForLink enclosingElement;
+
DartType _inferredType;
DartType _declaredType;
- ParameterElementForLink(
- this._unlinkedParam, this._typeParameterContext, this.compilationUnit) {
+ ParameterElementForLink(this.enclosingElement, this._unlinkedParam,
+ this._typeParameterContext, this.compilationUnit, this._parameterIndex) {
if (_unlinkedParam.defaultValue != null) {
_constNode = new ConstParameterNode(this);
}
@@ -1837,6 +1947,9 @@ class ParameterElementForLink implements ParameterElementImpl {
!_unlinkedParam.isFunctionTyped && _unlinkedParam.type == null;
@override
+ String get name => _unlinkedParam.name;
+
+ @override
ParameterKind get parameterKind {
switch (_unlinkedParam.kind) {
case UnlinkedParamKind.required:
@@ -1855,7 +1968,9 @@ class ParameterElementForLink implements ParameterElementImpl {
} else if (_declaredType == null) {
if (_unlinkedParam.isFunctionTyped) {
// TODO(paulberry): implement.
- throw new UnimplementedError();
+ _declaredType = new FunctionTypeImpl(
+ new FunctionElementForLink_FunctionTypedParam(
+ this, enclosingElement, <int>[_parameterIndex]));
} else if (_unlinkedParam.type == null) {
_declaredType = DynamicTypeImpl.instance;
} else {
@@ -1878,7 +1993,7 @@ class ParameterElementForLink implements ParameterElementImpl {
*/
void link(CompilationUnitElementInBuildUnit compilationUnit) {
compilationUnit._storeLinkedType(
- _unlinkedParam.inferredTypeSlot, _inferredType);
+ _unlinkedParam.inferredTypeSlot, _inferredType, _typeParameterContext);
}
@override
@@ -2002,6 +2117,11 @@ class TopLevelVariableElementForLink extends VariableElementForLink
*/
abstract class TypeParameterContext {
/**
+ * Find out how many type parameters are in scope in this context.
+ */
+ int get typeParameterNestingLevel;
+
+ /**
* Convert the given [index] into a type parameter type.
*/
TypeParameterType getTypeParameterType(int index);
@@ -2017,12 +2137,23 @@ class TypeParameterElementForLink implements TypeParameterElement {
*/
final UnlinkedTypeParam _unlinkedTypeParam;
- TypeParameterElementForLink(this._unlinkedTypeParam);
+ /**
+ * The number of type parameters whose scope overlaps this one, and which are
+ * declared earlier in the file.
+ */
+ final int nestingLevel;
+
+ TypeParameterTypeImpl _type;
+
+ TypeParameterElementForLink(this._unlinkedTypeParam, this.nestingLevel);
@override
String get name => _unlinkedTypeParam.name;
@override
+ TypeParameterTypeImpl get type => _type ??= new TypeParameterTypeImpl(this);
+
+ @override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
@@ -2033,17 +2164,29 @@ abstract class TypeParameterizedElementForLink
implements TypeParameterizedElement, TypeParameterContext {
List<TypeParameterType> _typeParameterTypes;
List<TypeParameterElementForLink> _typeParameters;
+ int _nestingLevel;
/**
* Get the type parameter context enclosing this one, if any.
*/
TypeParameterContext get enclosingTypeParameterContext;
+ @override
+ int get typeParameterNestingLevel =>
+ _nestingLevel ??= _unlinkedTypeParams.length +
+ (enclosingTypeParameterContext?.typeParameterNestingLevel ?? 0);
+
List<TypeParameterElementForLink> get typeParameters {
if (_typeParameters == null) {
- _typeParameters = _unlinkedTypeParams
- .map((UnlinkedTypeParam p) => new TypeParameterElementForLink(p))
- .toList();
+ int enclosingNestingLevel =
+ enclosingTypeParameterContext?.typeParameterNestingLevel ?? 0;
+ int numTypeParameters = _unlinkedTypeParams.length;
+ _typeParameters =
+ new List<TypeParameterElementForLink>(numTypeParameters);
+ for (int i = 0; i < numTypeParameters; i++) {
+ _typeParameters[i] = new TypeParameterElementForLink(
+ _unlinkedTypeParams[i], enclosingNestingLevel + i);
+ }
}
return _typeParameters;
}
@@ -2055,7 +2198,7 @@ abstract class TypeParameterizedElementForLink
List<TypeParameterType> get typeParameterTypes {
if (_typeParameterTypes == null) {
_typeParameterTypes = typeParameters
- .map((TypeParameterElementForLink e) => new TypeParameterTypeImpl(e))
+ .map((TypeParameterElementForLink e) => e.type)
.toList();
}
return _typeParameterTypes;
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698