@@ -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. */
@@ -2080,7 +2087,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
20802087 * item in Rust.
20812088 */
20822089 class Variable {
2083- /** Gets the AST node that defines this variable. */
2090+ /** Gets the AST node that defines this variable, if any . */
20842091 AstNode getDefiningNode ( ) ;
20852092
20862093 /** Gets an access to this variable. */
@@ -2094,7 +2101,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
20942101 }
20952102
20962103 /** A declaration. */
2097- class Declaration extends AstNode {
2104+ class Declaration {
20982105 /**
20992106 * Gets the type mention of the entity that contains this declaration, if any.
21002107 *
@@ -2127,6 +2134,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21272134 * a function.
21282135 */
21292136 TypeMention getType ( ) ;
2137+
2138+ /** Gets a textual representation of this declaration. */
2139+ string toString ( ) ;
2140+
2141+ /** Gets the location of this declaration. */
2142+ Location getLocation ( ) ;
21302143 }
21312144
21322145 /**
@@ -2206,6 +2219,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22062219 /** A parameter. */
22072220 class Parameter extends VariableDeclaration ;
22082221
2222+ /**
2223+ * Holds if `p` is an implicit parameter declaration corresponding
2224+ * to variable `v`.
2225+ */
2226+ default predicate implicitParameterDecl ( Parameter p , Variable v ) { none ( ) }
2227+
22092228 /** A callable. This may include for example variant constructors. */
22102229 class Callable extends Declaration {
22112230 /**
@@ -2407,7 +2426,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
24072426 }
24082427
24092428 /** A closure/lambda expression. */
2410- class Closure extends Callable , Expr ;
2429+ class Closure extends Callable {
2430+ /** Gets the expression that defines this closure (typically the entity itself). */
2431+ Expr getDefiningExpr ( ) ;
2432+ }
24112433
24122434 /**
24132435 * A special pseudo type representing a particular closure parameter without
@@ -2523,12 +2545,14 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
25232545 module Make3< InputSig3 Input3> {
25242546 private import Input3
25252547
2526- private predicate closureStep ( AstNode pattern , TypePath prefix1 , Closure c , TypePath prefix2 ) {
2527- exists ( Parameter p |
2548+ pragma [ nomagic]
2549+ private predicate closureStep ( AstNode pattern , TypePath prefix1 , Expr c , TypePath prefix2 ) {
2550+ exists ( Closure c0 , Parameter p |
25282551 pattern = p .getPattern ( ) and
2529- p = c .getParameter ( _) and
2552+ p = c0 .getParameter ( _) and
25302553 prefix1 .isEmpty ( ) and
2531- prefix2 = getClosureParameterTypePath ( p )
2554+ prefix2 = getClosureParameterTypePath ( p ) and
2555+ c = c0 .getDefiningExpr ( )
25322556 )
25332557 }
25342558
@@ -2552,10 +2576,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
25522576 tm = decl .getType ( ) and
25532577 n = decl .getPattern ( )
25542578 )
2579+ or
2580+ exists ( Parameter p , Variable v |
2581+ implicitParameterDecl ( p , v ) and
2582+ result = p .getType ( ) .getTypeAt ( path ) and
2583+ n = v .getAnAccess ( )
2584+ )
25552585 )
25562586 or
25572587 exists ( Closure c , TypePath suffix |
2558- n = c and
2588+ n = c . getDefiningExpr ( ) and
25592589 result = getCallableReturnType ( c , suffix ) and
25602590 path = getClosureReturnTypePath ( c ) .append ( suffix )
25612591 )
@@ -2654,8 +2684,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
26542684 or
26552685 result = inferLogicalOperationType ( n , path )
26562686 or
2657- result = getClosureType ( n ) and
2658- path .isEmpty ( )
2687+ exists ( Closure c |
2688+ n = c .getDefiningExpr ( ) and
2689+ result = getClosureType ( c ) and
2690+ path .isEmpty ( )
2691+ )
26592692 or
26602693 infersCertainTypeAt ( n , path , result .getATypeParameter ( ) )
26612694 ) and
@@ -2748,9 +2781,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
27482781 or
27492782 exists ( Closure c |
27502783 n1 = c .getBody ( ) and
2751- n2 = c and
2784+ n2 = c . getDefiningExpr ( ) and
27522785 prefix1 .isEmpty ( ) and
2753- prefix2 = getClosureReturnTypePath ( n2 )
2786+ prefix2 = getClosureReturnTypePath ( c )
27542787 )
27552788 }
27562789
@@ -2764,7 +2797,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
27642797 or
27652798 closureStep ( n2 , prefix2 , n , prefix1 ) and
27662799 // prevent closure parameter pseudo types from escaping the closure
2767- not result .( ClosureParameterPseudoType ) .getParameter ( ) = n .( Closure ) .getParameter ( _)
2800+ not exists ( Closure c |
2801+ n = c .getDefiningExpr ( ) and
2802+ result .( ClosureParameterPseudoType ) .getParameter ( ) = c .getParameter ( _)
2803+ )
27682804 )
27692805 }
27702806
@@ -3115,7 +3151,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
31153151 }
31163152
31173153 pragma [ nomagic]
3118- private predicate hasUnknownTypeAt ( AstNode n , TypePath path ) {
3154+ predicate hasUnknownTypeAt ( AstNode n , TypePath path ) {
31193155 inferType ( n , path ) instanceof UnknownType
31203156 }
31213157
@@ -3248,8 +3284,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
32483284 result .( ClosureParameterPseudoType ) .getParameter ( ) = p
32493285 or
32503286 // step 3
3251- hasClosureParameterPseudoType ( c , path , p ) and
3252- n = c and
3287+ hasClosureParameterPseudoType ( n , path , p ) and
3288+ n = c . getDefiningExpr ( ) and
32533289 result instanceof UnknownType
32543290 )
32553291 or
@@ -3266,23 +3302,64 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
32663302 or
32673303 // The `step X` comments below refer to the steps for 'Case A' in the
32683304 // QL doc for `ClosureParameterPseudoType`.
3269- exists ( Closure c , Parameter p |
3305+ exists ( Closure c , Parameter p , Expr def |
32703306 p = c .getParameter ( _) and
3271- not exists ( p .getType ( ) )
3307+ not exists ( p .getType ( ) ) and
3308+ def = c .getDefiningExpr ( )
32723309 |
32733310 // step 1
3274- n = c and
3311+ n = def and
32753312 path = getClosureParameterTypePath ( p ) and
32763313 result instanceof UnknownType
32773314 or
32783315 // step 3
32793316 n = p .getPattern ( ) and
3280- result = inferType ( c , getClosureParameterTypePath ( p ) .appendInverse ( path ) ) and
3317+ result = inferType ( def , getClosureParameterTypePath ( p ) .appendInverse ( path ) ) and
32813318 not ( path .isEmpty ( ) and result instanceof UnknownType )
32823319 )
32833320 }
32843321 }
32853322
3323+ /**
3324+ * Holds if `n` has unknown type at `prefix`, but is still able to
3325+ * infer a known type at `suffix` for the `i`th type parameter of whatever
3326+ * the unknown type is.
3327+ *
3328+ * For example, in
3329+ *
3330+ * ```rust
3331+ * let mut x: Unresolvable<i32> = ...;
3332+ *
3333+ * x = resolvable(...);
3334+ * ```
3335+ *
3336+ * even though the root type is unresolvable at the declaration, we are still
3337+ * able to infer that the first type argument is `i32`. We can then combine this
3338+ * information with later inferred type information.
3339+ */
3340+ pragma [ nomagic]
3341+ private predicate infersUnknownTypeArg (
3342+ AstNode n , TypePath prefix , int i , TypePath suffix , Type t
3343+ ) {
3344+ exists ( TypeParameter tp , TypePath suffix0 |
3345+ ContextualTyping:: hasUnknownTypeAt ( n , prefix ) and
3346+ suffix0 .isCons ( tp , suffix ) and
3347+ tp = any ( UnknownType ut ) .getPositionalTypeParameter ( i ) and
3348+ t = inferType ( n , prefix .appendInverse ( suffix0 ) ) and
3349+ not t instanceof UnknownType
3350+ )
3351+ }
3352+
3353+ pragma [ nomagic]
3354+ private predicate infersKnownAndUnknownType ( AstNode n , TypePath path , int i , TypeParameter tp ) {
3355+ ContextualTyping:: hasUnknownTypeAt ( n , path ) and
3356+ exists ( Type t |
3357+ t = inferType ( n , path ) and
3358+ not t instanceof UnknownType and
3359+ tp = t .getPositionalTypeParameter ( i )
3360+ )
3361+ }
3362+
32863363 /**
32873364 * Gets an inferred candidate type of `n` at `path`.
32883365 *
@@ -3314,6 +3391,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
33143391 result instanceof UnknownType
33153392 or
33163393 result = ContextualTyping:: inferTypeContextual ( n , path )
3394+ or
3395+ exists ( TypePath prefix , int i , TypePath suffix , TypeParameter tp |
3396+ infersUnknownTypeArg ( n , prefix , i , suffix , result ) and
3397+ infersKnownAndUnknownType ( n , prefix , i , tp ) and
3398+ path = prefix .append ( TypePath:: cons ( tp , suffix ) )
3399+ )
33173400 }
33183401
33193402 /**
@@ -3337,7 +3420,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
33373420 result instanceof ClosureParameterPseudoType
33383421 ) and
33393422 // prevent closure parameter pseudo types from escaping from the closure
3340- not result .( ClosureParameterPseudoType ) .getParameter ( ) = n .( Closure ) .getParameter ( _)
3423+ not exists ( Closure c |
3424+ n = c .getDefiningExpr ( ) and
3425+ result .( ClosureParameterPseudoType ) .getParameter ( ) = c .getParameter ( _)
3426+ )
33413427 or
33423428 // If `n` has an explicitly unknown type at `prefix` and at the same time a certain
33433429 // type at `prefix.suffix`, then extend the unknown type information to any path
0 commit comments