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

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

Issue 2456803004: fixes #27586, prefer context type in generic inference (Closed)
Patch Set: fix Created 3 years, 10 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 4130 matching lines...) Expand 10 before | Expand all | Expand 10 after
4162 if (_returnStack.isEmpty) { 4163 if (_returnStack.isEmpty) {
4163 return; 4164 return;
4164 } 4165 }
4165 4166
4166 DartType inferred = _inferredReturn.last; 4167 DartType inferred = _inferredReturn.last;
4167 inferred = _typeSystem.getLeastUpperBound(type, inferred); 4168 inferred = _typeSystem.getLeastUpperBound(type, inferred);
4168 _inferredReturn[_inferredReturn.length - 1] = inferred; 4169 _inferredReturn[_inferredReturn.length - 1] = inferred;
4169 } 4170 }
4170 4171
4171 /** 4172 /**
4172 * Like [getContext] but expands a union type into a list of types.
4173 */
4174 Iterable<DartType> getTypes(AstNode node) {
4175 DartType t = getContext(node);
4176 if (t == null) {
4177 return DartType.EMPTY_LIST;
4178 }
4179 if (t is InterfaceType && t.isDartAsyncFutureOr) {
4180 var tArg = t.typeArguments[0]; // The T in FutureOr<T>
4181 return [
4182 _typeProvider.futureType.instantiate([tArg]),
4183 tArg
4184 ];
4185 }
4186 return [t];
4187 }
4188
4189 /**
4190 * Match type [t1] against type [t2] as follows.
4191 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype
4192 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>`
4193 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'`
4194 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`,
4195 * such that `I<T0, .., Tn> <: t2`
4196 */
4197 List<DartType> matchTypes(DartType t1, DartType t2) =>
4198 (t1 is InterfaceType && t2 is InterfaceType) ? _matchTypes(t1, t2) : null;
4199
4200 /**
4201 * Pop a return type off of the return stack. 4173 * Pop a return type off of the return stack.
4202 * 4174 *
4203 * Also record any inferred return type using [setType], unless this node 4175 * Also record any inferred return type using [setType], unless this node
4204 * already has a context type. This recorded type will be the least upper 4176 * already has a context type. This recorded type will be the least upper
4205 * bound of all types added with [addReturnOrYieldType]. 4177 * bound of all types added with [addReturnOrYieldType].
4206 */ 4178 */
4207 void popReturnContext(BlockFunctionBody node) { 4179 void popReturnContext(BlockFunctionBody node) {
4208 if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) { 4180 if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) {
4209 DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance; 4181 DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance;
4210 DartType inferred = _inferredReturn.removeLast(); 4182 DartType inferred = _inferredReturn.removeLast();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4244 error = StrongModeCode.INFERRED_TYPE_ALLOCATION; 4216 error = StrongModeCode.INFERRED_TYPE_ALLOCATION;
4245 } else if (node is FunctionExpression) { 4217 } else if (node is FunctionExpression) {
4246 error = StrongModeCode.INFERRED_TYPE_CLOSURE; 4218 error = StrongModeCode.INFERRED_TYPE_CLOSURE;
4247 } else { 4219 } else {
4248 error = StrongModeCode.INFERRED_TYPE; 4220 error = StrongModeCode.INFERRED_TYPE;
4249 } 4221 }
4250 4222
4251 _errorReporter.reportErrorForNode(error, node, [node, type]); 4223 _errorReporter.reportErrorForNode(error, node, [node, type]);
4252 } 4224 }
4253 4225
4254 List<DartType> _matchTypes(InterfaceType t1, InterfaceType t2) {
4255 if (t1 == t2) {
4256 return t2.typeArguments;
4257 }
4258 List<DartType> tArgs1 = t1.typeArguments;
4259 List<DartType> tArgs2 = t2.typeArguments;
4260 // If t1 isn't a raw type, bail out
4261 if (tArgs1 != null && tArgs1.any((t) => !t.isDynamic)) {
4262 return null;
4263 }
4264
4265 // This is our inferred type argument list. We start at all dynamic,
4266 // and fill in with inferred types when we reach a match.
4267 List<DartType> actuals =
4268 new List<DartType>.filled(tArgs1.length, _typeProvider.dynamicType);
4269
4270 // When we find the supertype of t1 with the same
4271 // classname as t2 (see below), we have the following:
4272 // If t1 is an instantiation of a class T1<X0, ..., Xn>
4273 // and t2 is an instantiation of a class T2<Y0, ...., Ym>
4274 // of the form t2 = T2<S0, ..., Sm>
4275 // then we want to choose instantiations for the Xi
4276 // T0, ..., Tn such that T1<T0, ..., Tn> <: t2 .
4277 // To find this, we simply instantate T1 with
4278 // X0, ..., Xn, and then find its superclass
4279 // T2<T0', ..., Tn'>. We then solve the constraint
4280 // set T0' <: S0, ..., Tn' <: Sn for the Xi.
4281 // Currently, we only handle constraints where
4282 // the Ti' is one of the Xi'. If there are multiple
4283 // constraints on some Xi, we choose the lower of the
4284 // two (if it exists).
4285 bool permute(List<DartType> permutedArgs) {
4286 if (permutedArgs == null) {
4287 return false;
4288 }
4289 List<TypeParameterElement> ps = t1.typeParameters;
4290 List<DartType> ts = ps.map((p) => p.type).toList();
4291 for (int i = 0; i < permutedArgs.length; i++) {
4292 DartType tVar = permutedArgs[i];
4293 DartType tActual = tArgs2[i];
4294 int index = ts.indexOf(tVar);
4295 if (index >= 0 && _typeSystem.isSubtypeOf(tActual, actuals[index])) {
4296 actuals[index] = tActual;
4297 }
4298 }
4299 return actuals.any((x) => !x.isDynamic);
4300 }
4301
4302 // Look for the first supertype of t1 with the same class name as t2.
4303 bool match(InterfaceType t1, Set<Element> visited) {
4304 if (t1.element == t2.element) {
4305 return permute(t1.typeArguments);
4306 }
4307
4308 if (t1 == _typeProvider.objectType) {
4309 return false;
4310 }
4311
4312 Element element = t1.element;
4313 if (visited == null) {
4314 visited = new HashSet<Element>();
4315 }
4316 if (element == null || !visited.add(element)) {
4317 return false;
4318 }
4319 try {
4320 if (match(t1.superclass, visited)) {
4321 return true;
4322 }
4323
4324 List<InterfaceType> mixins = t1.mixins;
4325 int mixinLength = mixins.length;
4326 for (int i = 0; i < mixinLength; i++) {
4327 if (match(mixins[i], visited)) {
4328 return true;
4329 }
4330 }
4331
4332 List<InterfaceType> interfaces = t1.interfaces;
4333 int interfaceLength = interfaces.length;
4334 for (int j = 0; j < interfaceLength; j++) {
4335 if (match(interfaces[j], visited)) {
4336 return true;
4337 }
4338 }
4339 } finally {
4340 visited.remove(element);
4341 }
4342 return false;
4343 }
4344
4345 // We have that t1 = T1<dynamic, ..., dynamic>.
4346 // To match t1 against t2, we use the uninstantiated version
4347 // of t1, essentially treating it as an instantiation with
4348 // fresh variables, and solve for the variables.
4349 // t1.element.type will be of the form T1<X0, ..., Xn>
4350 if (!match(t1.element.type, null)) {
4351 return null;
4352 }
4353 DartType newT1 = t1.element.type.instantiate(actuals);
4354 // If we found a solution, return it.
4355 if (_typeSystem.isSubtypeOf(newT1, t2)) {
4356 return actuals;
4357 }
4358 return null;
4359 }
4360
4361 /** 4226 /**
4362 * Clear the type information assocated with [node]. 4227 * Clear the type information assocated with [node].
4363 */ 4228 */
4364 static void clearType(AstNode node) { 4229 static void clearType(AstNode node) {
4365 node?.setProperty(_typeProperty, null); 4230 node?.setProperty(_typeProperty, null);
4366 } 4231 }
4367 4232
4368 /** 4233 /**
4369 * Look for contextual type information attached to [node]. Returns 4234 * Look for contextual type information attached to [node], and returns
4370 * the type if found, otherwise null. 4235 * the type if found.
4371 * 4236 *
4372 * If [node] has a contextual union type like `T | Future<T>` this will be 4237 * If [node] has a contextual union type like `T | Future<T>` or a type that
4373 * returned. You can use [getType] if you prefer to only get the `T`. 4238 * contains `?` this will be returned. You can use [getValueContext] if you
4239 * prefer to eliminate the Future union, or [getType] to eliminate both.
4374 */ 4240 */
4375 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty); 4241 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty);
4376 4242
4377 /** 4243 /**
4378 * Look for a single contextual type attached to [node], and returns the type 4244 * Look for a single contextual type attached to [node], and returns the type
4379 * if found, otherwise null. 4245 * if found, otherwise null.
4380 * 4246 *
4381 * If [node] has a contextual union type like `T | Future<T>` this will 4247 * If [node] has a contextual union type like `T | Future<T>` this will
4382 * simplify it to only return `T`. If the caller can handle a union type, 4248 * simplify it to only return `T`. If the caller can handle a union type,
4383 * [getContext] should be used instead. 4249 * [getContext] should be used instead.
4384 */ 4250 */
4385 static DartType getType(AstNode node) { 4251 static DartType getType(AstNode node) {
4386 DartType t = getContext(node); 4252 DartType t = getContext(node);
4387 if (t is InterfaceType && t.isDartAsyncFutureOr) { 4253 if (t is InterfaceType && t.isDartAsyncFutureOr) {
4388 return t.typeArguments[0]; // The T in FutureOr<T> 4254 return _substituteForUnknown(t.typeArguments[0]); // The T in FutureOr<T>
4389 } 4255 }
4390 return t; 4256 return _substituteForUnknown(t);
4257 }
4258
4259 static DartType _substituteForUnknown(DartType t) {
4260 if (t == null) return null;
4261 // Since the type is being used for downwards inference, the expression
4262 // type E must be a subtype of the context type T, i.e. T is an upper bound.
4263 //
4264 // TODO(jmesserly): our downwards inference code is not designed to handle
Leaf 2017/02/17 06:41:21 What's the status of this? We have user facing Nu
Jennifer Messerly 2017/03/14 02:07:06 fixed! new code handles Null
4265 // the bottom type, so we need to prevent it from resulting here.
4266 // Instead use `dynamic`. See `UnknownInferredType.upperBoundForType`.
4267 return UnknownInferredType.substituteDynamic(t);
4391 } 4268 }
4392 4269
4393 /** 4270 /**
4394 * Attach contextual type information [type] to [node] for use during 4271 * Attach contextual type information [type] to [node] for use during
4395 * inference. 4272 * inference.
4396 */ 4273 */
4397 static void setType(AstNode node, DartType type) { 4274 static void setType(AstNode node, DartType type) {
4398 if (type == null || type.isDynamic) { 4275 if (type == null || type.isDynamic) {
4399 clearType(node); 4276 clearType(node);
4400 } else { 4277 } else {
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after
5434 assert(parent is PartOfDirective); 5311 assert(parent is PartOfDirective);
5435 } else { 5312 } else {
5436 elementAnnotationImpl.annotationAst = 5313 elementAnnotationImpl.annotationAst =
5437 new ConstantAstCloner().cloneNode(node); 5314 new ConstantAstCloner().cloneNode(node);
5438 } 5315 }
5439 return null; 5316 return null;
5440 } 5317 }
5441 5318
5442 @override 5319 @override
5443 Object visitArgumentList(ArgumentList node) { 5320 Object visitArgumentList(ArgumentList node) {
5444 DartType callerType = InferenceContext.getType(node); 5321 DartType callerType = InferenceContext.getContext(node);
5445 if (callerType is FunctionType) { 5322 if (callerType is FunctionType) {
5446 Map<String, DartType> namedParameterTypes = 5323 Map<String, DartType> namedParameterTypes =
5447 callerType.namedParameterTypes; 5324 callerType.namedParameterTypes;
5448 List<DartType> normalParameterTypes = callerType.normalParameterTypes; 5325 List<DartType> normalParameterTypes = callerType.normalParameterTypes;
5449 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes; 5326 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes;
5450 int normalCount = normalParameterTypes.length; 5327 int normalCount = normalParameterTypes.length;
5451 int optionalCount = optionalParameterTypes.length; 5328 int optionalCount = optionalParameterTypes.length;
5452 5329
5453 NodeList<Expression> arguments = node.arguments; 5330 NodeList<Expression> arguments = node.arguments;
5454 Iterable<Expression> positional = 5331 Iterable<Expression> positional =
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
6072 _currentFunctionBody = outerFunctionBody; 5949 _currentFunctionBody = outerFunctionBody;
6073 _enclosingFunction = outerFunction; 5950 _enclosingFunction = outerFunction;
6074 } 5951 }
6075 return null; 5952 return null;
6076 } 5953 }
6077 5954
6078 @override 5955 @override
6079 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 5956 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
6080 node.function?.accept(this); 5957 node.function?.accept(this);
6081 node.accept(elementResolver); 5958 node.accept(elementResolver);
6082 _inferArgumentTypesFromContext(node); 5959 _inferArgumentTypesForInvocation(node);
6083 node.argumentList?.accept(this); 5960 node.argumentList?.accept(this);
6084 node.accept(typeAnalyzer); 5961 node.accept(typeAnalyzer);
6085 return null; 5962 return null;
6086 } 5963 }
6087 5964
6088 @override 5965 @override
6089 Object visitFunctionTypeAlias(FunctionTypeAlias node) { 5966 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
6090 // Resolve the metadata in the library scope. 5967 // Resolve the metadata in the library scope.
6091 if (node.metadata != null) { 5968 if (node.metadata != null) {
6092 node.metadata.accept(this); 5969 node.metadata.accept(this);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
6170 <Map<VariableElement, DartType>>[]; 6047 <Map<VariableElement, DartType>>[];
6171 perBranchOverrides.add(thenOverrides); 6048 perBranchOverrides.add(thenOverrides);
6172 perBranchOverrides.add(elseOverrides); 6049 perBranchOverrides.add(elseOverrides);
6173 _overrideManager.mergeOverrides(perBranchOverrides); 6050 _overrideManager.mergeOverrides(perBranchOverrides);
6174 } 6051 }
6175 return null; 6052 return null;
6176 } 6053 }
6177 6054
6178 @override 6055 @override
6179 Object visitInstanceCreationExpression(InstanceCreationExpression node) { 6056 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
6180 TypeName classTypeName = node.constructorName.type;
6181 // TODO(leafp): Currently, we may re-infer types here, since we
6182 // sometimes resolve multiple times. We should really check that we
6183 // have not already inferred something. However, the obvious ways to
6184 // check this don't work, since we may have been instantiated
6185 // to bounds in an earlier phase, and we *do* want to do inference
6186 // in that case.
6187 if (classTypeName.typeArguments == null) {
6188 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first
6189 // valid instantiation `new C<Ti>`, if it exists.
6190 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
6191 // will become a valid possibility. Right now the only allowed union is
6192 // `T | Future<T>` so we can take a simple approach.
6193 for (var contextType in inferenceContext.getTypes(node)) {
6194 if (contextType is InterfaceType &&
6195 contextType.typeArguments != null &&
6196 contextType.typeArguments.isNotEmpty) {
6197 // TODO(jmesserly): for generic methods we use the
6198 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
6199 // be a tad more powerful than matchTypes.
6200 //
6201 // For example it can infer this case:
6202 //
6203 // class E<S, T> extends A<C<S>, T> { ... }
6204 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
6205 //
6206 // See _inferArgumentTypesFromContext in this file for use of it.
6207 List<DartType> targs =
6208 inferenceContext.matchTypes(classTypeName.type, contextType);
6209 if (targs != null && targs.any((t) => !t.isDynamic)) {
6210 ClassElement classElement =
6211 resolutionMap.typeForTypeName(classTypeName).element;
6212 InterfaceType rawType = classElement.type;
6213 InterfaceType fullType =
6214 rawType.substitute2(targs, rawType.typeArguments);
6215 // The element resolver uses the type on the constructor name, so
6216 // infer it first
6217 typeAnalyzer.inferConstructorName(node.constructorName, fullType);
6218 break;
6219 }
6220 }
6221 }
6222 }
6223 node.constructorName?.accept(this); 6057 node.constructorName?.accept(this);
6224 FunctionType constructorType = resolutionMap 6058 _inferArgumentTypesForInstanceCreate(node);
6225 .staticElementForConstructorReference(node.constructorName)
6226 ?.type;
6227 if (constructorType != null) {
6228 InferenceContext.setType(node.argumentList, constructorType);
6229 }
6230 node.argumentList?.accept(this); 6059 node.argumentList?.accept(this);
6231 node.accept(elementResolver); 6060 node.accept(elementResolver);
6232 node.accept(typeAnalyzer); 6061 node.accept(typeAnalyzer);
6233 return null; 6062 return null;
6234 } 6063 }
6235 6064
6236 @override 6065 @override
6237 Object visitLabel(Label node) => null; 6066 Object visitLabel(Label node) => null;
6238 6067
6239 @override 6068 @override
6240 Object visitLibraryIdentifier(LibraryIdentifier node) => null; 6069 Object visitLibraryIdentifier(LibraryIdentifier node) => null;
6241 6070
6242 @override 6071 @override
6243 Object visitListLiteral(ListLiteral node) { 6072 Object visitListLiteral(ListLiteral node) {
6244 DartType contextType = InferenceContext.getType(node); 6073 InterfaceType listT;
6245 List<DartType> targs = null; 6074
6246 if (node.typeArguments != null) { 6075 if (node.typeArguments != null) {
6247 targs = node.typeArguments.arguments.map((t) => t.type).toList(); 6076 var targs = node.typeArguments.arguments.map((t) => t.type).toList();
6248 } else if (contextType is InterfaceType) { 6077 if (targs.length == 1 && !targs[0].isDynamic) {
6249 InterfaceType listD = 6078 listT = typeProvider.listType.instantiate([targs[0]]);
6250 typeProvider.listType.instantiate([typeProvider.dynamicType]); 6079 }
6251 targs = inferenceContext.matchTypes(listD, contextType); 6080 } else if (strongMode) {
6081 listT = typeAnalyzer.inferListType(node, downwards: true);
6252 } 6082 }
6253 if (targs != null && targs.length == 1 && !targs[0].isDynamic) { 6083 if (listT != null) {
6254 DartType eType = targs[0]; 6084 DartType eType = listT.typeArguments[0];
6255 InterfaceType listT = typeProvider.listType.instantiate([eType]);
6256 for (Expression child in node.elements) { 6085 for (Expression child in node.elements) {
6257 InferenceContext.setType(child, eType); 6086 InferenceContext.setType(child, eType);
6258 } 6087 }
6259 InferenceContext.setType(node, listT); 6088 InferenceContext.setType(node, listT);
6260 } else { 6089 } else {
6261 InferenceContext.clearType(node); 6090 InferenceContext.clearType(node);
6262 } 6091 }
6263 super.visitListLiteral(node); 6092 super.visitListLiteral(node);
6264 return null; 6093 return null;
6265 } 6094 }
6266 6095
6267 @override 6096 @override
6268 Object visitMapLiteral(MapLiteral node) { 6097 Object visitMapLiteral(MapLiteral node) {
6269 DartType contextType = InferenceContext.getType(node); 6098 InterfaceType mapT;
6270 List<DartType> targs = null;
6271 if (node.typeArguments != null) { 6099 if (node.typeArguments != null) {
6272 targs = node.typeArguments.arguments.map((t) => t.type).toList(); 6100 var targs = node.typeArguments.arguments.map((t) => t.type).toList();
6273 } else if (contextType is InterfaceType) { 6101 if (targs.length == 2 && targs.any((t) => !t.isDynamic)) {
6274 InterfaceType mapD = typeProvider.mapType 6102 mapT = typeProvider.mapType.instantiate([targs[0], targs[1]]);
6275 .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]); 6103 }
6276 targs = inferenceContext.matchTypes(mapD, contextType); 6104 } else if (strongMode) {
6105 mapT = typeAnalyzer.inferMapType(node, downwards: true);
6277 } 6106 }
6278 if (targs != null && targs.length == 2 && targs.any((t) => !t.isDynamic)) { 6107 if (mapT != null) {
6279 DartType kType = targs[0]; 6108 DartType kType = mapT.typeArguments[0];
6280 DartType vType = targs[1]; 6109 DartType vType = mapT.typeArguments[1];
6281 InterfaceType mapT = typeProvider.mapType.instantiate([kType, vType]);
6282 for (MapLiteralEntry entry in node.entries) { 6110 for (MapLiteralEntry entry in node.entries) {
6283 InferenceContext.setType(entry.key, kType); 6111 InferenceContext.setType(entry.key, kType);
6284 InferenceContext.setType(entry.value, vType); 6112 InferenceContext.setType(entry.value, vType);
6285 } 6113 }
6286 InferenceContext.setType(node, mapT); 6114 InferenceContext.setType(node, mapT);
6287 } else { 6115 } else {
6288 InferenceContext.clearType(node); 6116 InferenceContext.clearType(node);
6289 } 6117 }
6290 super.visitMapLiteral(node); 6118 super.visitMapLiteral(node);
6291 return null; 6119 return null;
(...skipping 25 matching lines...) Expand all
6317 6145
6318 @override 6146 @override
6319 Object visitMethodInvocation(MethodInvocation node) { 6147 Object visitMethodInvocation(MethodInvocation node) {
6320 // 6148 //
6321 // We visit the target and argument list, but do not visit the method name 6149 // We visit the target and argument list, but do not visit the method name
6322 // because it needs to be visited in the context of the invocation. 6150 // because it needs to be visited in the context of the invocation.
6323 // 6151 //
6324 node.target?.accept(this); 6152 node.target?.accept(this);
6325 node.typeArguments?.accept(this); 6153 node.typeArguments?.accept(this);
6326 node.accept(elementResolver); 6154 node.accept(elementResolver);
6327 _inferArgumentTypesFromContext(node); 6155 _inferArgumentTypesForInvocation(node);
6328 node.argumentList?.accept(this); 6156 node.argumentList?.accept(this);
6329 node.accept(typeAnalyzer); 6157 node.accept(typeAnalyzer);
6330 return null; 6158 return null;
6331 } 6159 }
6332 6160
6333 @override 6161 @override
6334 Object visitNamedExpression(NamedExpression node) { 6162 Object visitNamedExpression(NamedExpression node) {
6335 InferenceContext.setTypeFromNode(node.expression, node); 6163 InferenceContext.setTypeFromNode(node.expression, node);
6336 return super.visitNamedExpression(node); 6164 return super.visitNamedExpression(node);
6337 } 6165 }
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
6610 6438
6611 // Ordinary functions just return their declared types. 6439 // Ordinary functions just return their declared types.
6612 if (!isGenerator && !isAsynchronous) { 6440 if (!isGenerator && !isAsynchronous) {
6613 return declaredType; 6441 return declaredType;
6614 } 6442 }
6615 if (declaredType is InterfaceType) { 6443 if (declaredType is InterfaceType) {
6616 if (isGenerator) { 6444 if (isGenerator) {
6617 // If it's sync* we expect Iterable<T> 6445 // If it's sync* we expect Iterable<T>
6618 // If it's async* we expect Stream<T> 6446 // If it's async* we expect Stream<T>
6619 InterfaceType rawType = isAsynchronous 6447 InterfaceType rawType = isAsynchronous
6620 ? typeProvider.streamDynamicType 6448 ? typeProvider.streamType
6621 : typeProvider.iterableDynamicType; 6449 : typeProvider.iterableType;
6622 // Match the types to instantiate the type arguments if possible 6450 // Match the types to instantiate the type arguments if possible
6623 List<DartType> typeArgs = 6451 List<DartType> targs = declaredType.typeArguments;
6624 inferenceContext.matchTypes(rawType, declaredType); 6452 if (targs.length == 1 && rawType.instantiate(targs) == declaredType) {
6625 return (typeArgs?.length == 1) ? typeArgs[0] : null; 6453 return targs[0];
6454 }
6626 } 6455 }
6627 // async functions expect `Future<T> | T` 6456 // async functions expect `Future<T> | T`
6628 var futureTypeParam = declaredType.flattenFutures(typeSystem); 6457 var futureTypeParam = declaredType.flattenFutures(typeSystem);
6629 return _createFutureOr(futureTypeParam); 6458 return _createFutureOr(futureTypeParam);
6630 } 6459 }
6631 return declaredType; 6460 return declaredType;
6632 } 6461 }
6633 6462
6634 /** 6463 /**
6635 * Creates a union of `T | Future<T>`, unless `T` is already a 6464 * Creates a union of `T | Future<T>`, unless `T` is already a
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
6714 if (executable is MethodElement) { 6543 if (executable is MethodElement) {
6715 return true; 6544 return true;
6716 } 6545 }
6717 if (executable is FunctionElement) { 6546 if (executable is FunctionElement) {
6718 return executable.enclosingElement is CompilationUnitElement; 6547 return executable.enclosingElement is CompilationUnitElement;
6719 } 6548 }
6720 } 6549 }
6721 return false; 6550 return false;
6722 } 6551 }
6723 6552
6724 void _inferArgumentTypesFromContext(InvocationExpression node) { 6553 FunctionType _inferArgumentTypesForGeneric(
6554 AstNode inferenceNode,
6555 DartType uninstantiatedType,
6556 TypeArgumentList typeArguments,
6557 {AstNode errorNode}) {
6558 errorNode ??= inferenceNode;
6559 TypeSystem ts = typeSystem;
6560 if (typeArguments == null &&
6561 uninstantiatedType is FunctionType &&
6562 uninstantiatedType.typeFormals.isNotEmpty &&
6563 ts is StrongTypeSystemImpl) {
6564 return ts.inferGenericFunctionOrType/*<FunctionType>*/(
6565 uninstantiatedType,
6566 ParameterElement.EMPTY_LIST,
6567 DartType.EMPTY_LIST,
6568 uninstantiatedType.returnType,
6569 InferenceContext.getContext(inferenceNode),
6570 downwards: true,
6571 errorReporter: errorReporter,
6572 errorNode: errorNode);
6573 }
6574 return null;
6575 }
6576
6577 void _inferArgumentTypesForInstanceCreate(InstanceCreationExpression node) {
6578 ConstructorName constructor = node.constructorName;
6579 TypeName classTypeName = constructor?.type;
6580 if (classTypeName == null || !strongMode) {
6581 return;
6582 }
6583
6584 ConstructorElement originalElement =
6585 resolutionMap.staticElementForConstructorReference(constructor);
6586 FunctionType inferred;
6587 // If the constructor is generic, we'll have a ConstructorMember that
6588 // substitutes in type arguments (possibly `dynamic`) from earlier in
6589 // resolution.
6590 //
6591 // Otherwise we'll have a ConstructorElement, and we can skip inference
6592 // because there's nothing to infer in a non-generic type.
6593 if (classTypeName.typeArguments == null &&
6594 originalElement is ConstructorMember) {
6595 // TODO(leafp): Currently, we may re-infer types here, since we
6596 // sometimes resolve multiple times. We should really check that we
6597 // have not already inferred something. However, the obvious ways to
6598 // check this don't work, since we may have been instantiated
6599 // to bounds in an earlier phase, and we *do* want to do inference
6600 // in that case.
6601
6602 // Get back to the uninstantiated generic constructor.
6603 // TODO(jmesserly): should we store this earlier in resolution?
6604 // Or look it up, instead of jumping backwards through the Member?
6605 var rawElement = originalElement.baseElement;
6606
6607 FunctionType constructorType =
6608 typeAnalyzer.constructorToGenericFunctionType(rawElement);
6609
6610 inferred = _inferArgumentTypesForGeneric(node, constructorType,
6611 constructor.type.typeArguments, errorNode: node.constructorName);
6612
6613 if (inferred != null) {
6614 ArgumentList arguments = node.argumentList;
6615 InferenceContext.setType(arguments, inferred);
6616 // Fix up the parameter elements based on inferred method.
6617 arguments.correspondingStaticParameters =
6618 resolveArgumentsToParameters(arguments, inferred.parameters, null);
6619
6620 constructor.type.type = inferred.returnType;
6621 if (!UnknownInferredType.typeIsUnknown(inferred)) {
6622 inferenceContext.recordInference(node, inferred.returnType);
6623 }
6624
6625 // Update the static element as well. This is used in some cases, such
6626 // as computing constant values. It is stored in two places.
6627 constructor.staticElement =
6628 ConstructorMember.from(rawElement, inferred.returnType);
6629 node.staticElement = constructor.staticElement;
6630 }
6631 }
6632
6633 if (inferred == null) {
6634 InferenceContext.setType(node.argumentList, originalElement?.type);
6635 }
6636 }
6637
6638 void _inferArgumentTypesForInvocation(InvocationExpression node) {
6725 if (!strongMode) { 6639 if (!strongMode) {
6726 // Use propagated type inference for lambdas if not in strong mode. 6640 // Use propagated type inference for lambdas if not in strong mode.
6727 _inferFunctionExpressionsParametersTypes(node.argumentList); 6641 _inferFunctionExpressionsParametersTypes(node.argumentList);
6728 return; 6642 return;
6729 } 6643 }
6730 6644 DartType inferred = _inferArgumentTypesForGeneric(node,
6731 DartType contextType = node.staticInvokeType; 6645 node.function.staticType, node.typeArguments);
6732 if (contextType is FunctionType) { 6646 InferenceContext.setType(
6733 DartType originalType = node.function.staticType; 6647 node.argumentList, inferred ?? node.staticInvokeType);
6734 DartType returnContextType = InferenceContext.getContext(node);
6735 TypeSystem ts = typeSystem;
6736 if (returnContextType != null &&
6737 node.typeArguments == null &&
6738 originalType is FunctionType &&
6739 originalType.typeFormals.isNotEmpty &&
6740 ts is StrongTypeSystemImpl) {
6741 contextType = ts.inferGenericFunctionCall(
6742 originalType,
6743 DartType.EMPTY_LIST,
6744 DartType.EMPTY_LIST,
6745 originalType.returnType,
6746 returnContextType);
6747 }
6748
6749 InferenceContext.setType(node.argumentList, contextType);
6750 }
6751 } 6648 }
6752 6649
6753 void _inferFormalParameterList(FormalParameterList node, DartType type) { 6650 void _inferFormalParameterList(FormalParameterList node, DartType type) {
6754 if (typeAnalyzer.inferFormalParameterList(node, type)) { 6651 if (typeAnalyzer.inferFormalParameterList(node, type)) {
6755 // TODO(leafp): This gets dropped on the floor if we're in the field 6652 // TODO(leafp): This gets dropped on the floor if we're in the field
6756 // inference task. We should probably keep these infos. 6653 // inference task. We should probably keep these infos.
6757 // 6654 //
6758 // TODO(jmesserly): this is reporting the context type, and therefore not 6655 // TODO(jmesserly): this is reporting the context type, and therefore not
6759 // necessarily the correct inferred type for the lambda. 6656 // necessarily the correct inferred type for the lambda.
6760 // 6657 //
(...skipping 4078 matching lines...) Expand 10 before | Expand all | Expand 10 after
10839 return null; 10736 return null;
10840 } 10737 }
10841 if (identical(node.staticElement, variable)) { 10738 if (identical(node.staticElement, variable)) {
10842 if (node.inSetterContext()) { 10739 if (node.inSetterContext()) {
10843 result = true; 10740 result = true;
10844 } 10741 }
10845 } 10742 }
10846 return null; 10743 return null;
10847 } 10744 }
10848 } 10745 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698