@@ -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 it iself
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 exists ( tp .getATypeBound ( ) ) )
1297+ }
1298+
12921299/**
12931300 * Provides logic for resolving calls to methods.
12941301 *
@@ -2384,10 +2391,7 @@ private module MethodResolution {
23842391 exists ( TypePath path , Type t0 |
23852392 FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , path , t0 ) and
23862393 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
2394+ typeCanBeUsedForDisambiguation ( t0 )
23912395 )
23922396 }
23932397
@@ -2746,7 +2750,7 @@ private module NonMethodResolution {
27462750 * Gets the blanket function that this call may resolve to, if any.
27472751 */
27482752 pragma [ nomagic]
2749- private NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
2753+ NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
27502754 exists ( string name |
27512755 this .hasNameAndArity ( pragma [ only_bind_into ] ( name ) , _) and
27522756 ArgIsInstantiationOfBlanketParam:: argIsInstantiationOf ( MkCallAndBlanketPos ( this , _) , impl , _) and
@@ -2761,12 +2765,11 @@ private module NonMethodResolution {
27612765 predicate hasTrait ( ) { exists ( this .getTrait ( ) ) }
27622766
27632767 pragma [ nomagic]
2764- NonMethodFunction resolveAssocCallTargetCand ( ImplItemNode i ) {
2768+ NonMethodFunction resolveCallTargetNonBlanketCand ( ImplItemNode i ) {
27652769 not this .hasTrait ( ) and
27662770 result = this .getPathResolutionResolved ( ) and
2767- result = i .getASuccessor ( _)
2768- or
2769- result = this .resolveCallTargetBlanketCand ( i )
2771+ result = i .getASuccessor ( _) and
2772+ FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
27702773 }
27712774
27722775 AstNode getNodeAt ( FunctionPosition pos ) {
@@ -2798,6 +2801,21 @@ private module NonMethodResolution {
27982801 trait = this .getTrait ( )
27992802 }
28002803
2804+ /**
2805+ * Holds if this call has no compatible non-blanket target, and it has some
2806+ * candidate blanket target.
2807+ */
2808+ pragma [ nomagic]
2809+ predicate hasNoCompatibleNonBlanketTarget ( ) {
2810+ this .resolveCallTargetBlanketLikeCandidate ( _, _, _, _) and
2811+ not exists ( this .resolveCallTargetViaPathResolution ( ) ) and
2812+ forall ( ImplOrTraitItemNode i , Function f |
2813+ this .( NonMethodArgsAreInstantiationsOfNonBlanketInput:: Call ) .hasTargetCand ( i , f )
2814+ |
2815+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreNotInstantiationsOf ( this , i , f )
2816+ )
2817+ }
2818+
28012819 /**
28022820 * Gets the target of this call, which can be resolved using only path resolution.
28032821 */
@@ -2816,7 +2834,9 @@ private module NonMethodResolution {
28162834 result = this .resolveCallTargetBlanketCand ( i ) and
28172835 not FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
28182836 or
2819- NonMethodArgsAreInstantiationsOf:: argsAreInstantiationsOf ( this , i , result )
2837+ NonMethodArgsAreInstantiationsOfBlanket:: argsAreInstantiationsOf ( this , i , result )
2838+ or
2839+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreInstantiationsOf ( this , i , result )
28202840 }
28212841
28222842 pragma [ nomagic]
@@ -2855,7 +2875,11 @@ private module NonMethodResolution {
28552875 ) {
28562876 exists ( NonMethodCall fc , FunctionPosition pos |
28572877 fcp = MkCallAndBlanketPos ( fc , pos ) and
2858- fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam )
2878+ fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam ) and
2879+ // Only apply blanket implementations when no other implementations are possible;
2880+ // this is to account for codebases that use the (unstable) specialization feature
2881+ // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
2882+ ( fc .hasNoCompatibleNonBlanketTarget ( ) or not impl .isBlanketImplementation ( ) )
28592883 )
28602884 }
28612885 }
@@ -2890,37 +2914,24 @@ private module NonMethodResolution {
28902914 private module ArgIsInstantiationOfBlanketParam =
28912915 ArgIsInstantiationOf< CallAndBlanketPos , ArgIsInstantiationOfBlanketParamInput > ;
28922916
2893- private module NonMethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
2917+ private module NonMethodArgsAreInstantiationsOfBlanketInput implements
2918+ ArgsAreInstantiationsOfInputSig
2919+ {
28942920 predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
28952921 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- )
2922+ exists ( Type t0 | typeCanBeUsedForDisambiguation ( t0 ) |
2923+ FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , _, t0 )
29072924 or
2908- // match against the trait function itself
2909- exists ( Trait trait |
2910- FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2911- TSelfTypeParameter ( trait ) )
2912- )
2925+ traitFunctionDependsOnPos ( _, _, pos , t0 , i , f )
29132926 )
29142927 }
29152928
2916- class Call extends NonMethodCall {
2929+ final class Call extends NonMethodCall {
29172930 Type getArgType ( FunctionPosition pos , TypePath path ) {
29182931 result = inferType ( this .getNodeAt ( pos ) , path )
29192932 }
29202933
2921- predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2922- f = this .resolveAssocCallTargetCand ( i )
2923- or
2934+ predicate hasTraitResolvedCand ( ImplOrTraitItemNode i , Function f ) {
29242935 exists ( TraitItemNode trait , NonMethodFunction resolved , ImplItemNode i1 , Function f1 |
29252936 this .hasTraitResolved ( trait , resolved ) and
29262937 traitFunctionDependsOnPos ( trait , resolved , _, _, i1 , f1 )
@@ -2932,11 +2943,45 @@ private module NonMethodResolution {
29322943 i = trait
29332944 )
29342945 }
2946+
2947+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2948+ f = this .resolveCallTargetBlanketCand ( i )
2949+ or
2950+ this .hasTraitResolvedCand ( i , f ) and
2951+ BlanketImplementation:: isBlanketLike ( i , _, _)
2952+ }
2953+ }
2954+ }
2955+
2956+ private module NonMethodArgsAreInstantiationsOfBlanket =
2957+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfBlanketInput > ;
2958+
2959+ private module NonMethodArgsAreInstantiationsOfNonBlanketInput implements
2960+ ArgsAreInstantiationsOfInputSig
2961+ {
2962+ predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
2963+ NonMethodArgsAreInstantiationsOfBlanketInput:: toCheck ( i , f , pos , t )
2964+ or
2965+ // match against the trait function itself
2966+ t .appliesTo ( f , i , pos ) and
2967+ exists ( Trait trait |
2968+ FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2969+ TSelfTypeParameter ( trait ) )
2970+ )
2971+ }
2972+
2973+ class Call extends NonMethodArgsAreInstantiationsOfBlanketInput:: Call {
2974+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2975+ f = this .resolveCallTargetNonBlanketCand ( i )
2976+ or
2977+ this .hasTraitResolvedCand ( i , f ) and
2978+ not BlanketImplementation:: isBlanketLike ( i , _, _)
2979+ }
29352980 }
29362981 }
29372982
2938- private module NonMethodArgsAreInstantiationsOf =
2939- ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfInput > ;
2983+ private module NonMethodArgsAreInstantiationsOfNonBlanket =
2984+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfNonBlanketInput > ;
29402985}
29412986
29422987abstract private class TupleLikeConstructor extends Addressable {
0 commit comments