@@ -1287,6 +1287,13 @@ private class BorrowKind extends TBorrowKind {
12871287 }
12881288}
12891289
1290+ // for now, we do not handle ambiguous targets when one of the types it iself
1291+ // a constrained type parameter; we should be checking the constraints in this case
1292+ private predicate typeCanBeUsedForDisambiguation ( Type t ) {
1293+ not t instanceof TypeParameter or
1294+ t .( TypeParamTypeParameter ) .getTypeParam ( ) = any ( TypeParam tp | not exists ( tp .getATypeBound ( ) ) )
1295+ }
1296+
12901297/**
12911298 * Provides logic for resolving calls to methods.
12921299 *
@@ -2382,10 +2389,7 @@ private module MethodResolution {
23822389 exists ( TypePath path , Type t0 |
23832390 FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , path , t0 ) and
23842391 t .appliesTo ( f , i , pos ) and
2385- // for now, we do not handle ambiguous targets when one of the types it iself
2386- // a type parameter; we should be checking the constraints on that type parameter
2387- // in this case
2388- not t0 instanceof TypeParameter
2392+ typeCanBeUsedForDisambiguation ( t0 )
23892393 )
23902394 }
23912395
@@ -2744,7 +2748,7 @@ private module NonMethodResolution {
27442748 * Gets the blanket function that this call may resolve to, if any.
27452749 */
27462750 pragma [ nomagic]
2747- private NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
2751+ NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
27482752 exists ( string name |
27492753 this .hasNameAndArity ( pragma [ only_bind_into ] ( name ) , _) and
27502754 ArgIsInstantiationOfBlanketParam:: argIsInstantiationOf ( MkCallAndBlanketPos ( this , _) , impl , _) and
@@ -2759,12 +2763,11 @@ private module NonMethodResolution {
27592763 predicate hasTrait ( ) { exists ( this .getTrait ( ) ) }
27602764
27612765 pragma [ nomagic]
2762- NonMethodFunction resolveAssocCallTargetCand ( ImplItemNode i ) {
2766+ NonMethodFunction resolveCallTargetNonBlanketCand ( ImplItemNode i ) {
27632767 not this .hasTrait ( ) and
27642768 result = this .getPathResolutionResolved ( ) and
2765- result = i .getASuccessor ( _)
2766- or
2767- result = this .resolveCallTargetBlanketCand ( i )
2769+ result = i .getASuccessor ( _) and
2770+ FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
27682771 }
27692772
27702773 AstNode getNodeAt ( FunctionPosition pos ) {
@@ -2796,6 +2799,21 @@ private module NonMethodResolution {
27962799 trait = this .getTrait ( )
27972800 }
27982801
2802+ /**
2803+ * Holds if this call has no compatible non-blanket target, and it has some
2804+ * candidate blanket target.
2805+ */
2806+ pragma [ nomagic]
2807+ predicate hasNoCompatibleNonBlanketTarget ( ) {
2808+ this .resolveCallTargetBlanketLikeCandidate ( _, _, _, _) and
2809+ not exists ( this .resolveCallTargetViaPathResolution ( ) ) and
2810+ forall ( ImplOrTraitItemNode i , Function f |
2811+ this .( NonMethodArgsAreInstantiationsOfNonBlanketInput:: Call ) .hasTargetCand ( i , f )
2812+ |
2813+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreNotInstantiationsOf ( this , i , f )
2814+ )
2815+ }
2816+
27992817 /**
28002818 * Gets the target of this call, which can be resolved using only path resolution.
28012819 */
@@ -2814,7 +2832,9 @@ private module NonMethodResolution {
28142832 result = this .resolveCallTargetBlanketCand ( i ) and
28152833 not FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
28162834 or
2817- NonMethodArgsAreInstantiationsOf:: argsAreInstantiationsOf ( this , i , result )
2835+ NonMethodArgsAreInstantiationsOfBlanket:: argsAreInstantiationsOf ( this , i , result )
2836+ or
2837+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreInstantiationsOf ( this , i , result )
28182838 }
28192839
28202840 pragma [ nomagic]
@@ -2853,7 +2873,11 @@ private module NonMethodResolution {
28532873 ) {
28542874 exists ( NonMethodCall fc , FunctionPosition pos |
28552875 fcp = MkCallAndBlanketPos ( fc , pos ) and
2856- fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam )
2876+ fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam ) and
2877+ // Only apply blanket implementations when no other implementations are possible;
2878+ // this is to account for codebases that use the (unstable) specialization feature
2879+ // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
2880+ ( fc .hasNoCompatibleNonBlanketTarget ( ) or not impl .isBlanketImplementation ( ) )
28572881 )
28582882 }
28592883 }
@@ -2888,37 +2912,24 @@ private module NonMethodResolution {
28882912 private module ArgIsInstantiationOfBlanketParam =
28892913 ArgIsInstantiationOf< CallAndBlanketPos , ArgIsInstantiationOfBlanketParamInput > ;
28902914
2891- private module NonMethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
2915+ private module NonMethodArgsAreInstantiationsOfBlanketInput implements
2916+ ArgsAreInstantiationsOfInputSig
2917+ {
28922918 predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
28932919 t .appliesTo ( f , i , pos ) and
2894- (
2895- exists ( Type t0 |
2896- // for now, we do not handle ambiguous targets when one of the types it iself
2897- // a type parameter; we should be checking the constraints on that type parameter
2898- // in this case
2899- not t0 instanceof TypeParameter
2900- |
2901- FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , _, t0 )
2902- or
2903- traitFunctionDependsOnPos ( _, _, pos , t0 , i , f )
2904- )
2920+ exists ( Type t0 | typeCanBeUsedForDisambiguation ( t0 ) |
2921+ FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , _, t0 )
29052922 or
2906- // match against the trait function itself
2907- exists ( Trait trait |
2908- FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2909- TSelfTypeParameter ( trait ) )
2910- )
2923+ traitFunctionDependsOnPos ( _, _, pos , t0 , i , f )
29112924 )
29122925 }
29132926
2914- class Call extends NonMethodCall {
2927+ final class Call extends NonMethodCall {
29152928 Type getArgType ( FunctionPosition pos , TypePath path ) {
29162929 result = inferType ( this .getNodeAt ( pos ) , path )
29172930 }
29182931
2919- predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2920- f = this .resolveAssocCallTargetCand ( i )
2921- or
2932+ predicate hasTraitResolvedCand ( ImplOrTraitItemNode i , Function f ) {
29222933 exists ( TraitItemNode trait , NonMethodFunction resolved , ImplItemNode i1 , Function f1 |
29232934 this .hasTraitResolved ( trait , resolved ) and
29242935 traitFunctionDependsOnPos ( trait , resolved , _, _, i1 , f1 )
@@ -2930,11 +2941,45 @@ private module NonMethodResolution {
29302941 i = trait
29312942 )
29322943 }
2944+
2945+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2946+ f = this .resolveCallTargetBlanketCand ( i )
2947+ or
2948+ this .hasTraitResolvedCand ( i , f ) and
2949+ BlanketImplementation:: isBlanketLike ( i , _, _)
2950+ }
2951+ }
2952+ }
2953+
2954+ private module NonMethodArgsAreInstantiationsOfBlanket =
2955+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfBlanketInput > ;
2956+
2957+ private module NonMethodArgsAreInstantiationsOfNonBlanketInput implements
2958+ ArgsAreInstantiationsOfInputSig
2959+ {
2960+ predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
2961+ NonMethodArgsAreInstantiationsOfBlanketInput:: toCheck ( i , f , pos , t )
2962+ or
2963+ // match against the trait function itself
2964+ t .appliesTo ( f , i , pos ) and
2965+ exists ( Trait trait |
2966+ FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2967+ TSelfTypeParameter ( trait ) )
2968+ )
2969+ }
2970+
2971+ class Call extends NonMethodArgsAreInstantiationsOfBlanketInput:: Call {
2972+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2973+ f = this .resolveCallTargetNonBlanketCand ( i )
2974+ or
2975+ this .hasTraitResolvedCand ( i , f ) and
2976+ not BlanketImplementation:: isBlanketLike ( i , _, _)
2977+ }
29332978 }
29342979 }
29352980
2936- private module NonMethodArgsAreInstantiationsOf =
2937- ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfInput > ;
2981+ private module NonMethodArgsAreInstantiationsOfNonBlanket =
2982+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfNonBlanketInput > ;
29382983}
29392984
29402985abstract private class TupleLikeConstructor extends Addressable {
0 commit comments