@@ -79,7 +79,14 @@ signature module InputSig1<LocationSig Location> {
7979 * For example `int` or ``IEnumerable`1``.
8080 */
8181 class Type {
82- /** Gets a type parameter of this type, if any. */
82+ /** Gets the `i`th positional type parameter of this type, if any. */
83+ TypeParameter getPositionalTypeParameter ( int i ) ;
84+
85+ /**
86+ * Gets a type parameter of this type, if any.
87+ *
88+ * This may include non-positional type parameters as well.
89+ */
8390 TypeParameter getATypeParameter ( ) ;
8491
8592 /** Gets a textual representation of this type. */
@@ -2041,7 +2048,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
20412048 * item in Rust.
20422049 */
20432050 class Variable {
2044- /** Gets the AST node that defines this variable. */
2051+ /** Gets the AST node that defines this variable, if any . */
20452052 AstNode getDefiningNode ( ) ;
20462053
20472054 /** Gets an access to this variable. */
@@ -2055,7 +2062,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
20552062 }
20562063
20572064 /** A declaration. */
2058- class Declaration extends AstNode {
2065+ class Declaration {
20592066 /**
20602067 * Gets the type mention of the entity that contains this declaration, if any.
20612068 *
@@ -2088,6 +2095,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
20882095 * a function.
20892096 */
20902097 TypeMention getType ( ) ;
2098+
2099+ /** Gets a textual representation of this declaration. */
2100+ string toString ( ) ;
2101+
2102+ /** Gets the location of this declaration. */
2103+ Location getLocation ( ) ;
20912104 }
20922105
20932106 /**
@@ -2167,6 +2180,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21672180 /** A parameter. */
21682181 class Parameter extends VariableDeclaration ;
21692182
2183+ /**
2184+ * Holds if `p` is an implicit parameter declaration corresponding
2185+ * to variable `v`.
2186+ */
2187+ default predicate implicitParameterDecl ( Parameter p , Variable v ) { none ( ) }
2188+
21702189 /** A callable. This may include for example variant constructors. */
21712190 class Callable extends Declaration {
21722191 /**
@@ -2368,7 +2387,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23682387 }
23692388
23702389 /** A closure/lambda expression. */
2371- class Closure extends Callable , Expr ;
2390+ class Closure extends Callable {
2391+ /** Gets the expression that defines this closure (typically the entity itself). */
2392+ Expr getDefiningExpr ( ) ;
2393+ }
23722394
23732395 /**
23742396 * A special pseudo type representing a particular closure parameter without
@@ -2484,12 +2506,14 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
24842506 module Make3< InputSig3 Input3> {
24852507 private import Input3
24862508
2487- private predicate closureStep ( AstNode pattern , TypePath prefix1 , Closure c , TypePath prefix2 ) {
2488- exists ( Parameter p |
2509+ pragma [ nomagic]
2510+ private predicate closureStep ( AstNode pattern , TypePath prefix1 , Expr c , TypePath prefix2 ) {
2511+ exists ( Closure c0 , Parameter p |
24892512 pattern = p .getPattern ( ) and
2490- p = c .getParameter ( _) and
2513+ p = c0 .getParameter ( _) and
24912514 prefix1 .isEmpty ( ) and
2492- prefix2 = getClosureParameterTypePath ( p )
2515+ prefix2 = getClosureParameterTypePath ( p ) and
2516+ c = c0 .getDefiningExpr ( )
24932517 )
24942518 }
24952519
@@ -2513,10 +2537,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
25132537 tm = decl .getType ( ) and
25142538 n = decl .getPattern ( )
25152539 )
2540+ or
2541+ exists ( Parameter p , Variable v |
2542+ implicitParameterDecl ( p , v ) and
2543+ result = p .getType ( ) .getTypeAt ( path ) and
2544+ n = v .getAnAccess ( )
2545+ )
25162546 )
25172547 or
25182548 exists ( Closure c , TypePath suffix |
2519- n = c and
2549+ n = c . getDefiningExpr ( ) and
25202550 result = getCallableReturnType ( c , suffix ) and
25212551 path = getClosureReturnTypePath ( c ) .append ( suffix )
25222552 )
@@ -2615,8 +2645,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
26152645 or
26162646 result = inferLogicalOperationType ( n , path )
26172647 or
2618- result = getClosureType ( n ) and
2619- path .isEmpty ( )
2648+ exists ( Closure c |
2649+ n = c .getDefiningExpr ( ) and
2650+ result = getClosureType ( c ) and
2651+ path .isEmpty ( )
2652+ )
26202653 or
26212654 infersCertainTypeAt ( n , path , result .getATypeParameter ( ) )
26222655 ) and
@@ -2709,9 +2742,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
27092742 or
27102743 exists ( Closure c |
27112744 n1 = c .getBody ( ) and
2712- n2 = c and
2745+ n2 = c . getDefiningExpr ( ) and
27132746 prefix1 .isEmpty ( ) and
2714- prefix2 = getClosureReturnTypePath ( n2 )
2747+ prefix2 = getClosureReturnTypePath ( c )
27152748 )
27162749 }
27172750
@@ -2725,7 +2758,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
27252758 or
27262759 closureStep ( n2 , prefix2 , n , prefix1 ) and
27272760 // prevent closure parameter pseudo types from escaping the closure
2728- not result .( ClosureParameterPseudoType ) .getParameter ( ) = n .( Closure ) .getParameter ( _)
2761+ not exists ( Closure c |
2762+ n = c .getDefiningExpr ( ) and
2763+ result .( ClosureParameterPseudoType ) .getParameter ( ) = c .getParameter ( _)
2764+ )
27292765 )
27302766 }
27312767
@@ -3076,7 +3112,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
30763112 }
30773113
30783114 pragma [ nomagic]
3079- private predicate hasUnknownTypeAt ( AstNode n , TypePath path ) {
3115+ predicate hasUnknownTypeAt ( AstNode n , TypePath path ) {
30803116 inferType ( n , path ) instanceof UnknownType
30813117 }
30823118
@@ -3209,8 +3245,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
32093245 result .( ClosureParameterPseudoType ) .getParameter ( ) = p
32103246 or
32113247 // step 3
3212- hasClosureParameterPseudoType ( c , path , p ) and
3213- n = c and
3248+ hasClosureParameterPseudoType ( n , path , p ) and
3249+ n = c . getDefiningExpr ( ) and
32143250 result instanceof UnknownType
32153251 )
32163252 or
@@ -3227,23 +3263,64 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
32273263 or
32283264 // The `step X` comments below refer to the steps for 'Case A' in the
32293265 // QL doc for `ClosureParameterPseudoType`.
3230- exists ( Closure c , Parameter p |
3266+ exists ( Closure c , Parameter p , Expr def |
32313267 p = c .getParameter ( _) and
3232- not exists ( p .getType ( ) )
3268+ not exists ( p .getType ( ) ) and
3269+ def = c .getDefiningExpr ( )
32333270 |
32343271 // step 1
3235- n = c and
3272+ n = def and
32363273 path = getClosureParameterTypePath ( p ) and
32373274 result instanceof UnknownType
32383275 or
32393276 // step 3
32403277 n = p .getPattern ( ) and
3241- result = inferType ( c , getClosureParameterTypePath ( p ) .appendInverse ( path ) ) and
3278+ result = inferType ( def , getClosureParameterTypePath ( p ) .appendInverse ( path ) ) and
32423279 not ( path .isEmpty ( ) and result instanceof UnknownType )
32433280 )
32443281 }
32453282 }
32463283
3284+ /**
3285+ * Holds if `n` has unknown type at at `prefix`, but is still able to
3286+ * infer a known type at `suffix` for the `i`th type parameter of whatever
3287+ * the unknown type is.
3288+ *
3289+ * For example, in
3290+ *
3291+ * ```rust
3292+ * let mut x: Unresolvable<i32> = ...;
3293+ *
3294+ * x = resolvable(...);
3295+ * ```
3296+ *
3297+ * even though the root type is unresolvable at the declaration, we are still
3298+ * able to infer that the first type argument is `i32`. We can then combine this
3299+ * information with later inferred type information.
3300+ */
3301+ pragma [ nomagic]
3302+ private predicate infersUnknownTypeArg (
3303+ AstNode n , TypePath prefix , int i , TypePath suffix , Type t
3304+ ) {
3305+ exists ( TypeParameter tp , TypePath suffix0 |
3306+ ContextualTyping:: hasUnknownTypeAt ( n , prefix ) and
3307+ suffix0 .isCons ( tp , suffix ) and
3308+ tp = any ( UnknownType ut ) .getPositionalTypeParameter ( i ) and
3309+ t = inferType ( n , prefix .appendInverse ( suffix0 ) ) and
3310+ not t instanceof UnknownType
3311+ )
3312+ }
3313+
3314+ pragma [ nomagic]
3315+ private predicate infersKnownAndUnknownType ( AstNode n , TypePath path , int i , TypeParameter tp ) {
3316+ ContextualTyping:: hasUnknownTypeAt ( n , path ) and
3317+ exists ( Type t |
3318+ t = inferType ( n , path ) and
3319+ not t instanceof UnknownType and
3320+ tp = t .getPositionalTypeParameter ( i )
3321+ )
3322+ }
3323+
32473324 /**
32483325 * Gets an inferred candidate type of `n` at `path`.
32493326 *
@@ -3275,6 +3352,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
32753352 result instanceof UnknownType
32763353 or
32773354 result = ContextualTyping:: inferTypeContextual ( n , path )
3355+ or
3356+ exists ( TypePath prefix , int i , TypePath suffix , TypeParameter tp |
3357+ infersUnknownTypeArg ( n , prefix , i , suffix , result ) and
3358+ infersKnownAndUnknownType ( n , prefix , i , tp ) and
3359+ path = prefix .append ( TypePath:: cons ( tp , suffix ) )
3360+ )
32783361 }
32793362
32803363 /**
@@ -3298,7 +3381,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
32983381 result instanceof ClosureParameterPseudoType
32993382 ) and
33003383 // prevent closure parameter pseudo types from escaping from the closure
3301- not result .( ClosureParameterPseudoType ) .getParameter ( ) = n .( Closure ) .getParameter ( _)
3384+ not exists ( Closure c |
3385+ n = c .getDefiningExpr ( ) and
3386+ result .( ClosureParameterPseudoType ) .getParameter ( ) = c .getParameter ( _)
3387+ )
33023388 or
33033389 // If `n` has an explicitly unknown type at `prefix` and at the same time a certain
33043390 // type at `prefix.suffix`, then extend the unknown type information to any path
0 commit comments