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 4080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |