@@ -196,12 +196,17 @@ abstract interface class TypeAnalyzerOperations<
196196 @override
197197 bool isNever (SharedTypeView <TypeStructure > type);
198198
199- /// Returns `true` if `Null` is not a subtype of all types matching
200- /// [typeSchema] .
199+ /// Returns `true` if `Null` is a subtype of all types matching [type] .
201200 ///
202- /// The predicate of [isNonNullable] could be computed directly with a subtype
203- /// query, but the implementations can do that more efficiently.
204- bool isNonNullable (SharedTypeSchemaView <TypeStructure > typeSchema);
201+ /// The predicate of [isNullableInternal] could be computed directly with a
202+ /// subtype query, but the implementations can do that more efficiently.
203+ bool isNullableInternal (TypeStructure type);
204+
205+ /// Returns `true` if `Null` is not a subtype of all types matching [type] .
206+ ///
207+ /// The predicate of [isNonNullableInternal] could be computed directly with
208+ /// a subtype query, but the implementations can do that more efficiently.
209+ bool isNonNullableInternal (TypeStructure type);
205210
206211 /// Returns `true` if [type] is `Null` .
207212 bool isNull (SharedTypeView <TypeStructure > type);
@@ -943,12 +948,12 @@ abstract class TypeConstraintGenerator<
943948 /// Add constraint: [lower] <: [typeParameter] <: TOP.
944949 void addLowerConstraintForParameter (
945950 TypeParameterStructure typeParameter, TypeStructure lower,
946- {required AstNode ? nodeForTesting });
951+ {required AstNode ? astNodeForTesting });
947952
948953 /// Add constraint: BOTTOM <: [typeParameter] <: [upper] .
949954 void addUpperConstraintForParameter (
950955 TypeParameterStructure typeParameter, TypeStructure upper,
951- {required AstNode ? nodeForTesting });
956+ {required AstNode ? astNodeForTesting });
952957
953958 /// Returns the type arguments of the supertype of [type] that is an
954959 /// instantiation of [typeDeclaration] . If none of the supertypes of [type]
@@ -1543,6 +1548,9 @@ abstract class TypeConstraintGenerator<
15431548 return false ;
15441549 }
15451550
1551+ /// Type parameters being constrained by [TypeConstraintGenerator] .
1552+ Iterable <TypeParameterStructure > get typeParametersToConstrain;
1553+
15461554 /// Implementation backing [performSubtypeConstraintGenerationLeftSchema] and
15471555 /// [performSubtypeConstraintGenerationRightSchema] .
15481556 ///
@@ -1568,7 +1576,154 @@ abstract class TypeConstraintGenerator<
15681576 /// [performSubtypeConstraintGenerationRightSchema] from the mixin.
15691577 bool performSubtypeConstraintGenerationInternal (
15701578 TypeStructure p, TypeStructure q,
1571- {required bool leftSchema, required AstNode ? astNodeForTesting});
1579+ {required bool leftSchema, required AstNode ? astNodeForTesting}) {
1580+ // If `P` is `_` then the match holds with no constraints.
1581+ if (p is SharedUnknownTypeStructure ) {
1582+ return true ;
1583+ }
1584+
1585+ // If `Q` is `_` then the match holds with no constraints.
1586+ if (q is SharedUnknownTypeStructure ) {
1587+ return true ;
1588+ }
1589+
1590+ // If `P` is a type variable `X` in `L`, then the match holds:
1591+ // Under constraint `_ <: X <: Q`.
1592+ NullabilitySuffix pNullability = p.nullabilitySuffix;
1593+ if (typeAnalyzerOperations.matchInferableParameter (new SharedTypeView (p))
1594+ case var pParameter?
1595+ when pNullability == NullabilitySuffix .none &&
1596+ typeParametersToConstrain.contains (pParameter)) {
1597+ addUpperConstraintForParameter (pParameter, q,
1598+ astNodeForTesting: astNodeForTesting);
1599+ return true ;
1600+ }
1601+
1602+ // If `Q` is a type variable `X` in `L`, then the match holds:
1603+ // Under constraint `P <: X <: _`.
1604+ NullabilitySuffix qNullability = q.nullabilitySuffix;
1605+ if (typeAnalyzerOperations.matchInferableParameter (new SharedTypeView (q))
1606+ case var qParameter?
1607+ when qNullability == NullabilitySuffix .none &&
1608+ typeParametersToConstrain.contains (qParameter) &&
1609+ (! inferenceUsingBoundsIsEnabled ||
1610+ (qParameter.bound == null ||
1611+ typeAnalyzerOperations.isSubtypeOfInternal (
1612+ p,
1613+ typeAnalyzerOperations.greatestClosureOfTypeInternal (
1614+ qParameter.bound! ,
1615+ [...typeParametersToConstrain]))))) {
1616+ addLowerConstraintForParameter (qParameter, p,
1617+ astNodeForTesting: astNodeForTesting);
1618+ return true ;
1619+ }
1620+
1621+ // If `P` and `Q` are identical types, then the subtype match holds
1622+ // under no constraints.
1623+ if (p == q) {
1624+ return true ;
1625+ }
1626+
1627+ // Note that it's not necessary to rewind [_constraints] to its prior state
1628+ // in case [performSubtypeConstraintGenerationForFutureOr] returns false, as
1629+ // [performSubtypeConstraintGenerationForFutureOr] handles the rewinding of
1630+ // the state itself.
1631+ if (performSubtypeConstraintGenerationForRightFutureOr (p, q,
1632+ leftSchema: leftSchema, astNodeForTesting: astNodeForTesting)) {
1633+ return true ;
1634+ }
1635+
1636+ if (performSubtypeConstraintGenerationForRightNullableType (p, q,
1637+ leftSchema: leftSchema, astNodeForTesting: astNodeForTesting)) {
1638+ return true ;
1639+ }
1640+
1641+ // If `P` is `FutureOr<P0>` the match holds under constraint set `C1 + C2`:
1642+ if (performSubtypeConstraintGenerationForLeftFutureOr (p, q,
1643+ leftSchema: leftSchema, astNodeForTesting: astNodeForTesting)) {
1644+ return true ;
1645+ }
1646+
1647+ // If `P` is `P0?` the match holds under constraint set `C1 + C2`:
1648+ if (performSubtypeConstraintGenerationForLeftNullableType (p, q,
1649+ leftSchema: leftSchema, astNodeForTesting: astNodeForTesting)) {
1650+ return true ;
1651+ }
1652+
1653+ // If `Q` is `dynamic`, `Object?`, or `void` then the match holds under
1654+ // no constraints.
1655+ if (q is SharedDynamicTypeStructure ||
1656+ q is SharedVoidTypeStructure ||
1657+ q == typeAnalyzerOperations.objectQuestionType.unwrapTypeView ()) {
1658+ return true ;
1659+ }
1660+
1661+ // If `P` is `Never` then the match holds under no constraints.
1662+ if (typeAnalyzerOperations.isNever (new SharedTypeView (p))) {
1663+ return true ;
1664+ }
1665+
1666+ // If `Q` is `Object`, then the match holds under no constraints:
1667+ // Only if `P` is non-nullable.
1668+ if (q == typeAnalyzerOperations.objectType.unwrapTypeView ()) {
1669+ return typeAnalyzerOperations.isNonNullableInternal (p);
1670+ }
1671+
1672+ // If `P` is `Null`, then the match holds under no constraints:
1673+ // Only if `Q` is nullable.
1674+ if (pNullability == NullabilitySuffix .none &&
1675+ typeAnalyzerOperations.isNull (new SharedTypeView (p))) {
1676+ return typeAnalyzerOperations.isNullableInternal (q);
1677+ }
1678+
1679+ // If `P` is a type variable `X` with bound `B` (or a promoted type
1680+ // variable `X & B`), the match holds with constraint set `C`:
1681+ // If `B` is a subtype match for `Q` with constraint set `C`.
1682+ // Note: we have already eliminated the case that `X` is a variable in `L`.
1683+ if (typeAnalyzerOperations.matchTypeParameterBoundInternal (p)
1684+ case var bound? ) {
1685+ if (performSubtypeConstraintGenerationInternal (bound, q,
1686+ leftSchema: leftSchema, astNodeForTesting: astNodeForTesting)) {
1687+ return true ;
1688+ }
1689+ }
1690+
1691+ bool ? result = performSubtypeConstraintGenerationForTypeDeclarationTypes (
1692+ p, q,
1693+ leftSchema: leftSchema, astNodeForTesting: astNodeForTesting);
1694+ if (result != null ) {
1695+ return result;
1696+ }
1697+
1698+ // If `Q` is `Function` then the match holds under no constraints:
1699+ // If `P` is a function type.
1700+ if (typeAnalyzerOperations.isDartCoreFunction (new SharedTypeView (q))) {
1701+ if (p is SharedFunctionTypeStructure ) {
1702+ return true ;
1703+ }
1704+ }
1705+
1706+ if (performSubtypeConstraintGenerationForFunctionTypes (p, q,
1707+ leftSchema: leftSchema, astNodeForTesting: astNodeForTesting)) {
1708+ return true ;
1709+ }
1710+
1711+ // A type `P` is a subtype match for `Record` with respect to `L` under no
1712+ // constraints:
1713+ // If `P` is a record type or `Record`.
1714+ if (typeAnalyzerOperations.isDartCoreRecord (new SharedTypeView (q))) {
1715+ if (p is SharedRecordTypeStructure <TypeStructure >) {
1716+ return true ;
1717+ }
1718+ }
1719+
1720+ if (performSubtypeConstraintGenerationForRecordTypes (p, q,
1721+ leftSchema: leftSchema, astNodeForTesting: astNodeForTesting)) {
1722+ return true ;
1723+ }
1724+
1725+ return false ;
1726+ }
15721727
15731728 /// Matches type schema [p] against type [q] as a subtype against supertype,
15741729 /// assuming [p] is the constraining type schema, and [q] contains the type
0 commit comments