@@ -2744,7 +2744,7 @@ private module NonMethodResolution {
27442744 * Gets the blanket function that this call may resolve to, if any.
27452745 */
27462746 pragma [ nomagic]
2747- private NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
2747+ NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
27482748 exists ( string name |
27492749 this .hasNameAndArity ( pragma [ only_bind_into ] ( name ) , _) and
27502750 ArgIsInstantiationOfBlanketParam:: argIsInstantiationOf ( MkCallAndBlanketPos ( this , _) , impl , _) and
@@ -2759,12 +2759,11 @@ private module NonMethodResolution {
27592759 predicate hasTrait ( ) { exists ( this .getTrait ( ) ) }
27602760
27612761 pragma [ nomagic]
2762- NonMethodFunction resolveAssocCallTargetCand ( ImplItemNode i ) {
2762+ NonMethodFunction resolveCallTargetNonBlanketCand ( ImplItemNode i ) {
27632763 not this .hasTrait ( ) and
27642764 result = this .getPathResolutionResolved ( ) and
2765- result = i .getASuccessor ( _)
2766- or
2767- result = this .resolveCallTargetBlanketCand ( i )
2765+ result = i .getASuccessor ( _) and
2766+ FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
27682767 }
27692768
27702769 AstNode getNodeAt ( FunctionPosition pos ) {
@@ -2796,6 +2795,16 @@ private module NonMethodResolution {
27962795 trait = this .getTrait ( )
27972796 }
27982797
2798+ pragma [ nomagic]
2799+ predicate hasNoCompatibleNonBlanketTarget ( ) {
2800+ not exists ( this .resolveCallTargetViaPathResolution ( ) ) and
2801+ forall ( ImplOrTraitItemNode i , Function f |
2802+ this .( NonMethodArgsAreInstantiationsOfNonBlanketInput:: Call ) .hasTargetCand ( i , f )
2803+ |
2804+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreNotInstantiationsOf ( this , i , f )
2805+ )
2806+ }
2807+
27992808 /**
28002809 * Gets the target of this call, which can be resolved using only path resolution.
28012810 */
@@ -2814,7 +2823,9 @@ private module NonMethodResolution {
28142823 result = this .resolveCallTargetBlanketCand ( i ) and
28152824 not FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
28162825 or
2817- NonMethodArgsAreInstantiationsOf:: argsAreInstantiationsOf ( this , i , result )
2826+ NonMethodArgsAreInstantiationsOfBlanket:: argsAreInstantiationsOf ( this , i , result )
2827+ or
2828+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreInstantiationsOf ( this , i , result )
28182829 }
28192830
28202831 pragma [ nomagic]
@@ -2853,7 +2864,11 @@ private module NonMethodResolution {
28532864 ) {
28542865 exists ( NonMethodCall fc , FunctionPosition pos |
28552866 fcp = MkCallAndBlanketPos ( fc , pos ) and
2856- fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam )
2867+ fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam ) and
2868+ // Only apply blanket implementations when no other implementations are possible;
2869+ // this is to account for codebases that use the (unstable) specialization feature
2870+ // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
2871+ ( fc .hasNoCompatibleNonBlanketTarget ( ) or not impl .isBlanketImplementation ( ) )
28572872 )
28582873 }
28592874 }
@@ -2888,37 +2903,29 @@ private module NonMethodResolution {
28882903 private module ArgIsInstantiationOfBlanketParam =
28892904 ArgIsInstantiationOf< CallAndBlanketPos , ArgIsInstantiationOfBlanketParamInput > ;
28902905
2891- private module NonMethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
2906+ private module NonMethodArgsAreInstantiationsOfBlanketInput implements
2907+ ArgsAreInstantiationsOfInputSig
2908+ {
28922909 predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
28932910 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- )
2911+ exists ( Type t0 |
2912+ // for now, we do not handle ambiguous targets when one of the types it iself
2913+ // a type parameter; we should be checking the constraints on that type parameter
2914+ // in this case
2915+ not t0 instanceof TypeParameter
2916+ |
2917+ FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , _, t0 )
29052918 or
2906- // match against the trait function itself
2907- exists ( Trait trait |
2908- FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2909- TSelfTypeParameter ( trait ) )
2910- )
2919+ traitFunctionDependsOnPos ( _, _, pos , t0 , i , f )
29112920 )
29122921 }
29132922
2914- class Call extends NonMethodCall {
2923+ final class Call extends NonMethodCall {
29152924 Type getArgType ( FunctionPosition pos , TypePath path ) {
29162925 result = inferType ( this .getNodeAt ( pos ) , path )
29172926 }
29182927
2919- predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2920- f = this .resolveAssocCallTargetCand ( i )
2921- or
2928+ predicate hasTraitResolvedCand ( ImplOrTraitItemNode i , Function f ) {
29222929 exists ( TraitItemNode trait , NonMethodFunction resolved , ImplItemNode i1 , Function f1 |
29232930 this .hasTraitResolved ( trait , resolved ) and
29242931 traitFunctionDependsOnPos ( trait , resolved , _, _, i1 , f1 )
@@ -2930,11 +2937,45 @@ private module NonMethodResolution {
29302937 i = trait
29312938 )
29322939 }
2940+
2941+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2942+ f = this .resolveCallTargetBlanketCand ( i )
2943+ or
2944+ this .hasTraitResolvedCand ( i , f ) and
2945+ BlanketImplementation:: isBlanketLike ( i , _, _)
2946+ }
2947+ }
2948+ }
2949+
2950+ private module NonMethodArgsAreInstantiationsOfBlanket =
2951+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfBlanketInput > ;
2952+
2953+ private module NonMethodArgsAreInstantiationsOfNonBlanketInput implements
2954+ ArgsAreInstantiationsOfInputSig
2955+ {
2956+ predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
2957+ NonMethodArgsAreInstantiationsOfBlanketInput:: toCheck ( i , f , pos , t )
2958+ or
2959+ // match against the trait function itself
2960+ t .appliesTo ( f , i , pos ) and
2961+ exists ( Trait trait |
2962+ FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2963+ TSelfTypeParameter ( trait ) )
2964+ )
2965+ }
2966+
2967+ class Call extends NonMethodArgsAreInstantiationsOfBlanketInput:: Call {
2968+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2969+ f = this .resolveCallTargetNonBlanketCand ( i )
2970+ or
2971+ this .hasTraitResolvedCand ( i , f ) and
2972+ not BlanketImplementation:: isBlanketLike ( i , _, _)
2973+ }
29332974 }
29342975 }
29352976
2936- private module NonMethodArgsAreInstantiationsOf =
2937- ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfInput > ;
2977+ private module NonMethodArgsAreInstantiationsOfNonBlanket =
2978+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfNonBlanketInput > ;
29382979}
29392980
29402981abstract private class TupleLikeConstructor extends Addressable {
0 commit comments