@@ -1289,6 +1289,13 @@ private class BorrowKind extends TBorrowKind {
12891289 }
12901290}
12911291
1292+ // for now, we do not handle ambiguous targets when one of the types is itself
1293+ // a constrained type parameter; we should be checking the constraints in this case
1294+ private predicate typeCanBeUsedForDisambiguation ( Type t ) {
1295+ not t instanceof TypeParameter or
1296+ t .( TypeParamTypeParameter ) .getTypeParam ( ) = any ( TypeParam tp | not tp .hasTypeBound ( ) )
1297+ }
1298+
12921299/**
12931300 * Provides logic for resolving calls to methods.
12941301 *
@@ -2234,7 +2241,8 @@ private module MethodResolution {
22342241 methodCallBlanketLikeCandidate ( mc , _, impl , _, blanketPath , blanketTypeParam ) and
22352242 // Only apply blanket implementations when no other implementations are possible;
22362243 // this is to account for codebases that use the (unstable) specialization feature
2237- // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
2244+ // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html), as well as
2245+ // cases where our blanket implementation filtering is not precise enough.
22382246 ( mcc .hasNoCompatibleNonBlanketTarget ( ) or not impl .isBlanketImplementation ( ) )
22392247 |
22402248 borrow .isNoBorrow ( )
@@ -2384,10 +2392,7 @@ private module MethodResolution {
23842392 exists ( TypePath path , Type t0 |
23852393 FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , path , t0 ) and
23862394 t .appliesTo ( f , i , pos ) and
2387- // for now, we do not handle ambiguous targets when one of the types it iself
2388- // a type parameter; we should be checking the constraints on that type parameter
2389- // in this case
2390- not t0 instanceof TypeParameter
2395+ typeCanBeUsedForDisambiguation ( t0 )
23912396 )
23922397 }
23932398
@@ -2746,7 +2751,7 @@ private module NonMethodResolution {
27462751 * Gets the blanket function that this call may resolve to, if any.
27472752 */
27482753 pragma [ nomagic]
2749- private NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
2754+ NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
27502755 exists ( string name |
27512756 this .hasNameAndArity ( pragma [ only_bind_into ] ( name ) , _) and
27522757 ArgIsInstantiationOfBlanketParam:: argIsInstantiationOf ( MkCallAndBlanketPos ( this , _) , impl , _) and
@@ -2761,12 +2766,11 @@ private module NonMethodResolution {
27612766 predicate hasTrait ( ) { exists ( this .getTrait ( ) ) }
27622767
27632768 pragma [ nomagic]
2764- NonMethodFunction resolveAssocCallTargetCand ( ImplItemNode i ) {
2769+ NonMethodFunction resolveCallTargetNonBlanketCand ( ImplItemNode i ) {
27652770 not this .hasTrait ( ) and
27662771 result = this .getPathResolutionResolved ( ) and
2767- result = i .getASuccessor ( _)
2768- or
2769- result = this .resolveCallTargetBlanketCand ( i )
2772+ result = i .getASuccessor ( _) and
2773+ FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
27702774 }
27712775
27722776 AstNode getNodeAt ( FunctionPosition pos ) {
@@ -2798,6 +2802,21 @@ private module NonMethodResolution {
27982802 trait = this .getTrait ( )
27992803 }
28002804
2805+ /**
2806+ * Holds if this call has no compatible non-blanket target, and it has some
2807+ * candidate blanket target.
2808+ */
2809+ pragma [ nomagic]
2810+ predicate hasNoCompatibleNonBlanketTarget ( ) {
2811+ this .resolveCallTargetBlanketLikeCandidate ( _, _, _, _) and
2812+ not exists ( this .resolveCallTargetViaPathResolution ( ) ) and
2813+ forall ( ImplOrTraitItemNode i , Function f |
2814+ this .( NonMethodArgsAreInstantiationsOfNonBlanketInput:: Call ) .hasTargetCand ( i , f )
2815+ |
2816+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreNotInstantiationsOf ( this , i , f )
2817+ )
2818+ }
2819+
28012820 /**
28022821 * Gets the target of this call, which can be resolved using only path resolution.
28032822 */
@@ -2816,7 +2835,9 @@ private module NonMethodResolution {
28162835 result = this .resolveCallTargetBlanketCand ( i ) and
28172836 not FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
28182837 or
2819- NonMethodArgsAreInstantiationsOf:: argsAreInstantiationsOf ( this , i , result )
2838+ NonMethodArgsAreInstantiationsOfBlanket:: argsAreInstantiationsOf ( this , i , result )
2839+ or
2840+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreInstantiationsOf ( this , i , result )
28202841 }
28212842
28222843 pragma [ nomagic]
@@ -2855,7 +2876,12 @@ private module NonMethodResolution {
28552876 ) {
28562877 exists ( NonMethodCall fc , FunctionPosition pos |
28572878 fcp = MkCallAndBlanketPos ( fc , pos ) and
2858- fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam )
2879+ fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam ) and
2880+ // Only apply blanket implementations when no other implementations are possible;
2881+ // this is to account for codebases that use the (unstable) specialization feature
2882+ // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html), as well as
2883+ // cases where our blanket implementation filtering is not precise enough.
2884+ ( fc .hasNoCompatibleNonBlanketTarget ( ) or not impl .isBlanketImplementation ( ) )
28592885 )
28602886 }
28612887 }
@@ -2890,37 +2916,24 @@ private module NonMethodResolution {
28902916 private module ArgIsInstantiationOfBlanketParam =
28912917 ArgIsInstantiationOf< CallAndBlanketPos , ArgIsInstantiationOfBlanketParamInput > ;
28922918
2893- private module NonMethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
2919+ private module NonMethodArgsAreInstantiationsOfBlanketInput implements
2920+ ArgsAreInstantiationsOfInputSig
2921+ {
28942922 predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
28952923 t .appliesTo ( f , i , pos ) and
2896- (
2897- exists ( Type t0 |
2898- // for now, we do not handle ambiguous targets when one of the types it iself
2899- // a type parameter; we should be checking the constraints on that type parameter
2900- // in this case
2901- not t0 instanceof TypeParameter
2902- |
2903- FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , _, t0 )
2904- or
2905- traitFunctionDependsOnPos ( _, _, pos , t0 , i , f )
2906- )
2924+ exists ( Type t0 | typeCanBeUsedForDisambiguation ( t0 ) |
2925+ FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , _, t0 )
29072926 or
2908- // match against the trait function itself
2909- exists ( Trait trait |
2910- FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2911- TSelfTypeParameter ( trait ) )
2912- )
2927+ traitFunctionDependsOnPos ( _, _, pos , t0 , i , f )
29132928 )
29142929 }
29152930
2916- class Call extends NonMethodCall {
2931+ final class Call extends NonMethodCall {
29172932 Type getArgType ( FunctionPosition pos , TypePath path ) {
29182933 result = inferType ( this .getNodeAt ( pos ) , path )
29192934 }
29202935
2921- predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2922- f = this .resolveAssocCallTargetCand ( i )
2923- or
2936+ predicate hasTraitResolvedCand ( ImplOrTraitItemNode i , Function f ) {
29242937 exists ( TraitItemNode trait , NonMethodFunction resolved , ImplItemNode i1 , Function f1 |
29252938 this .hasTraitResolved ( trait , resolved ) and
29262939 traitFunctionDependsOnPos ( trait , resolved , _, _, i1 , f1 )
@@ -2932,11 +2945,45 @@ private module NonMethodResolution {
29322945 i = trait
29332946 )
29342947 }
2948+
2949+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2950+ f = this .resolveCallTargetBlanketCand ( i )
2951+ or
2952+ this .hasTraitResolvedCand ( i , f ) and
2953+ BlanketImplementation:: isBlanketLike ( i , _, _)
2954+ }
2955+ }
2956+ }
2957+
2958+ private module NonMethodArgsAreInstantiationsOfBlanket =
2959+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfBlanketInput > ;
2960+
2961+ private module NonMethodArgsAreInstantiationsOfNonBlanketInput implements
2962+ ArgsAreInstantiationsOfInputSig
2963+ {
2964+ predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
2965+ NonMethodArgsAreInstantiationsOfBlanketInput:: toCheck ( i , f , pos , t )
2966+ or
2967+ // match against the trait function itself
2968+ t .appliesTo ( f , i , pos ) and
2969+ exists ( Trait trait |
2970+ FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2971+ TSelfTypeParameter ( trait ) )
2972+ )
2973+ }
2974+
2975+ class Call extends NonMethodArgsAreInstantiationsOfBlanketInput:: Call {
2976+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2977+ f = this .resolveCallTargetNonBlanketCand ( i )
2978+ or
2979+ this .hasTraitResolvedCand ( i , f ) and
2980+ not BlanketImplementation:: isBlanketLike ( i , _, _)
2981+ }
29352982 }
29362983 }
29372984
2938- private module NonMethodArgsAreInstantiationsOf =
2939- ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfInput > ;
2985+ private module NonMethodArgsAreInstantiationsOfNonBlanket =
2986+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfNonBlanketInput > ;
29402987}
29412988
29422989abstract private class TupleLikeConstructor extends Addressable {
0 commit comments