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

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

Issue 2295853002: fix #26992, inference failures are now an error (Closed)
Patch Set: fix comment Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.type_system; 5 library analyzer.src.generated.type_system;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:math' as math; 8 import 'dart:math' as math;
9 9
10 import 'package:analyzer/dart/ast/ast.dart' show AstNode;
10 import 'package:analyzer/dart/ast/token.dart' show TokenType; 11 import 'package:analyzer/dart/ast/token.dart' show TokenType;
11 import 'package:analyzer/dart/element/element.dart'; 12 import 'package:analyzer/dart/element/element.dart';
12 import 'package:analyzer/dart/element/type.dart'; 13 import 'package:analyzer/dart/element/type.dart';
13 import 'package:analyzer/src/dart/element/element.dart'; 14 import 'package:analyzer/src/dart/element/element.dart';
14 import 'package:analyzer/src/dart/element/type.dart'; 15 import 'package:analyzer/src/dart/element/type.dart';
15 import 'package:analyzer/src/generated/engine.dart' 16 import 'package:analyzer/src/generated/engine.dart'
16 show AnalysisContext, AnalysisOptionsImpl; 17 show AnalysisContext, AnalysisOptionsImpl;
18 import 'package:analyzer/src/generated/error.dart'
19 show ErrorCode, ErrorReporter, StrongModeCode;
17 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 20 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
18 import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind; 21 import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
19 import 'package:analyzer/src/generated/utilities_general.dart' 22 import 'package:analyzer/src/generated/utilities_general.dart'
20 show JenkinsSmiHash; 23 show JenkinsSmiHash;
21 24
22 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited); 25 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
23 26
24 /** 27 /**
25 * Implementation of [TypeSystem] using the strong mode rules. 28 * Implementation of [TypeSystem] using the strong mode rules.
26 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md 29 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 244
242 // Try to infer and instantiate the resulting type. 245 // Try to infer and instantiate the resulting type.
243 var resultType = inferringTypeSystem._infer(fnType); 246 var resultType = inferringTypeSystem._infer(fnType);
244 247
245 // If the instantiation failed (because some type variable constraints 248 // If the instantiation failed (because some type variable constraints
246 // could not be solved, in other words, we could not find a valid subtype), 249 // could not be solved, in other words, we could not find a valid subtype),
247 // then return the original type, so the error is in terms of it. 250 // then return the original type, so the error is in terms of it.
248 // 251 //
249 // It would be safe to return a partial solution here, but the user 252 // It would be safe to return a partial solution here, but the user
250 // experience may be better if we simply do not infer in this case. 253 // experience may be better if we simply do not infer in this case.
254 //
255 // TODO(jmesserly): this heuristic is old. Maybe we should we issue the
256 // inference error?
251 return resultType ?? fnType; 257 return resultType ?? fnType;
252 } 258 }
253 259
254 /// Given a function type with generic type parameters, infer the type 260 /// Given a function type with generic type parameters, infer the type
255 /// parameters from the actual argument types, and return the instantiated 261 /// parameters from the actual argument types, and return the instantiated
256 /// function type. If we can't, returns the original function type. 262 /// function type. If we can't, returns the original function type.
257 /// 263 ///
258 /// Concretely, given a function type with parameter types P0, P1, ... Pn, 264 /// Concretely, given a function type with parameter types P0, P1, ... Pn,
259 /// result type R, and generic type parameters T0, T1, ... Tm, use the 265 /// result type R, and generic type parameters T0, T1, ... Tm, use the
260 /// argument types A0, A1, ... An to solve for the type parameters. 266 /// argument types A0, A1, ... An to solve for the type parameters.
261 /// 267 ///
262 /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by 268 /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by
263 /// running the subtype algorithm, and when we reach a type parameter Tj, 269 /// running the subtype algorithm, and when we reach a type parameter Tj,
264 /// recording the lower or upper bound it must satisfy. At the end, all 270 /// recording the lower or upper bound it must satisfy. At the end, all
265 /// constraints can be combined to determine the type. 271 /// constraints can be combined to determine the type.
266 /// 272 ///
267 /// As a simplification, we do not actually store all constraints on each type 273 /// As a simplification, we do not actually store all constraints on each type
268 /// parameter Tj. Instead we track Uj and Lj where U is the upper bound and 274 /// parameter Tj. Instead we track Uj and Lj where U is the upper bound and
269 /// L is the lower bound of that type parameter. 275 /// L is the lower bound of that type parameter.
270 FunctionType inferGenericFunctionCall( 276 FunctionType inferGenericFunctionCall(
271 TypeProvider typeProvider, 277 TypeProvider typeProvider,
272 FunctionType fnType, 278 FunctionType fnType,
273 List<DartType> correspondingParameterTypes, 279 List<DartType> correspondingParameterTypes,
274 List<DartType> argumentTypes, 280 List<DartType> argumentTypes,
275 DartType returnContextType) { 281 DartType returnContextType,
282 {ErrorReporter errorReporter,
283 AstNode errorNode}) {
276 if (fnType.typeFormals.isEmpty) { 284 if (fnType.typeFormals.isEmpty) {
277 return fnType; 285 return fnType;
278 } 286 }
279 287
280 // If we're in a future union context, choose either the Future<T> or the T 288 // If we're in a future union context, choose either the Future<T> or the T
281 // based on the function's return type. 289 // based on the function's return type.
282 if (returnContextType is FutureUnionType) { 290 if (returnContextType is FutureUnionType) {
283 var futureUnion = returnContextType as FutureUnionType; 291 var futureUnion = returnContextType as FutureUnionType;
284 returnContextType = 292 returnContextType =
285 isSubtypeOf(fnType.returnType, typeProvider.futureDynamicType) 293 isSubtypeOf(fnType.returnType, typeProvider.futureDynamicType)
(...skipping 12 matching lines...) Expand all
298 inferringTypeSystem.isSubtypeOf(fnType.returnType, returnContextType); 306 inferringTypeSystem.isSubtypeOf(fnType.returnType, returnContextType);
299 } 307 }
300 308
301 for (int i = 0; i < argumentTypes.length; i++) { 309 for (int i = 0; i < argumentTypes.length; i++) {
302 // Try to pass each argument to each parameter, recording any type 310 // Try to pass each argument to each parameter, recording any type
303 // parameter bounds that were implied by this assignment. 311 // parameter bounds that were implied by this assignment.
304 inferringTypeSystem.isSubtypeOf( 312 inferringTypeSystem.isSubtypeOf(
305 argumentTypes[i], correspondingParameterTypes[i]); 313 argumentTypes[i], correspondingParameterTypes[i]);
306 } 314 }
307 315
308 return inferringTypeSystem._infer(fnType); 316 return inferringTypeSystem._infer(fnType, errorReporter, errorNode);
309 } 317 }
310 318
311 /** 319 /**
312 * Given a [DartType] [type], if [type] is an uninstantiated 320 * Given a [DartType] [type], if [type] is an uninstantiated
313 * parameterized type then instantiate the parameters to their 321 * parameterized type then instantiate the parameters to their
314 * bounds. Specifically, if [type] is of the form 322 * bounds. Specifically, if [type] is of the form
315 * `<T0 extends B0, ... Tn extends Bn>.F` or 323 * `<T0 extends B0, ... Tn extends Bn>.F` or
316 * `class C<T0 extends B0, ... Tn extends Bn> {...}` 324 * `class C<T0 extends B0, ... Tn extends Bn> {...}`
317 * (where Bi is implicitly dynamic if absent), 325 * (where Bi is implicitly dynamic if absent),
318 * compute `{I0/T0, ..., In/Tn}F or C<I0, ..., In>` respectively 326 * compute `{I0/T0, ..., In/Tn}F or C<I0, ..., In>` respectively
(...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 final StrongTypeSystemImpl _typeSystem; 1372 final StrongTypeSystemImpl _typeSystem;
1365 final Map<TypeParameterType, _TypeParameterBound> _bounds; 1373 final Map<TypeParameterType, _TypeParameterBound> _bounds;
1366 1374
1367 _StrongInferenceTypeSystem(this._typeProvider, this._typeSystem, 1375 _StrongInferenceTypeSystem(this._typeProvider, this._typeSystem,
1368 Iterable<TypeParameterElement> typeFormals) 1376 Iterable<TypeParameterElement> typeFormals)
1369 : _bounds = new Map.fromIterable(typeFormals, 1377 : _bounds = new Map.fromIterable(typeFormals,
1370 key: (t) => t.type, value: (t) => new _TypeParameterBound()); 1378 key: (t) => t.type, value: (t) => new _TypeParameterBound());
1371 1379
1372 /// Given the constraints that were given by calling [isSubtypeOf], find the 1380 /// Given the constraints that were given by calling [isSubtypeOf], find the
1373 /// instantiation of the generic function that satisfies these constraints. 1381 /// instantiation of the generic function that satisfies these constraints.
1374 FunctionType _infer(FunctionType fnType) { 1382 FunctionType _infer(FunctionType fnType,
1383 [ErrorReporter errorReporter, AstNode errorNode]) {
1375 List<TypeParameterType> fnTypeParams = 1384 List<TypeParameterType> fnTypeParams =
1376 TypeParameterTypeImpl.getTypes(fnType.typeFormals); 1385 TypeParameterTypeImpl.getTypes(fnType.typeFormals);
1377 1386
1378 // Initialize the inferred type array. 1387 // Initialize the inferred type array.
1379 // 1388 //
1380 // They all start as `dynamic` to offer reasonable degradation for f-bounded 1389 // They all start as `dynamic` to offer reasonable degradation for f-bounded
1381 // type parameters. 1390 // type parameters.
1382 var inferredTypes = new List<DartType>.filled( 1391 var inferredTypes = new List<DartType>.filled(
1383 fnTypeParams.length, DynamicTypeImpl.instance, 1392 fnTypeParams.length, DynamicTypeImpl.instance,
1384 growable: false); 1393 growable: false);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 // if the type parameter occurs in covariant or contravariant positions. 1425 // if the type parameter occurs in covariant or contravariant positions.
1417 // 1426 //
1418 // If the type is "passed in" at all, or if our lower bound was bottom, 1427 // If the type is "passed in" at all, or if our lower bound was bottom,
1419 // we choose the upper bound as being the most useful. 1428 // we choose the upper bound as being the most useful.
1420 // 1429 //
1421 // Otherwise we choose the more precise lower bound. 1430 // Otherwise we choose the more precise lower bound.
1422 _TypeParameterVariance variance = 1431 _TypeParameterVariance variance =
1423 new _TypeParameterVariance.from(typeParam, fnType.returnType); 1432 new _TypeParameterVariance.from(typeParam, fnType.returnType);
1424 1433
1425 _TypeParameterBound bound = _bounds[typeParam]; 1434 _TypeParameterBound bound = _bounds[typeParam];
1426 inferredTypes[i] = 1435 DartType lowerBound = bound.lower;
1427 variance.passedIn || bound.lower.isBottom ? bound.upper : bound.lower; 1436 DartType upperBound = bound.upper;
1428 1437
1429 // See if the bounds can be satisfied. 1438 // See if the bounds can be satisfied.
1430 if (bound.upper.isBottom || 1439 // TODO(jmesserly): also we should have an error for unconstrained type
1431 !_typeSystem.isSubtypeOf(bound.lower, bound.upper)) { 1440 // parameters, rather than silently inferring dynamic.
1432 // Inference failed. Bail. 1441 if (upperBound.isBottom ||
1433 return null; 1442 !_typeSystem.isSubtypeOf(lowerBound, upperBound)) {
1443 // Inference failed.
1444 if (errorReporter == null) {
1445 return null;
1446 }
1447 errorReporter.reportErrorForNode(StrongModeCode.COULD_NOT_INFER,
1448 errorNode, [typeParam, lowerBound, upperBound]);
1449
1450 // To make the errors more useful, we swap the normal heuristic.
1451 //
1452 // The normal heuristic prefers using the argument types (upwards
1453 // inference, lower bound) to choose a tighter type.
1454 //
1455 // Here we want to prefer the return context type, so we can put the
1456 // blame on the arguments to the function. That will result in narrow
1457 // error spans. But ultimately it's just a heuristic, as the code is
1458 // already erroneous.
1459 //
1460 // (we may adjust the normal heuristic too, once upwards+downwards
1461 // inference are fully integrated, to prefer downwards info).
1462 lowerBound = bound.upper;
1463 upperBound = bound.lower;
1434 } 1464 }
1465
1466 inferredTypes[i] =
1467 variance.passedIn || lowerBound.isBottom ? upperBound : lowerBound;
1435 } 1468 }
1436 1469
1437 // Return the instantiated type. 1470 // Return the instantiated type.
1438 return fnType.instantiate(inferredTypes); 1471 return fnType.instantiate(inferredTypes);
1439 } 1472 }
1440 1473
1441 @override 1474 @override
1442 bool _inferTypeParameterSubtypeOf( 1475 bool _inferTypeParameterSubtypeOf(
1443 DartType t1, DartType t2, Set<Element> visited) { 1476 DartType t1, DartType t2, Set<Element> visited) {
1444 if (t1 is TypeParameterType) { 1477 if (t1 is TypeParameterType) {
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1698 } 1731 }
1699 1732
1700 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { 1733 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
1701 return (t.isDynamic && dynamicIsBottom) || t.isBottom; 1734 return (t.isDynamic && dynamicIsBottom) || t.isBottom;
1702 } 1735 }
1703 1736
1704 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { 1737 bool _isTop(DartType t, {bool dynamicIsBottom: false}) {
1705 // TODO(leafp): Document the rules in play here 1738 // TODO(leafp): Document the rules in play here
1706 return (t.isDynamic && !dynamicIsBottom) || t.isObject; 1739 return (t.isDynamic && !dynamicIsBottom) || t.isObject;
1707 } 1740 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/static_type_analyzer.dart ('k') | pkg/analyzer/test/src/task/strong/checker_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698