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

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

Issue 2343713002: fix #27151, list and map literals infer using up and down info (Closed)
Patch Set: format 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/ast.dart' show AstNode;
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 356
357 // Since we're trying to infer the instantiation, we want to ignore type 357 // Since we're trying to infer the instantiation, we want to ignore type
358 // formals as we check the parameters and return type. 358 // formals as we check the parameters and return type.
359 var inferFnType = 359 var inferFnType =
360 fnType.instantiate(TypeParameterTypeImpl.getTypes(fnType.typeFormals)); 360 fnType.instantiate(TypeParameterTypeImpl.getTypes(fnType.typeFormals));
361 if (!inferringTypeSystem.isSubtypeOf(inferFnType, contextType)) { 361 if (!inferringTypeSystem.isSubtypeOf(inferFnType, contextType)) {
362 return fnType; 362 return fnType;
363 } 363 }
364 364
365 // Try to infer and instantiate the resulting type. 365 // Try to infer and instantiate the resulting type.
366 var resultType = inferringTypeSystem._infer(fnType); 366 var resultType = inferringTypeSystem._infer(
367 fnType, fnType.typeFormals, fnType.returnType);
367 368
368 // If the instantiation failed (because some type variable constraints 369 // If the instantiation failed (because some type variable constraints
369 // could not be solved, in other words, we could not find a valid subtype), 370 // could not be solved, in other words, we could not find a valid subtype),
370 // then return the original type, so the error is in terms of it. 371 // then return the original type, so the error is in terms of it.
371 // 372 //
372 // It would be safe to return a partial solution here, but the user 373 // It would be safe to return a partial solution here, but the user
373 // experience may be better if we simply do not infer in this case. 374 // experience may be better if we simply do not infer in this case.
374 // 375 //
375 // TODO(jmesserly): this heuristic is old. Maybe we should we issue the 376 // TODO(jmesserly): this heuristic is old. Maybe we should we issue the
376 // inference error? 377 // inference error?
377 return resultType ?? fnType; 378 return resultType ?? fnType;
378 } 379 }
379 380
380 /// Given a function type with generic type parameters, infer the type 381 /// Given a function type with generic type parameters, infer the type
381 /// parameters from the actual argument types, and return the instantiated 382 /// parameters from the actual argument types, and return the instantiated
382 /// function type. If we can't, returns the original function type. 383 /// function type. If we can't, returns the original function type.
383 /// 384 ///
384 /// Concretely, given a function type with parameter types P0, P1, ... Pn, 385 /// Concretely, given a function type with parameter types P0, P1, ... Pn,
385 /// result type R, and generic type parameters T0, T1, ... Tm, use the 386 /// result type R, and generic type parameters T0, T1, ... Tm, use the
386 /// argument types A0, A1, ... An to solve for the type parameters. 387 /// argument types A0, A1, ... An to solve for the type parameters.
387 /// 388 ///
388 /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by 389 /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by
389 /// running the subtype algorithm, and when we reach a type parameter Tj, 390 /// running the subtype algorithm, and when we reach a type parameter Tj,
390 /// recording the lower or upper bound it must satisfy. At the end, all 391 /// recording the lower or upper bound it must satisfy. At the end, all
391 /// constraints can be combined to determine the type. 392 /// constraints can be combined to determine the type.
392 /// 393 ///
393 /// As a simplification, we do not actually store all constraints on each type 394 /// As a simplification, we do not actually store all constraints on each type
394 /// parameter Tj. Instead we track Uj and Lj where U is the upper bound and 395 /// parameter Tj. Instead we track Uj and Lj where U is the upper bound and
395 /// L is the lower bound of that type parameter. 396 /// L is the lower bound of that type parameter.
396 FunctionType inferGenericFunctionCall( 397 /*=T*/ inferGenericFunctionCall/*<T extends ParameterizedType>*/(
397 TypeProvider typeProvider, 398 TypeProvider typeProvider,
398 FunctionType fnType, 399 /*=T*/ genericType,
399 List<DartType> correspondingParameterTypes, 400 List<DartType> declaredParameterTypes,
400 List<DartType> argumentTypes, 401 List<DartType> argumentTypes,
402 DartType declaredReturnType,
401 DartType returnContextType, 403 DartType returnContextType,
402 {ErrorReporter errorReporter, 404 {ErrorReporter errorReporter,
403 AstNode errorNode}) { 405 AstNode errorNode}) {
404 if (fnType.typeFormals.isEmpty) { 406 // TODO(jmesserly): expose typeFormals on ParameterizedType.
405 return fnType; 407 List<TypeParameterElement> typeFormals = genericType is FunctionType
406 } 408 ? genericType.typeFormals
407 409 : genericType.typeParameters;
408 // If we're in a future union context, choose either the Future<T> or the T 410 if (typeFormals.isEmpty) {
409 // based on the function's return type. 411 return genericType;
410 if (returnContextType is FutureUnionType) {
411 var futureUnion = returnContextType as FutureUnionType;
412 returnContextType =
413 isSubtypeOf(fnType.returnType, typeProvider.futureDynamicType)
414 ? futureUnion.futureOfType
415 : futureUnion.type;
416 } 412 }
417 413
418 // Create a TypeSystem that will allow certain type parameters to be 414 // Create a TypeSystem that will allow certain type parameters to be
419 // inferred. It will optimistically assume these type parameters can be 415 // inferred. It will optimistically assume these type parameters can be
420 // subtypes (or supertypes) as necessary, and track the constraints that 416 // subtypes (or supertypes) as necessary, and track the constraints that
421 // are implied by this. 417 // are implied by this.
422 var inferringTypeSystem = 418 var inferringTypeSystem =
423 new _StrongInferenceTypeSystem(typeProvider, this, fnType.typeFormals); 419 new _StrongInferenceTypeSystem(typeProvider, this, typeFormals);
424 420
425 if (returnContextType != null) { 421 if (returnContextType != null) {
426 inferringTypeSystem.isSubtypeOf(fnType.returnType, returnContextType); 422 // If we're in a future union context, choose either the Future<T>
423 // or the T based on the declared return type.
424 if (returnContextType is FutureUnionType) {
425 var futureUnion = returnContextType as FutureUnionType;
426 returnContextType =
427 isSubtypeOf(declaredReturnType, typeProvider.futureDynamicType)
428 ? futureUnion.futureOfType
429 : futureUnion.type;
430 }
431
432 inferringTypeSystem.isSubtypeOf(declaredReturnType, returnContextType);
427 } 433 }
428 434
429 for (int i = 0; i < argumentTypes.length; i++) { 435 for (int i = 0; i < argumentTypes.length; i++) {
430 // Try to pass each argument to each parameter, recording any type 436 // Try to pass each argument to each parameter, recording any type
431 // parameter bounds that were implied by this assignment. 437 // parameter bounds that were implied by this assignment.
432 inferringTypeSystem.isSubtypeOf( 438 inferringTypeSystem.isSubtypeOf(
433 argumentTypes[i], correspondingParameterTypes[i]); 439 argumentTypes[i], declaredParameterTypes[i]);
434 } 440 }
435 441
436 return inferringTypeSystem._infer(fnType, errorReporter, errorNode); 442 return inferringTypeSystem._infer(
443 genericType, typeFormals, declaredReturnType, errorReporter, errorNode);
437 } 444 }
438 445
439 /** 446 /**
440 * Given a [DartType] [type], if [type] is an uninstantiated 447 * Given a [DartType] [type], if [type] is an uninstantiated
441 * parameterized type then instantiate the parameters to their 448 * parameterized type then instantiate the parameters to their
442 * bounds. Specifically, if [type] is of the form 449 * bounds. Specifically, if [type] is of the form
443 * `<T0 extends B0, ... Tn extends Bn>.F` or 450 * `<T0 extends B0, ... Tn extends Bn>.F` or
444 * `class C<T0 extends B0, ... Tn extends Bn> {...}` 451 * `class C<T0 extends B0, ... Tn extends Bn> {...}`
445 * (where Bi is implicitly dynamic if absent), 452 * (where Bi is implicitly dynamic if absent),
446 * compute `{I0/T0, ..., In/Tn}F or C<I0, ..., In>` respectively 453 * compute `{I0/T0, ..., In/Tn}F or C<I0, ..., In>` respectively
(...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 final StrongTypeSystemImpl _typeSystem; 1511 final StrongTypeSystemImpl _typeSystem;
1505 final Map<TypeParameterType, _TypeParameterBound> _bounds; 1512 final Map<TypeParameterType, _TypeParameterBound> _bounds;
1506 1513
1507 _StrongInferenceTypeSystem(this._typeProvider, this._typeSystem, 1514 _StrongInferenceTypeSystem(this._typeProvider, this._typeSystem,
1508 Iterable<TypeParameterElement> typeFormals) 1515 Iterable<TypeParameterElement> typeFormals)
1509 : _bounds = new Map.fromIterable(typeFormals, 1516 : _bounds = new Map.fromIterable(typeFormals,
1510 key: (t) => t.type, value: (t) => new _TypeParameterBound()); 1517 key: (t) => t.type, value: (t) => new _TypeParameterBound());
1511 1518
1512 /// Given the constraints that were given by calling [isSubtypeOf], find the 1519 /// Given the constraints that were given by calling [isSubtypeOf], find the
1513 /// instantiation of the generic function that satisfies these constraints. 1520 /// instantiation of the generic function that satisfies these constraints.
1514 FunctionType _infer(FunctionType fnType, 1521 /*=T*/ _infer/*<T extends ParameterizedType>*/(/*=T*/ genericType,
1522 List<TypeParameterElement> typeFormals, DartType declaredReturnType,
1515 [ErrorReporter errorReporter, AstNode errorNode]) { 1523 [ErrorReporter errorReporter, AstNode errorNode]) {
1516 List<TypeParameterType> fnTypeParams = 1524 List<TypeParameterType> fnTypeParams =
1517 TypeParameterTypeImpl.getTypes(fnType.typeFormals); 1525 TypeParameterTypeImpl.getTypes(typeFormals);
1518 1526
1519 // Initialize the inferred type array. 1527 // Initialize the inferred type array.
1520 // 1528 //
1521 // They all start as `dynamic` to offer reasonable degradation for f-bounded 1529 // They all start as `dynamic` to offer reasonable degradation for f-bounded
1522 // type parameters. 1530 // type parameters.
1523 var inferredTypes = new List<DartType>.filled( 1531 var inferredTypes = new List<DartType>.filled(
1524 fnTypeParams.length, DynamicTypeImpl.instance, 1532 fnTypeParams.length, DynamicTypeImpl.instance,
1525 growable: false); 1533 growable: false);
1526 1534
1527 for (int i = 0; i < fnTypeParams.length; i++) { 1535 for (int i = 0; i < fnTypeParams.length; i++) {
(...skipping 26 matching lines...) Expand all
1554 // Now we've computed lower and upper bounds for each type parameter. 1562 // Now we've computed lower and upper bounds for each type parameter.
1555 // 1563 //
1556 // To decide on which type to assign, we look at the return type and see 1564 // To decide on which type to assign, we look at the return type and see
1557 // if the type parameter occurs in covariant or contravariant positions. 1565 // if the type parameter occurs in covariant or contravariant positions.
1558 // 1566 //
1559 // If the type is "passed in" at all, or if our lower bound was bottom, 1567 // If the type is "passed in" at all, or if our lower bound was bottom,
1560 // we choose the upper bound as being the most useful. 1568 // we choose the upper bound as being the most useful.
1561 // 1569 //
1562 // Otherwise we choose the more precise lower bound. 1570 // Otherwise we choose the more precise lower bound.
1563 _TypeParameterVariance variance = 1571 _TypeParameterVariance variance =
1564 new _TypeParameterVariance.from(typeParam, fnType.returnType); 1572 new _TypeParameterVariance.from(typeParam, declaredReturnType);
1565 1573
1566 _TypeParameterBound bound = _bounds[typeParam]; 1574 _TypeParameterBound bound = _bounds[typeParam];
1567 DartType lowerBound = bound.lower; 1575 DartType lowerBound = bound.lower;
1568 DartType upperBound = bound.upper; 1576 DartType upperBound = bound.upper;
1569 1577
1570 // See if the bounds can be satisfied. 1578 // See if the bounds can be satisfied.
1571 // TODO(jmesserly): also we should have an error for unconstrained type 1579 // TODO(jmesserly): also we should have an error for unconstrained type
1572 // parameters, rather than silently inferring dynamic. 1580 // parameters, rather than silently inferring dynamic.
1573 if (upperBound.isBottom || 1581 if (upperBound.isBottom ||
1574 !_typeSystem.isSubtypeOf(lowerBound, upperBound)) { 1582 !_typeSystem.isSubtypeOf(lowerBound, upperBound)) {
(...skipping 18 matching lines...) Expand all
1593 // inference are fully integrated, to prefer downwards info). 1601 // inference are fully integrated, to prefer downwards info).
1594 lowerBound = bound.upper; 1602 lowerBound = bound.upper;
1595 upperBound = bound.lower; 1603 upperBound = bound.lower;
1596 } 1604 }
1597 1605
1598 inferredTypes[i] = 1606 inferredTypes[i] =
1599 variance.passedIn || lowerBound.isBottom ? upperBound : lowerBound; 1607 variance.passedIn || lowerBound.isBottom ? upperBound : lowerBound;
1600 } 1608 }
1601 1609
1602 // Return the instantiated type. 1610 // Return the instantiated type.
1603 return fnType.instantiate(inferredTypes); 1611 return genericType.instantiate(inferredTypes) as dynamic/*=T*/;
Leaf 2016/09/14 23:11:35 Does this mean that .instantiate should have a bet
Jennifer Messerly 2016/09/14 23:18:41 Maybe something like: abstract class Parameterize
1604 } 1612 }
1605 1613
1606 @override 1614 @override
1607 bool _inferTypeParameterSubtypeOf( 1615 bool _inferTypeParameterSubtypeOf(
1608 DartType t1, DartType t2, Set<Element> visited) { 1616 DartType t1, DartType t2, Set<Element> visited) {
1609 if (t1 is TypeParameterType) { 1617 if (t1 is TypeParameterType) {
1610 _TypeParameterBound bound = _bounds[t1]; 1618 _TypeParameterBound bound = _bounds[t1];
1611 if (bound != null) { 1619 if (bound != null) {
1612 // Ensure T1 <: T2, where T1 is a type parameter we are inferring. 1620 // Ensure T1 <: T2, where T1 is a type parameter we are inferring.
1613 // T2 is an upper bound, so merge it with our existing upper bound. 1621 // T2 is an upper bound, so merge it with our existing upper bound.
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1743 } else { 1751 } else {
1744 passedOut = true; 1752 passedOut = true;
1745 } 1753 }
1746 } else if (type is FunctionType) { 1754 } else if (type is FunctionType) {
1747 _visitFunctionType(typeParam, type, paramIn); 1755 _visitFunctionType(typeParam, type, paramIn);
1748 } else if (type is InterfaceType) { 1756 } else if (type is InterfaceType) {
1749 _visitInterfaceType(typeParam, type, paramIn); 1757 _visitInterfaceType(typeParam, type, paramIn);
1750 } 1758 }
1751 } 1759 }
1752 } 1760 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/static_type_analyzer.dart ('k') | pkg/analyzer/lib/src/summary/link.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698