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

Side by Side Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 2456803004: fixes #27586, prefer context type in generic inference (Closed)
Patch Set: wip Created 3 years, 11 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library analyzer.src.generated.resolver; 5 library analyzer.src.generated.resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; 10 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
11 import 'package:analyzer/dart/ast/token.dart'; 11 import 'package:analyzer/dart/ast/token.dart';
12 import 'package:analyzer/dart/ast/visitor.dart'; 12 import 'package:analyzer/dart/ast/visitor.dart';
13 import 'package:analyzer/dart/element/element.dart'; 13 import 'package:analyzer/dart/element/element.dart';
14 import 'package:analyzer/dart/element/type.dart'; 14 import 'package:analyzer/dart/element/type.dart';
15 import 'package:analyzer/dart/element/visitor.dart'; 15 import 'package:analyzer/dart/element/visitor.dart';
16 import 'package:analyzer/error/error.dart'; 16 import 'package:analyzer/error/error.dart';
17 import 'package:analyzer/error/listener.dart'; 17 import 'package:analyzer/error/listener.dart';
18 import 'package:analyzer/exception/exception.dart'; 18 import 'package:analyzer/exception/exception.dart';
19 import 'package:analyzer/src/dart/ast/ast.dart'; 19 import 'package:analyzer/src/dart/ast/ast.dart';
20 import 'package:analyzer/src/dart/ast/utilities.dart'; 20 import 'package:analyzer/src/dart/ast/utilities.dart';
21 import 'package:analyzer/src/dart/element/element.dart'; 21 import 'package:analyzer/src/dart/element/element.dart';
22 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
22 import 'package:analyzer/src/dart/element/type.dart'; 23 import 'package:analyzer/src/dart/element/type.dart';
23 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; 24 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
24 import 'package:analyzer/src/dart/resolver/scope.dart'; 25 import 'package:analyzer/src/dart/resolver/scope.dart';
25 import 'package:analyzer/src/error/codes.dart'; 26 import 'package:analyzer/src/error/codes.dart';
26 import 'package:analyzer/src/generated/constant.dart'; 27 import 'package:analyzer/src/generated/constant.dart';
27 import 'package:analyzer/src/generated/element_resolver.dart'; 28 import 'package:analyzer/src/generated/element_resolver.dart';
28 import 'package:analyzer/src/generated/engine.dart'; 29 import 'package:analyzer/src/generated/engine.dart';
29 import 'package:analyzer/src/generated/error_verifier.dart'; 30 import 'package:analyzer/src/generated/error_verifier.dart';
30 import 'package:analyzer/src/generated/source.dart'; 31 import 'package:analyzer/src/generated/source.dart';
31 import 'package:analyzer/src/generated/static_type_analyzer.dart'; 32 import 'package:analyzer/src/generated/static_type_analyzer.dart';
(...skipping 4080 matching lines...) Expand 10 before | Expand all | Expand 10 after
4112 if (_returnStack.isEmpty) { 4113 if (_returnStack.isEmpty) {
4113 return; 4114 return;
4114 } 4115 }
4115 4116
4116 DartType inferred = _inferredReturn.last; 4117 DartType inferred = _inferredReturn.last;
4117 inferred = _typeSystem.getLeastUpperBound(type, inferred); 4118 inferred = _typeSystem.getLeastUpperBound(type, inferred);
4118 _inferredReturn[_inferredReturn.length - 1] = inferred; 4119 _inferredReturn[_inferredReturn.length - 1] = inferred;
4119 } 4120 }
4120 4121
4121 /** 4122 /**
4122 * Match type [t1] against type [t2] as follows.
4123 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype
4124 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>`
4125 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'`
4126 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`,
4127 * such that `I<T0, .., Tn> <: t2`
4128 */
4129 List<DartType> matchTypes(DartType t1, DartType t2) =>
4130 (t1 is InterfaceType && t2 is InterfaceType) ? _matchTypes(t1, t2) : null;
4131
4132 /**
4133 * Pop a return type off of the return stack. 4123 * Pop a return type off of the return stack.
4134 * 4124 *
4135 * Also record any inferred return type using [setType], unless this node 4125 * Also record any inferred return type using [setType], unless this node
4136 * already has a context type. This recorded type will be the least upper 4126 * already has a context type. This recorded type will be the least upper
4137 * bound of all types added with [addReturnOrYieldType]. 4127 * bound of all types added with [addReturnOrYieldType].
4138 */ 4128 */
4139 void popReturnContext(BlockFunctionBody node) { 4129 void popReturnContext(BlockFunctionBody node) {
4140 if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) { 4130 if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) {
4141 DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance; 4131 DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance;
4142 DartType inferred = _inferredReturn.removeLast(); 4132 DartType inferred = _inferredReturn.removeLast();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4182 error = StrongModeCode.INFERRED_TYPE_ALLOCATION; 4172 error = StrongModeCode.INFERRED_TYPE_ALLOCATION;
4183 } else if (node is FunctionExpression) { 4173 } else if (node is FunctionExpression) {
4184 error = StrongModeCode.INFERRED_TYPE_CLOSURE; 4174 error = StrongModeCode.INFERRED_TYPE_CLOSURE;
4185 } else { 4175 } else {
4186 error = StrongModeCode.INFERRED_TYPE; 4176 error = StrongModeCode.INFERRED_TYPE;
4187 } 4177 }
4188 4178
4189 _errorReporter.reportErrorForNode(error, node, [node, type]); 4179 _errorReporter.reportErrorForNode(error, node, [node, type]);
4190 } 4180 }
4191 4181
4192 List<DartType> _matchTypes(InterfaceType t1, InterfaceType t2) {
4193 if (t1 == t2) {
4194 return t2.typeArguments;
4195 }
4196 List<DartType> tArgs1 = t1.typeArguments;
4197 List<DartType> tArgs2 = t2.typeArguments;
4198 // If t1 isn't a raw type, bail out
4199 if (tArgs1 != null && tArgs1.any((t) => !t.isDynamic)) {
4200 return null;
4201 }
4202
4203 // This is our inferred type argument list. We start at all dynamic,
4204 // and fill in with inferred types when we reach a match.
4205 List<DartType> actuals =
4206 new List<DartType>.filled(tArgs1.length, _typeProvider.dynamicType);
4207
4208 // When we find the supertype of t1 with the same
4209 // classname as t2 (see below), we have the following:
4210 // If t1 is an instantiation of a class T1<X0, ..., Xn>
4211 // and t2 is an instantiation of a class T2<Y0, ...., Ym>
4212 // of the form t2 = T2<S0, ..., Sm>
4213 // then we want to choose instantiations for the Xi
4214 // T0, ..., Tn such that T1<T0, ..., Tn> <: t2 .
4215 // To find this, we simply instantate T1 with
4216 // X0, ..., Xn, and then find its superclass
4217 // T2<T0', ..., Tn'>. We then solve the constraint
4218 // set T0' <: S0, ..., Tn' <: Sn for the Xi.
4219 // Currently, we only handle constraints where
4220 // the Ti' is one of the Xi'. If there are multiple
4221 // constraints on some Xi, we choose the lower of the
4222 // two (if it exists).
4223 bool permute(List<DartType> permutedArgs) {
4224 if (permutedArgs == null) {
4225 return false;
4226 }
4227 List<TypeParameterElement> ps = t1.typeParameters;
4228 List<DartType> ts = ps.map((p) => p.type).toList();
4229 for (int i = 0; i < permutedArgs.length; i++) {
4230 DartType tVar = permutedArgs[i];
4231 DartType tActual = tArgs2[i];
4232 int index = ts.indexOf(tVar);
4233 if (index >= 0 && _typeSystem.isSubtypeOf(tActual, actuals[index])) {
4234 actuals[index] = tActual;
4235 }
4236 }
4237 return actuals.any((x) => !x.isDynamic);
4238 }
4239
4240 // Look for the first supertype of t1 with the same class name as t2.
4241 bool match(InterfaceType t1, Set<Element> visited) {
4242 if (t1.element == t2.element) {
4243 return permute(t1.typeArguments);
4244 }
4245
4246 if (t1 == _typeProvider.objectType) {
4247 return false;
4248 }
4249
4250 Element element = t1.element;
4251 if (visited == null) {
4252 visited = new HashSet<Element>();
4253 }
4254 if (element == null || !visited.add(element)) {
4255 return false;
4256 }
4257 try {
4258 if (match(t1.superclass, visited)) {
4259 return true;
4260 }
4261
4262 List<InterfaceType> mixins = t1.mixins;
4263 int mixinLength = mixins.length;
4264 for (int i = 0; i < mixinLength; i++) {
4265 if (match(mixins[i], visited)) {
4266 return true;
4267 }
4268 }
4269
4270 List<InterfaceType> interfaces = t1.interfaces;
4271 int interfaceLength = interfaces.length;
4272 for (int j = 0; j < interfaceLength; j++) {
4273 if (match(interfaces[j], visited)) {
4274 return true;
4275 }
4276 }
4277 } finally {
4278 visited.remove(element);
4279 }
4280 return false;
4281 }
4282
4283 // We have that t1 = T1<dynamic, ..., dynamic>.
4284 // To match t1 against t2, we use the uninstantiated version
4285 // of t1, essentially treating it as an instantiation with
4286 // fresh variables, and solve for the variables.
4287 // t1.element.type will be of the form T1<X0, ..., Xn>
4288 if (!match(t1.element.type, null)) {
4289 return null;
4290 }
4291 DartType newT1 = t1.element.type.instantiate(actuals);
4292 // If we found a solution, return it.
4293 if (_typeSystem.isSubtypeOf(newT1, t2)) {
4294 return actuals;
4295 }
4296 return null;
4297 }
4298
4299 /** 4182 /**
4300 * Clear the type information assocated with [node]. 4183 * Clear the type information assocated with [node].
4301 */ 4184 */
4302 static void clearType(AstNode node) { 4185 static void clearType(AstNode node) {
4303 node?.setProperty(_typeProperty, null); 4186 node?.setProperty(_typeProperty, null);
4304 } 4187 }
4305 4188
4306 /** 4189 /**
4307 * Look for contextual type information attached to [node]. Returns 4190 * Look for contextual type information attached to [node], and returns
4308 * the type if found, otherwise null. 4191 * the type if found.
4309 * 4192 *
4310 * If [node] has a contextual union type like `T | Future<T>` this will be 4193 * If [node] has a contextual union type like `T | Future<T>` or a type that
4311 * returned. You can use [getType] if you prefer to only get the `T`. 4194 * contains `?` this will be returned. You can use [getValueContext] if you
4195 * prefer to eliminate the Future union, or [getType] to eliminate both.
4312 */ 4196 */
4313 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty); 4197 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty);
4314 4198
4315 /** 4199 /**
4200 * Look for contextual type information attached to [node] and returns it,
4201 * eliminating future unions by choosing `T` from `T | Future<T>`.
4202 *
4203 * See also [getContext].
4204 */
4205 static DartType getValueContext(AstNode node) {
4206 var context = getContext(node);
4207 return context is FutureUnionType ? context.type : context;
4208 }
4209
4210 /**
4316 * Look for a single contextual type attached to [node], and returns the type 4211 * Look for a single contextual type attached to [node], and returns the type
4317 * if found, otherwise null. 4212 * if found, otherwise null.
4318 * 4213 *
4319 * If [node] has a contextual union type like `T | Future<T>` this will 4214 * If [node] has a contextual union type like `T | Future<T>` this will
4320 * simplify it to only return `T`. If the caller can handle a union type, 4215 * simplify it to only return `T`. If the caller can handle a union type,
4321 * [getContext] should be used instead. 4216 * [getContext] should be used instead.
4322 */ 4217 */
4323 static DartType getType(AstNode node) { 4218 static DartType getType(AstNode node) {
4324 DartType t = getContext(node); 4219 DartType t = getContext(node);
4325 if (t is FutureUnionType) { 4220 if (t is FutureUnionType) {
4326 return t.type; 4221 return _substituteForUnknown(t.type);
4327 } 4222 }
4328 return t; 4223 return _substituteForUnknown(t);
4329 } 4224 }
4330 4225
4331 /** 4226 /**
4332 * Like [getContext] but expands a union type into a list of types. 4227 * Like [getContext] but expands a union type into a list of types.
4333 */ 4228 */
4334 static Iterable<DartType> getTypes(AstNode node) { 4229 static Iterable<DartType> getTypes(AstNode node) {
4335 DartType t = getContext(node); 4230 DartType t = getContext(node);
4336 if (t == null) { 4231 if (t == null) {
4337 return DartType.EMPTY_LIST; 4232 return DartType.EMPTY_LIST;
4338 } 4233 }
4339 if (t is FutureUnionType) { 4234 Iterable<DartType> result = t is FutureUnionType ? t.types : [t];
4340 return t.types; 4235 return result.map(_substituteForUnknown).where((t) => t != null);
4341 } 4236 }
4342 return <DartType>[t]; 4237
4238 static DartType _substituteForUnknown(DartType t) {
4239 if (t == null) return null;
4240 // Since the type is being used for downwards inference, the expression
4241 // type E must be a subtype of the context type T, i.e. T is an upper bound.
4242 //
4243 // TODO(jmesserly): our downwards inference code is not designed to handle
4244 // the bottom type, so we need to prevent it from resulting here.
4245 // Instead use `dynamic`. See `UnknownInferredType.upperBoundForType`.
4246 return UnknownInferredType.substituteDynamic(t);
4343 } 4247 }
4344 4248
4345 /** 4249 /**
4346 * Attach contextual type information [type] to [node] for use during 4250 * Attach contextual type information [type] to [node] for use during
4347 * inference. 4251 * inference.
4348 */ 4252 */
4349 static void setType(AstNode node, DartType type) { 4253 static void setType(AstNode node, DartType type) {
4350 if (type == null || type.isDynamic) { 4254 if (type == null || type.isDynamic) {
4351 clearType(node); 4255 clearType(node);
4352 } else { 4256 } else {
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after
5396 assert(parent is PartOfDirective); 5300 assert(parent is PartOfDirective);
5397 } else { 5301 } else {
5398 elementAnnotationImpl.annotationAst = 5302 elementAnnotationImpl.annotationAst =
5399 new ConstantAstCloner().cloneNode(node); 5303 new ConstantAstCloner().cloneNode(node);
5400 } 5304 }
5401 return null; 5305 return null;
5402 } 5306 }
5403 5307
5404 @override 5308 @override
5405 Object visitArgumentList(ArgumentList node) { 5309 Object visitArgumentList(ArgumentList node) {
5406 DartType callerType = InferenceContext.getType(node); 5310 DartType callerType = InferenceContext.getContext(node);
5407 if (callerType is FunctionType) { 5311 if (callerType is FunctionType) {
5408 Map<String, DartType> namedParameterTypes = 5312 Map<String, DartType> namedParameterTypes =
5409 callerType.namedParameterTypes; 5313 callerType.namedParameterTypes;
5410 List<DartType> normalParameterTypes = callerType.normalParameterTypes; 5314 List<DartType> normalParameterTypes = callerType.normalParameterTypes;
5411 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes; 5315 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes;
5412 int normalCount = normalParameterTypes.length; 5316 int normalCount = normalParameterTypes.length;
5413 int optionalCount = optionalParameterTypes.length; 5317 int optionalCount = optionalParameterTypes.length;
5414 5318
5415 NodeList<Expression> arguments = node.arguments; 5319 NodeList<Expression> arguments = node.arguments;
5416 Iterable<Expression> positional = 5320 Iterable<Expression> positional =
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after
6056 _currentFunctionBody = outerFunctionBody; 5960 _currentFunctionBody = outerFunctionBody;
6057 _enclosingFunction = outerFunction; 5961 _enclosingFunction = outerFunction;
6058 } 5962 }
6059 return null; 5963 return null;
6060 } 5964 }
6061 5965
6062 @override 5966 @override
6063 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 5967 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
6064 node.function?.accept(this); 5968 node.function?.accept(this);
6065 node.accept(elementResolver); 5969 node.accept(elementResolver);
6066 _inferArgumentTypesFromContext(node); 5970 _inferArgumentTypesForInvocation(node);
6067 node.argumentList?.accept(this); 5971 node.argumentList?.accept(this);
6068 node.accept(typeAnalyzer); 5972 node.accept(typeAnalyzer);
6069 return null; 5973 return null;
6070 } 5974 }
6071 5975
6072 @override 5976 @override
6073 Object visitFunctionTypeAlias(FunctionTypeAlias node) { 5977 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
6074 // Resolve the metadata in the library scope. 5978 // Resolve the metadata in the library scope.
6075 if (node.metadata != null) { 5979 if (node.metadata != null) {
6076 node.metadata.accept(this); 5980 node.metadata.accept(this);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
6151 <Map<VariableElement, DartType>>[]; 6055 <Map<VariableElement, DartType>>[];
6152 perBranchOverrides.add(thenOverrides); 6056 perBranchOverrides.add(thenOverrides);
6153 perBranchOverrides.add(elseOverrides); 6057 perBranchOverrides.add(elseOverrides);
6154 _overrideManager.mergeOverrides(perBranchOverrides); 6058 _overrideManager.mergeOverrides(perBranchOverrides);
6155 } 6059 }
6156 return null; 6060 return null;
6157 } 6061 }
6158 6062
6159 @override 6063 @override
6160 Object visitInstanceCreationExpression(InstanceCreationExpression node) { 6064 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
6161 TypeName classTypeName = node.constructorName.type;
6162 // TODO(leafp): Currently, we may re-infer types here, since we
6163 // sometimes resolve multiple times. We should really check that we
6164 // have not already inferred something. However, the obvious ways to
6165 // check this don't work, since we may have been instantiated
6166 // to bounds in an earlier phase, and we *do* want to do inference
6167 // in that case.
6168 if (classTypeName.typeArguments == null) {
6169 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first
6170 // valid instantiation `new C<Ti>`, if it exists.
6171 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
6172 // will become a valid possibility. Right now the only allowed union is
6173 // `T | Future<T>` so we can take a simple approach.
6174 for (var contextType in InferenceContext.getTypes(node)) {
6175 if (contextType is InterfaceType &&
6176 contextType.typeArguments != null &&
6177 contextType.typeArguments.isNotEmpty) {
6178 // TODO(jmesserly): for generic methods we use the
6179 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
6180 // be a tad more powerful than matchTypes.
6181 //
6182 // For example it can infer this case:
6183 //
6184 // class E<S, T> extends A<C<S>, T> { ... }
6185 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
6186 //
6187 // See _inferArgumentTypesFromContext in this file for use of it.
6188 List<DartType> targs =
6189 inferenceContext.matchTypes(classTypeName.type, contextType);
6190 if (targs != null && targs.any((t) => !t.isDynamic)) {
6191 ClassElement classElement =
6192 resolutionMap.typeForTypeName(classTypeName).element;
6193 InterfaceType rawType = classElement.type;
6194 InterfaceType fullType =
6195 rawType.substitute2(targs, rawType.typeArguments);
6196 // The element resolver uses the type on the constructor name, so
6197 // infer it first
6198 typeAnalyzer.inferConstructorName(node.constructorName, fullType);
6199 break;
6200 }
6201 }
6202 }
6203 }
6204 node.constructorName?.accept(this); 6065 node.constructorName?.accept(this);
6205 FunctionType constructorType = resolutionMap 6066 _inferArgumentTypesForInstanceCreate(node);
6206 .staticElementForConstructorReference(node.constructorName)
6207 ?.type;
6208 if (constructorType != null) {
6209 InferenceContext.setType(node.argumentList, constructorType);
6210 }
6211 node.argumentList?.accept(this); 6067 node.argumentList?.accept(this);
6212 node.accept(elementResolver); 6068 node.accept(elementResolver);
6213 node.accept(typeAnalyzer); 6069 node.accept(typeAnalyzer);
6214 return null; 6070 return null;
6215 } 6071 }
6216 6072
6217 @override 6073 @override
6218 Object visitLabel(Label node) => null; 6074 Object visitLabel(Label node) => null;
6219 6075
6220 @override 6076 @override
6221 Object visitLibraryIdentifier(LibraryIdentifier node) => null; 6077 Object visitLibraryIdentifier(LibraryIdentifier node) => null;
6222 6078
6223 @override 6079 @override
6224 Object visitListLiteral(ListLiteral node) { 6080 Object visitListLiteral(ListLiteral node) {
6225 DartType contextType = InferenceContext.getType(node); 6081 InterfaceType listT;
6226 List<DartType> targs = null; 6082
6227 if (node.typeArguments != null) { 6083 if (node.typeArguments != null) {
6228 targs = node.typeArguments.arguments.map((t) => t.type).toList(); 6084 var targs = node.typeArguments.arguments.map((t) => t.type).toList();
6229 } else if (contextType is InterfaceType) { 6085 if (targs.length == 1 && !targs[0].isDynamic) {
6230 InterfaceType listD = 6086 listT = typeProvider.listType.instantiate([targs[0]]);
6231 typeProvider.listType.instantiate([typeProvider.dynamicType]); 6087 }
6232 targs = inferenceContext.matchTypes(listD, contextType); 6088 } else if (strongMode) {
6089 listT = typeAnalyzer.inferListType(node, downwards: true);
6233 } 6090 }
6234 if (targs != null && targs.length == 1 && !targs[0].isDynamic) { 6091 if (listT != null) {
6235 DartType eType = targs[0]; 6092 DartType eType = listT.typeArguments[0];
6236 InterfaceType listT = typeProvider.listType.instantiate([eType]);
6237 for (Expression child in node.elements) { 6093 for (Expression child in node.elements) {
6238 InferenceContext.setType(child, eType); 6094 InferenceContext.setType(child, eType);
6239 } 6095 }
6240 InferenceContext.setType(node, listT); 6096 InferenceContext.setType(node, listT);
6241 } else { 6097 } else {
6242 InferenceContext.clearType(node); 6098 InferenceContext.clearType(node);
6243 } 6099 }
6244 super.visitListLiteral(node); 6100 super.visitListLiteral(node);
6245 return null; 6101 return null;
6246 } 6102 }
6247 6103
6248 @override 6104 @override
6249 Object visitMapLiteral(MapLiteral node) { 6105 Object visitMapLiteral(MapLiteral node) {
6250 DartType contextType = InferenceContext.getType(node); 6106 InterfaceType mapT;
6251 List<DartType> targs = null;
6252 if (node.typeArguments != null) { 6107 if (node.typeArguments != null) {
6253 targs = node.typeArguments.arguments.map((t) => t.type).toList(); 6108 var targs = node.typeArguments.arguments.map((t) => t.type).toList();
6254 } else if (contextType is InterfaceType) { 6109 if (targs.length == 2 && targs.any((t) => !t.isDynamic)) {
6255 InterfaceType mapD = typeProvider.mapType 6110 mapT = typeProvider.mapType.instantiate([targs[0], targs[1]]);
6256 .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]); 6111 }
6257 targs = inferenceContext.matchTypes(mapD, contextType); 6112 } else if (strongMode) {
6113 mapT = typeAnalyzer.inferMapType(node, downwards: true);
6258 } 6114 }
6259 if (targs != null && targs.length == 2 && targs.any((t) => !t.isDynamic)) { 6115 if (mapT != null) {
6260 DartType kType = targs[0]; 6116 DartType kType = mapT.typeArguments[0];
6261 DartType vType = targs[1]; 6117 DartType vType = mapT.typeArguments[1];
6262 InterfaceType mapT = typeProvider.mapType.instantiate([kType, vType]);
6263 for (MapLiteralEntry entry in node.entries) { 6118 for (MapLiteralEntry entry in node.entries) {
6264 InferenceContext.setType(entry.key, kType); 6119 InferenceContext.setType(entry.key, kType);
6265 InferenceContext.setType(entry.value, vType); 6120 InferenceContext.setType(entry.value, vType);
6266 } 6121 }
6267 InferenceContext.setType(node, mapT); 6122 InferenceContext.setType(node, mapT);
6268 } else { 6123 } else {
6269 InferenceContext.clearType(node); 6124 InferenceContext.clearType(node);
6270 } 6125 }
6271 super.visitMapLiteral(node); 6126 super.visitMapLiteral(node);
6272 return null; 6127 return null;
(...skipping 25 matching lines...) Expand all
6298 6153
6299 @override 6154 @override
6300 Object visitMethodInvocation(MethodInvocation node) { 6155 Object visitMethodInvocation(MethodInvocation node) {
6301 // 6156 //
6302 // We visit the target and argument list, but do not visit the method name 6157 // We visit the target and argument list, but do not visit the method name
6303 // because it needs to be visited in the context of the invocation. 6158 // because it needs to be visited in the context of the invocation.
6304 // 6159 //
6305 node.target?.accept(this); 6160 node.target?.accept(this);
6306 node.typeArguments?.accept(this); 6161 node.typeArguments?.accept(this);
6307 node.accept(elementResolver); 6162 node.accept(elementResolver);
6308 _inferArgumentTypesFromContext(node); 6163 _inferArgumentTypesForInvocation(node);
6309 node.argumentList?.accept(this); 6164 node.argumentList?.accept(this);
6310 node.accept(typeAnalyzer); 6165 node.accept(typeAnalyzer);
6311 return null; 6166 return null;
6312 } 6167 }
6313 6168
6314 @override 6169 @override
6315 Object visitNamedExpression(NamedExpression node) { 6170 Object visitNamedExpression(NamedExpression node) {
6316 InferenceContext.setTypeFromNode(node.expression, node); 6171 InferenceContext.setTypeFromNode(node.expression, node);
6317 return super.visitNamedExpression(node); 6172 return super.visitNamedExpression(node);
6318 } 6173 }
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
6591 6446
6592 // Ordinary functions just return their declared types. 6447 // Ordinary functions just return their declared types.
6593 if (!isGenerator && !isAsynchronous) { 6448 if (!isGenerator && !isAsynchronous) {
6594 return declaredType; 6449 return declaredType;
6595 } 6450 }
6596 if (declaredType is InterfaceType) { 6451 if (declaredType is InterfaceType) {
6597 if (isGenerator) { 6452 if (isGenerator) {
6598 // If it's sync* we expect Iterable<T> 6453 // If it's sync* we expect Iterable<T>
6599 // If it's async* we expect Stream<T> 6454 // If it's async* we expect Stream<T>
6600 InterfaceType rawType = isAsynchronous 6455 InterfaceType rawType = isAsynchronous
6601 ? typeProvider.streamDynamicType 6456 ? typeProvider.streamType
6602 : typeProvider.iterableDynamicType; 6457 : typeProvider.iterableType;
6603 // Match the types to instantiate the type arguments if possible 6458 // Match the types to instantiate the type arguments if possible
6604 List<DartType> typeArgs = 6459 List<DartType> targs = declaredType.typeArguments;
6605 inferenceContext.matchTypes(rawType, declaredType); 6460 if (targs.length == 1 && rawType.instantiate(targs) == declaredType) {
6606 return (typeArgs?.length == 1) ? typeArgs[0] : null; 6461 return targs[0];
6462 }
6607 } 6463 }
6608 // async functions expect `Future<T> | T` 6464 // async functions expect `Future<T> | T`
6609 var futureTypeParam = declaredType.flattenFutures(typeSystem); 6465 var futureTypeParam = declaredType.flattenFutures(typeSystem);
6610 return FutureUnionType.from(futureTypeParam, typeProvider, typeSystem); 6466 return FutureUnionType.from(futureTypeParam, typeProvider, typeSystem);
6611 } 6467 }
6612 return declaredType; 6468 return declaredType;
6613 } 6469 }
6614 6470
6615 /** 6471 /**
6616 * The given expression is the expression used to compute the iterator for a 6472 * The given expression is the expression used to compute the iterator for a
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
6684 if (executable is MethodElement) { 6540 if (executable is MethodElement) {
6685 return true; 6541 return true;
6686 } 6542 }
6687 if (executable is FunctionElement) { 6543 if (executable is FunctionElement) {
6688 return executable.enclosingElement is CompilationUnitElement; 6544 return executable.enclosingElement is CompilationUnitElement;
6689 } 6545 }
6690 } 6546 }
6691 return false; 6547 return false;
6692 } 6548 }
6693 6549
6694 void _inferArgumentTypesFromContext(InvocationExpression node) { 6550 FunctionType _inferArgumentTypesForGeneric(
6551 AstNode inferenceNode,
6552 DartType uninstantiatedType,
6553 TypeArgumentList typeArguments,
6554 {AstNode errorNode}) {
6555 errorNode ??= inferenceNode;
6556 TypeSystem ts = typeSystem;
6557 if (typeArguments == null &&
6558 uninstantiatedType is FunctionType &&
6559 uninstantiatedType.typeFormals.isNotEmpty &&
6560 ts is StrongTypeSystemImpl) {
6561 return ts.inferGenericFunctionOrType/*<FunctionType>*/(
6562 uninstantiatedType,
6563 ParameterElement.EMPTY_LIST,
6564 DartType.EMPTY_LIST,
6565 uninstantiatedType.returnType,
6566 InferenceContext.getContext(inferenceNode),
6567 downwards: true,
6568 errorReporter: errorReporter,
6569 errorNode: errorNode);
6570 }
6571 return null;
6572 }
6573
6574 void _inferArgumentTypesForInstanceCreate(InstanceCreationExpression node) {
6575 ConstructorName constructor = node.constructorName;
6576 TypeName classTypeName = constructor?.type;
6577 if (classTypeName == null || !strongMode) {
6578 return;
6579 }
6580
6581 ConstructorElement originalElement =
6582 resolutionMap.staticElementForConstructorReference(constructor);
6583 FunctionType inferred;
6584 // If the constructor is generic, we'll have a ConstructorMember that
6585 // substitutes in type arguments (possibly `dynamic`) from earlier in
6586 // resolution.
6587 //
6588 // Otherwise we'll have a ConstructorElement, and we can skip inference
6589 // because there's nothing to infer in a non-generic type.
6590 if (classTypeName.typeArguments == null &&
6591 originalElement is ConstructorMember) {
6592 // TODO(leafp): Currently, we may re-infer types here, since we
6593 // sometimes resolve multiple times. We should really check that we
6594 // have not already inferred something. However, the obvious ways to
6595 // check this don't work, since we may have been instantiated
6596 // to bounds in an earlier phase, and we *do* want to do inference
6597 // in that case.
6598
6599 // Get back to the uninstantiated generic constructor.
6600 // TODO(jmesserly): should we store this earlier in resolution?
6601 // Or look it up, instead of jumping backwards through the Member?
6602 var rawElement = originalElement.baseElement;
6603
6604 FunctionType constructorType =
6605 typeAnalyzer.constructorToGenericFunctionType(rawElement);
6606
6607 inferred = _inferArgumentTypesForGeneric(node, constructorType,
6608 constructor.type.typeArguments, errorNode: node.constructorName);
6609
6610 if (inferred != null) {
6611 ArgumentList arguments = node.argumentList;
6612 InferenceContext.setType(arguments, inferred);
6613 // Fix up the parameter elements based on inferred method.
6614 arguments.correspondingStaticParameters =
6615 resolveArgumentsToParameters(arguments, inferred.parameters, null);
6616
6617 constructor.type.type = inferred.returnType;
6618 if (!UnknownInferredType.typeIsUnknown(inferred)) {
6619 inferenceContext.recordInference(node, inferred.returnType);
6620 }
6621
6622 // Update the static element as well. This is used in some cases, such a s
Leaf 2017/01/24 18:26:55 length
Jennifer Messerly 2017/02/01 09:31:38 Done.
6623 // computing constant values. It is stored in two places.
6624 constructor.staticElement =
6625 ConstructorMember.from(rawElement, inferred.returnType);
6626 node.staticElement = constructor.staticElement;
6627 }
6628 }
6629
6630 if (inferred == null) {
6631 InferenceContext.setType(node.argumentList, originalElement?.type);
6632 }
6633 }
6634
6635 void _inferArgumentTypesForInvocation(InvocationExpression node) {
6695 if (!strongMode) { 6636 if (!strongMode) {
6696 // Use propagated type inference for lambdas if not in strong mode. 6637 // Use propagated type inference for lambdas if not in strong mode.
6697 _inferFunctionExpressionsParametersTypes(node.argumentList); 6638 _inferFunctionExpressionsParametersTypes(node.argumentList);
6698 return; 6639 return;
6699 } 6640 }
6700 6641 DartType inferred = _inferArgumentTypesForGeneric(node,
6701 DartType contextType = node.staticInvokeType; 6642 node.function.staticType, node.typeArguments);
6702 if (contextType is FunctionType) { 6643 InferenceContext.setType(
6703 DartType originalType = node.function.staticType; 6644 node.argumentList, inferred ?? node.staticInvokeType);
6704 DartType returnContextType = InferenceContext.getContext(node);
6705 TypeSystem ts = typeSystem;
6706 if (returnContextType != null &&
6707 node.typeArguments == null &&
6708 originalType is FunctionType &&
6709 originalType.typeFormals.isNotEmpty &&
6710 ts is StrongTypeSystemImpl) {
6711 contextType = ts.inferGenericFunctionCall(
6712 originalType,
6713 DartType.EMPTY_LIST,
6714 DartType.EMPTY_LIST,
6715 originalType.returnType,
6716 returnContextType);
6717 }
6718
6719 InferenceContext.setType(node.argumentList, contextType);
6720 }
6721 } 6645 }
6722 6646
6723 void _inferFormalParameterList(FormalParameterList node, DartType type) { 6647 void _inferFormalParameterList(FormalParameterList node, DartType type) {
6724 if (typeAnalyzer.inferFormalParameterList(node, type)) { 6648 if (typeAnalyzer.inferFormalParameterList(node, type)) {
6725 // TODO(leafp): This gets dropped on the floor if we're in the field 6649 // TODO(leafp): This gets dropped on the floor if we're in the field
6726 // inference task. We should probably keep these infos. 6650 // inference task. We should probably keep these infos.
6727 // 6651 //
6728 // TODO(jmesserly): this is reporting the context type, and therefore not 6652 // TODO(jmesserly): this is reporting the context type, and therefore not
6729 // necessarily the correct inferred type for the lambda. 6653 // necessarily the correct inferred type for the lambda.
6730 // 6654 //
(...skipping 4067 matching lines...) Expand 10 before | Expand all | Expand 10 after
10798 return null; 10722 return null;
10799 } 10723 }
10800 if (identical(node.staticElement, variable)) { 10724 if (identical(node.staticElement, variable)) {
10801 if (node.inSetterContext()) { 10725 if (node.inSetterContext()) {
10802 result = true; 10726 result = true;
10803 } 10727 }
10804 } 10728 }
10805 return null; 10729 return null;
10806 } 10730 }
10807 } 10731 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698