Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |