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 3ce9ce8cb01a8e32c88b782d6854e7ce678fe7fd..f2c738f6f8709560e5790d6d3656313f58cfb0d4 100644 |
--- a/pkg/analyzer/lib/src/summary/link.dart |
+++ b/pkg/analyzer/lib/src/summary/link.dart |
@@ -1972,13 +1972,12 @@ abstract class ExecutableElementForLink_NonLocal |
} |
class ExprTypeComputer { |
- VariableElementForLink variable; |
- FunctionElementForLink_Initializer initializer; |
- CompilationUnitElementForLink unit; |
- LibraryElementForLink library; |
- Linker linker; |
- TypeProvider typeProvider; |
- UnlinkedConst unlinkedConst; |
+ final FunctionElementForLink_Local function; |
+ final CompilationUnitElementForLink unit; |
+ final LibraryElementForLink library; |
+ final Linker linker; |
+ final TypeProvider typeProvider; |
+ final UnlinkedConst unlinkedConst; |
final List<DartType> stack = <DartType>[]; |
int intPtr = 0; |
@@ -1986,17 +1985,25 @@ class ExprTypeComputer { |
int strPtr = 0; |
int assignmentOperatorPtr = 0; |
- ExprTypeComputer(VariableElementForLink variableElement) { |
- this.variable = variableElement; |
- initializer = variableElement.initializer; |
- unit = variableElement.compilationUnit; |
- library = unit.enclosingElement; |
- linker = library._linker; |
- typeProvider = linker.typeProvider; |
- unlinkedConst = variableElement.unlinkedVariable.initializer?.bodyExpr; |
+ factory ExprTypeComputer(FunctionElementForLink_Local functionElement) { |
+ CompilationUnitElementForLink unit = functionElement.compilationUnit; |
+ LibraryElementForLink library = unit.enclosingElement; |
+ Linker linker = library._linker; |
+ TypeProvider typeProvider = linker.typeProvider; |
+ UnlinkedConst unlinkedConst = functionElement._unlinkedExecutable.bodyExpr; |
+ return new ExprTypeComputer._( |
+ functionElement, unit, library, linker, typeProvider, unlinkedConst); |
} |
+ ExprTypeComputer._(this.function, this.unit, this.library, this.linker, |
+ this.typeProvider, this.unlinkedConst); |
+ |
DartType compute() { |
+ if (unlinkedConst == null) { |
+ // No function body was stored for this function, so we can't infer its |
+ // return type. Assume `dynamic`. |
+ return DynamicTypeImpl.instance; |
+ } |
// Perform RPN evaluation of the constant, using a stack of inferred types. |
for (UnlinkedConstOperation operation in unlinkedConst.operations) { |
switch (operation) { |
@@ -2158,7 +2165,7 @@ class ExprTypeComputer { |
case UnlinkedConstOperation.pushLocalFunctionReference: |
int popCount = _getNextInt(); |
assert(popCount == 0); // TODO(paulberry): handle the nonzero case. |
- stack.add(initializer.functions[_getNextInt()].type); |
+ stack.add(function.functions[_getNextInt()].type); |
break; |
default: |
// TODO(paulberry): implement. |
@@ -2315,7 +2322,7 @@ class ExprTypeComputer { |
// Type argument explicitly specified. |
if (i < ref.typeArguments.length) { |
return unit.resolveTypeRef( |
- ref.typeArguments[i], variable._typeParameterContext); |
+ ref.typeArguments[i], function.typeParameterContext); |
} else { |
return null; |
} |
@@ -2448,7 +2455,7 @@ class ExprTypeComputer { |
DartType _getNextTypeRef() { |
EntityRef ref = _getNextRef(); |
- return unit.resolveTypeRef(ref, variable._typeParameterContext); |
+ return unit.resolveTypeRef(ref, function.typeParameterContext); |
} |
/** |
@@ -2758,7 +2765,7 @@ class FunctionElementForLink_FunctionTypedParam extends Object |
* Element representing the initializer expression of a variable. |
*/ |
class FunctionElementForLink_Initializer extends Object |
- with ReferenceableElementForLink |
+ with ReferenceableElementForLink, TypeParameterizedElementMixin |
implements FunctionElementForLink_Local { |
/** |
* The variable for which this element is the initializer. |
@@ -2770,6 +2777,10 @@ class FunctionElementForLink_Initializer extends Object |
FunctionElementForLink_Initializer(this._variable); |
@override |
+ CompilationUnitElementForLink get compilationUnit => |
+ _variable.compilationUnit; |
+ |
+ @override |
VariableElementForLink get enclosingElement => _variable; |
TypeParameterizedElementMixin get enclosingTypeParameterContext => |
@@ -2778,6 +2789,9 @@ class FunctionElementForLink_Initializer extends Object |
: null; |
@override |
+ CompilationUnitElementForLink get enclosingUnit => _variable.compilationUnit; |
+ |
+ @override |
List<FunctionElementForLink_Local_NonSynthetic> get functions => |
_functions ??= _variable.unlinkedVariable.initializer.localFunctions |
.map((UnlinkedExecutable ex) => |
@@ -2807,10 +2821,17 @@ class FunctionElementForLink_Initializer extends Object |
} |
@override |
- int get typeParameterNestingLevel => |
- enclosingTypeParameterContext?.typeParameterNestingLevel ?? 0; |
+ TypeParameterizedElementMixin get typeParameterContext => this; |
- List<TypeParameterElement> get typeParameters => const []; |
+ @override |
+ List<UnlinkedTypeParam> get unlinkedTypeParams => const []; |
+ |
+ @override |
+ bool get _hasTypeBeenInferred => _variable._inferredType != null; |
+ |
+ @override |
+ UnlinkedExecutable get _unlinkedExecutable => |
+ _variable.unlinkedVariable.initializer; |
@override |
FunctionElementForLink_Local getLocalFunction(int index) { |
@@ -2820,6 +2841,12 @@ class FunctionElementForLink_Initializer extends Object |
@override |
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
+ |
+ @override |
+ void _setInferredType(DartType type) { |
+ assert(!_hasTypeBeenInferred); |
+ _variable._inferredType = type; |
+ } |
} |
/** |
@@ -2829,7 +2856,18 @@ abstract class FunctionElementForLink_Local |
implements |
ExecutableElementForLink, |
FunctionElementImpl, |
- ReferenceableElementForLink {} |
+ ReferenceableElementForLink { |
+ /** |
+ * Indicates whether type inference has completed for this function. |
+ */ |
+ bool get _hasTypeBeenInferred; |
+ |
+ /** |
+ * Stores the given [type] as the inferred return type for this function. |
+ * Should only be called if [_hasTypeBeenInferred] is `false`. |
+ */ |
+ void _setInferredType(DartType type); |
+} |
/** |
* Element representing a local function (possibly a closure) inside another |
@@ -2852,6 +2890,12 @@ class FunctionElementForLink_Local_NonSynthetic extends ExecutableElementForLink |
enclosingElement; |
@override |
+ bool get _hasTypeBeenInferred { |
+ // TODO(paulberry): add logic to infer types of nonsynthetic functions. |
+ return true; |
+ } |
+ |
+ @override |
DartType buildType( |
DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) { |
assert(implicitFunctionTypeIndices.isEmpty); |
@@ -2866,6 +2910,12 @@ class FunctionElementForLink_Local_NonSynthetic extends ExecutableElementForLink |
@override |
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
+ |
+ @override |
+ void _setInferredType(DartType type) { |
+ // TODO(paulberry): add logic to infer types of nonsynthetic functions. |
+ throw new UnimplementedError(); |
+ } |
} |
/** |
@@ -4319,15 +4369,14 @@ class TypeInferenceDependencyWalker |
*/ |
class TypeInferenceNode extends Node<TypeInferenceNode> { |
/** |
- * The [FieldElement] or [TopLevelVariableElement] to which this |
- * node refers. |
+ * The [FunctionElementForLink_Local] to which this node refers. |
*/ |
- final VariableElementForLink variableElement; |
+ final FunctionElementForLink_Local functionElement; |
- TypeInferenceNode(this.variableElement); |
+ TypeInferenceNode(this.functionElement); |
@override |
- bool get isEvaluated => variableElement._inferredType != null; |
+ bool get isEvaluated => functionElement._hasTypeBeenInferred; |
/** |
* Collect the type inference dependencies in [unlinkedExecutable] (which |
@@ -4420,24 +4469,22 @@ class TypeInferenceNode extends Node<TypeInferenceNode> { |
@override |
List<TypeInferenceNode> computeDependencies() { |
List<TypeInferenceNode> dependencies = <TypeInferenceNode>[]; |
- collectDependencies( |
- dependencies, |
- variableElement.unlinkedVariable.initializer, |
- variableElement.compilationUnit); |
+ collectDependencies(dependencies, functionElement._unlinkedExecutable, |
+ functionElement.compilationUnit); |
return dependencies; |
} |
void evaluate(bool inCycle) { |
if (inCycle) { |
- variableElement._inferredType = DynamicTypeImpl.instance; |
+ functionElement._setInferredType(DynamicTypeImpl.instance); |
} else { |
- variableElement._inferredType = |
- new ExprTypeComputer(variableElement).compute(); |
+ functionElement |
+ ._setInferredType(new ExprTypeComputer(functionElement).compute()); |
} |
} |
@override |
- String toString() => 'TypeInferenceNode($variableElement)'; |
+ String toString() => 'TypeInferenceNode($functionElement)'; |
} |
class TypeProviderForLink implements TypeProvider { |
@@ -4640,7 +4687,7 @@ abstract class VariableElementForLink |
unlinkedVariable.initializer?.bodyExpr != null) { |
_constNode = new ConstVariableNode(this); |
if (unlinkedVariable.type == null) { |
- _typeInferenceNode = new TypeInferenceNode(this); |
+ _typeInferenceNode = new TypeInferenceNode(initializer); |
} |
} |
} |