| 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 0945db285db9aa2665e25ad4a065d2e5870baef5..43c41d71a839294f274a2719d711e2709ea7e4b6 100644
|
| --- a/pkg/analyzer/lib/src/summary/link.dart
|
| +++ b/pkg/analyzer/lib/src/summary/link.dart
|
| @@ -1983,6 +1983,8 @@ class ExprTypeComputer {
|
| int strPtr = 0;
|
| int assignmentOperatorPtr = 0;
|
|
|
| + bool hasError = false;
|
| +
|
| factory ExprTypeComputer(FunctionElementForLink_Local functionElement) {
|
| CompilationUnitElementForLink unit = functionElement.compilationUnit;
|
| LibraryElementForLink library = unit.enclosingElement;
|
| @@ -2047,10 +2049,20 @@ class ExprTypeComputer {
|
| stack.add(DynamicTypeImpl.instance);
|
| break;
|
| case UnlinkedExprOperation.pushReference:
|
| - _doPushReference();
|
| + try {
|
| + _doPushReference();
|
| + } on _InferenceFailedError {
|
| + hasError = true;
|
| + return DynamicTypeImpl.instance;
|
| + }
|
| break;
|
| case UnlinkedExprOperation.extractProperty:
|
| - _doExtractProperty();
|
| + try {
|
| + _doExtractProperty();
|
| + } on _InferenceFailedError {
|
| + hasError = true;
|
| + return DynamicTypeImpl.instance;
|
| + }
|
| break;
|
| case UnlinkedExprOperation.invokeConstructor:
|
| _doInvokeConstructor();
|
| @@ -2133,10 +2145,20 @@ class ExprTypeComputer {
|
| _doConditional();
|
| break;
|
| case UnlinkedExprOperation.assignToRef:
|
| - _doAssignToRef();
|
| + try {
|
| + _doAssignToRef();
|
| + } on _InferenceFailedError {
|
| + hasError = true;
|
| + return DynamicTypeImpl.instance;
|
| + }
|
| break;
|
| case UnlinkedExprOperation.assignToProperty:
|
| - _doAssignToProperty();
|
| + try {
|
| + _doAssignToProperty();
|
| + } on _InferenceFailedError {
|
| + hasError = true;
|
| + return DynamicTypeImpl.instance;
|
| + }
|
| break;
|
| case UnlinkedExprOperation.assignToIndex:
|
| _doAssignToIndex();
|
| @@ -2148,7 +2170,12 @@ class ExprTypeComputer {
|
| _doExtractIndex();
|
| break;
|
| case UnlinkedExprOperation.invokeMethodRef:
|
| - _doInvokeMethodRef();
|
| + try {
|
| + _doInvokeMethodRef();
|
| + } on _InferenceFailedError {
|
| + hasError = true;
|
| + return DynamicTypeImpl.instance;
|
| + }
|
| break;
|
| case UnlinkedExprOperation.invokeMethod:
|
| _doInvokeMethod();
|
| @@ -2235,7 +2262,24 @@ class ExprTypeComputer {
|
| }
|
| }
|
|
|
| + void _throwIfInstanceFieldOrAccessor(Object element) {
|
| +// if (element is NonstaticMemberElementForLink) {
|
| +// element = (element as NonstaticMemberElementForLink).asExecutableElement;
|
| +// }
|
| + if (element is NonstaticMemberElementForLink &&
|
| + element.hasInstanceGetterReference ||
|
| + element is FieldElement && !element.isStatic ||
|
| + element is PropertyAccessorElement && !element.isStatic) {
|
| + throw new _InferenceFailedError(
|
| + 'Instance fields cannot be used for type inference.');
|
| + }
|
| + }
|
| +
|
| void _doAssignToProperty() {
|
| +// if (!element.isStatic) {
|
| + throw new _InferenceFailedError(
|
| + 'Instance fields cannot be used for type inference.');
|
| +// }
|
| DartType targetType = stack.removeLast();
|
| String propertyName = _getNextString();
|
| UnlinkedExprAssignOperator assignOperator =
|
| @@ -2263,7 +2307,9 @@ class ExprTypeComputer {
|
| }
|
|
|
| void _doAssignToRef() {
|
| - refPtr++;
|
| + EntityRef ref = _getNextRef();
|
| + ReferenceableElementForLink element = unit.resolveRef(ref.reference);
|
| + _throwIfInstanceFieldOrAccessor(element);
|
| UnlinkedExprAssignOperator operator =
|
| unlinkedConst.assignmentOperators[assignmentOperatorPtr++];
|
| if (operator == UnlinkedExprAssignOperator.assign) {
|
| @@ -2321,6 +2367,7 @@ class ExprTypeComputer {
|
| ExecutableElement element = target
|
| .lookUpInheritedGetterOrMethod(propertyName, library: library);
|
| if (element != null) {
|
| + _throwIfInstanceFieldOrAccessor(element);
|
| if (element is PropertyAccessorElement) {
|
| return element.returnType;
|
| } else {
|
| @@ -2436,6 +2483,7 @@ class ExprTypeComputer {
|
| List<DartType> positionalArgTypes = _popList(numPositional);
|
| EntityRef ref = _getNextRef();
|
| ReferenceableElementForLink element = unit.resolveRef(ref.reference);
|
| + _throwIfInstanceFieldOrAccessor(element);
|
| List<DartType> typeArguments = _getTypeArguments();
|
| stack.add(() {
|
| DartType rawType = element.asStaticType;
|
| @@ -2509,6 +2557,7 @@ class ExprTypeComputer {
|
| // function-typed parameters.
|
| assert(ref.implicitFunctionTypeIndices.isEmpty);
|
| ReferenceableElementForLink element = unit.resolveRef(ref.reference);
|
| + _throwIfInstanceFieldOrAccessor(element);
|
| stack.add(element.asStaticType);
|
| }
|
| }
|
| @@ -3933,33 +3982,62 @@ class NonstaticMemberElementForLink extends Object
|
| */
|
| final LibraryElementForLink _library;
|
|
|
| + bool _elementReady = false;
|
| + ExecutableElement _element;
|
| +
|
| NonstaticMemberElementForLink(this._library, this._target, this._name);
|
|
|
| @override
|
| ConstVariableNode get asConstVariable => _target.asConstVariable;
|
|
|
| - @override
|
| - DartType get asStaticType {
|
| - if (_library._linker.strongMode) {
|
| + /**
|
| + * TODO(scheglov) document
|
| + */
|
| + bool get hasInstanceGetterReference {
|
| + ExecutableElement element = asExecutableElement;
|
| + if (element is PropertyAccessorElement) {
|
| + return !element.isStatic;
|
| + }
|
| + ReferenceableElementForLink target = _target;
|
| + if (target is NonstaticMemberElementForLink) {
|
| + return target.hasInstanceGetterReference;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + /**
|
| + * TODO((scheglov) document
|
| + */
|
| + ExecutableElement get asExecutableElement {
|
| + if (!_elementReady) {
|
| + _elementReady = true;
|
| DartType targetType = _target.asStaticType;
|
| if (targetType.isDynamic) {
|
| targetType = _library._linker.typeProvider.objectType;
|
| }
|
| if (targetType is InterfaceType) {
|
| - ExecutableElement element =
|
| + _element =
|
| targetType.lookUpInheritedGetterOrMethod(_name, library: _library);
|
| - if (element != null) {
|
| - if (element is PropertyAccessorElement) {
|
| - return element.returnType;
|
| - } else {
|
| - // Method tear-off
|
| - return element.type;
|
| - }
|
| - }
|
| }
|
| // TODO(paulberry): handle .call on function types and .toString or
|
| // .hashCode on all types.
|
| }
|
| + return _element;
|
| + }
|
| +
|
| + @override
|
| + DartType get asStaticType {
|
| + if (_library._linker.strongMode) {
|
| + ExecutableElement element = asExecutableElement;
|
| + if (element != null) {
|
| + if (element is PropertyAccessorElement) {
|
| + return element.returnType;
|
| + } else {
|
| + // Method tear-off
|
| + return element.type;
|
| + }
|
| + }
|
| + }
|
| return DynamicTypeImpl.instance;
|
| }
|
|
|
| @@ -4470,17 +4548,17 @@ class PropertyAccessorElementForLink_Variable extends Object
|
| * progress of type inference.
|
| */
|
| DartType computeVariableType() {
|
| - if (variable.hasImplicitType &&
|
| - !isStatic &&
|
| - !variable.compilationUnit.isTypeInferenceComplete) {
|
| - // This is an instance field and we are currently inferring types in the
|
| - // library cycle containing it. So we shouldn't use the inferred type
|
| - // (even if we have already computed it), since that would lead to
|
| - // non-deterministic type inference results.
|
| - return DynamicTypeImpl.instance;
|
| - } else {
|
| - return variable.type;
|
| - }
|
| +// if (variable.hasImplicitType &&
|
| +// !isStatic &&
|
| +// !variable.compilationUnit.isTypeInferenceComplete) {
|
| +// // This is an instance field and we are currently inferring types in the
|
| +// // library cycle containing it. So we shouldn't use the inferred type
|
| +// // (even if we have already computed it), since that would lead to
|
| +// // non-deterministic type inference results.
|
| +// return DynamicTypeImpl.instance;
|
| +// } else {
|
| + return variable.type;
|
| +// }
|
| }
|
|
|
| @override
|
| @@ -4739,6 +4817,11 @@ class TypeInferenceNode extends Node<TypeInferenceNode> {
|
| */
|
| final FunctionElementForLink_Local functionElement;
|
|
|
| + /**
|
| + * TODO(scheglov) document
|
| + */
|
| + bool _hasError = false;
|
| +
|
| TypeInferenceNode(this.functionElement);
|
|
|
| @override
|
| @@ -4776,8 +4859,19 @@ class TypeInferenceNode extends Node<TypeInferenceNode> {
|
| EntityRef ref = unlinkedConst.references[refPtr++];
|
| // TODO(paulberry): cache these resolved references for
|
| // later use by evaluate().
|
| - TypeInferenceNode dependency =
|
| - compilationUnit.resolveRef(ref.reference).asTypeInferenceNode;
|
| + ReferenceableElementForLink element =
|
| + compilationUnit.resolveRef(ref.reference);
|
| +// // Type inference using instance fields is not allowed.
|
| +// // So, we need to report an error and fail the inference.
|
| +// if (element is VariableElementForLink) {
|
| +// var variable = element as VariableElementForLink;
|
| +// if (!variable.isStatic) {
|
| +// _hasError = true;
|
| +// dependencies.clear();
|
| +// return;
|
| +// }
|
| +// }
|
| + TypeInferenceNode dependency = element.asTypeInferenceNode;
|
| if (dependency != null) {
|
| dependencies.add(dependency);
|
| }
|
| @@ -4847,18 +4941,23 @@ class TypeInferenceNode extends Node<TypeInferenceNode> {
|
| if (inCycle) {
|
| functionElement._setInferredType(DynamicTypeImpl.instance);
|
| } else {
|
| - var bodyType = new ExprTypeComputer(functionElement).compute();
|
| - if (functionElement.isAsynchronous) {
|
| - var linker = functionElement.compilationUnit.library._linker;
|
| - var typeProvider = linker.typeProvider;
|
| - var typeSystem = linker.typeSystem;
|
| - if (bodyType.isDartAsyncFutureOr) {
|
| - bodyType = (bodyType as InterfaceType).typeArguments[0];
|
| + var computer = new ExprTypeComputer(functionElement);
|
| + if (computer.hasError) {
|
| + functionElement._setInferredType(DynamicTypeImpl.instance);
|
| + } else {
|
| + DartType bodyType = computer.compute();
|
| + if (functionElement.isAsynchronous) {
|
| + var linker = functionElement.compilationUnit.library._linker;
|
| + var typeProvider = linker.typeProvider;
|
| + var typeSystem = linker.typeSystem;
|
| + if (bodyType.isDartAsyncFutureOr) {
|
| + bodyType = (bodyType as InterfaceType).typeArguments[0];
|
| + }
|
| + bodyType = typeProvider.futureType
|
| + .instantiate([bodyType.flattenFutures(typeSystem)]);
|
| }
|
| - bodyType = typeProvider.futureType
|
| - .instantiate([bodyType.flattenFutures(typeSystem)]);
|
| + functionElement._setInferredType(bodyType);
|
| }
|
| - functionElement._setInferredType(bodyType);
|
| }
|
| }
|
|
|
| @@ -5190,3 +5289,12 @@ abstract class VariableElementForLink
|
| @override
|
| String toString() => '$enclosingElement.$name';
|
| }
|
| +
|
| +/**
|
| + * TODO(scheglov) document
|
| + */
|
| +class _InferenceFailedError {
|
| + final String message;
|
| +
|
| + _InferenceFailedError(this.message);
|
| +}
|
|
|