@@ -3253,67 +3253,92 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
32533253 * This module identifies calls where the return type may need to be inferred from the
32543254 * context, and also implements logic for performing contextual inference.
32553255 */
3256- private module ContextualTyping {
3257- pragma [ nomagic]
3258- private TypeParameter getAConstrained ( TypeParameter tp ) {
3259- result = getATypeParameterConstraint ( tp ) .getTypeAt ( _)
3260- }
3261-
3256+ module ContextualTyping {
32623257 /**
3263- * Holds if callable `c` mentions type parameter `tp` at some parameter,
3264- * possibly via a constraint on another mentioned type parameter.
3258+ * Provides the input to `ContextualReturnType`.
32653259 */
3266- pragma [ nomagic]
3267- private predicate mentionsTypeParameterAtParameter ( Callable c , TypeParameter tp ) {
3268- tp = getAConstrained * ( c .getParameter ( _) .getType ( ) .getTypeAt ( _) )
3260+ signature module ContextualReturnTypeInputSig {
3261+ /** Holds if `c` has the type parameter `tp` at its return type at `path`. */
3262+ default predicate callableHasTypeParameterAtReturnType (
3263+ Callable c , TypePath path , TypeParameter tp
3264+ ) {
3265+ tp = getCallableReturnType ( c , path )
3266+ }
3267+
3268+ /** Gets a parameter of `c`. */
3269+ default Parameter getACallableParameter ( Callable c ) { result = c .getParameter ( _) }
32693270 }
32703271
32713272 /**
3272- * Holds if the return type of the callable `c` at `path` is type parameter
3273- * `tp`, and `tp` does not appear in the type of any parameter of `c`.
3274- *
3275- * In this case, the context in which `p` is called may be needed to infer
3276- * the instantiation of `tp`.
3277- *
3278- * This covers functions like `Default::default` and `Vec::new` in Rust.
3273+ * Provide logic for identifying calls where the return type may need to be inferred from the context.
32793274 */
3280- pragma [ nomagic ]
3281- private predicate callableReturnContextTypedAt ( Callable c , TypePath path , TypeParameter tp ) {
3282- tp = getCallableReturnType ( c , path ) and
3283- not mentionsTypeParameterAtParameter ( c , tp )
3284- }
3275+ module ContextualReturnType < ContextualReturnTypeInputSig Input > {
3276+ pragma [ nomagic ]
3277+ private TypeParameter getAConstrained ( TypeParameter tp ) {
3278+ result = getATypeParameterConstraint ( tp ) . getTypeAt ( _ )
3279+ }
32853280
3286- bindingset [ invocation, target]
3287- pragma [ inline_late]
3288- private predicate hasTypeArgument ( Invocation invocation , Callable target , TypeParameter tp ) {
3289- exists ( Type t |
3290- InvocationTypeQualifierMatching:: typeMatch ( invocation , _, _, _, t , tp ) and
3291- not t instanceof PseudoType
3292- )
3293- or
3294- exists ( InvocationMatching:: getTypeArgument ( invocation , target , tp , _) )
3295- }
3281+ /**
3282+ * Holds if callable `c` mentions type parameter `tp` at some parameter,
3283+ * possibly via a constraint on another mentioned type parameter.
3284+ */
3285+ pragma [ nomagic]
3286+ private predicate mentionsTypeParameterAtParameter ( Callable c , TypeParameter tp ) {
3287+ tp = getAConstrained * ( Input:: getACallableParameter ( c ) .getType ( ) .getTypeAt ( _) )
3288+ }
32963289
3297- /**
3298- * Holds if `invocation` resolves to some target where the return type at `path`
3299- * may have to be inferred from the context.
3300- */
3301- pragma [ nomagic]
3302- predicate needsContextualTyping ( Invocation invocation , TypePath path ) {
3303- exists ( Callable target , TypeParameter tp |
3304- target = invocation .getATargetForTypeQualifierMatching ( )
3290+ /**
3291+ * Holds if the return type of the callable `c` at `path` is type parameter
3292+ * `tp`, and `tp` does not appear in the type of any parameter of `c`.
3293+ *
3294+ * In this case, the context in which `p` is called may be needed to infer
3295+ * the instantiation of `tp`.
3296+ *
3297+ * This covers functions like `Default::default` and `Vec::new` in Rust.
3298+ */
3299+ pragma [ nomagic]
3300+ private predicate callableReturnContextTypedAt ( Callable c , TypePath path , TypeParameter tp ) {
3301+ Input:: callableHasTypeParameterAtReturnType ( c , path , tp ) and
3302+ not mentionsTypeParameterAtParameter ( c , tp )
3303+ }
3304+
3305+ bindingset [ invocation, target]
3306+ pragma [ inline_late]
3307+ private predicate hasTypeArgument ( Invocation invocation , Callable target , TypeParameter tp ) {
3308+ exists ( Type t |
3309+ InvocationTypeQualifierMatching:: typeMatch ( invocation , _, _, _, t , tp ) and
3310+ not t instanceof PseudoType
3311+ )
33053312 or
3306- target = invocation .getTarget ( _)
3307- |
3308- callableReturnContextTypedAt ( target , path , tp ) and
3309- // check that no explicit type arguments have been supplied that bind `tp`
3310- not exists ( TypeParameter supplied |
3311- tp = getAConstrained * ( supplied ) and
3312- hasTypeArgument ( invocation , target , supplied )
3313+ exists ( InvocationMatching:: getTypeArgument ( invocation , target , tp , _) )
3314+ }
3315+
3316+ /**
3317+ * Holds if `invocation` resolves to some target where the return type at `path`
3318+ * may have to be inferred from the context.
3319+ */
3320+ pragma [ nomagic]
3321+ predicate needsContextualTyping ( Invocation invocation , TypePath path ) {
3322+ exists ( Callable target , TypeParameter tp |
3323+ target = invocation .getATargetForTypeQualifierMatching ( )
3324+ or
3325+ target = invocation .getTarget ( _)
3326+ |
3327+ callableReturnContextTypedAt ( target , path , tp ) and
3328+ // check that no explicit type arguments have been supplied that bind `tp`
3329+ not exists ( TypeParameter supplied |
3330+ tp = getAConstrained * ( supplied ) and
3331+ hasTypeArgument ( invocation , target , supplied )
3332+ )
33133333 )
3314- )
3334+ }
33153335 }
33163336
3337+ private module DefaultContextualReturnTypeInput implements ContextualReturnTypeInputSig { }
3338+
3339+ predicate needsContextualTyping =
3340+ ContextualReturnType< DefaultContextualReturnTypeInput > :: needsContextualTyping / 2 ;
3341+
33173342 pragma [ nomagic]
33183343 predicate hasUnknownTypeAt ( AstNode n , TypePath path ) {
33193344 inferType ( n , path ) instanceof UnknownType
0 commit comments