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 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 |