@@ -2741,7 +2741,7 @@ private module NonMethodResolution {
27412741 * Gets the blanket function that this call may resolve to, if any.
27422742 */
27432743 pragma [ nomagic]
2744- private NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
2744+ NonMethodFunction resolveCallTargetBlanketCand ( ImplItemNode impl ) {
27452745 exists ( string name |
27462746 this .hasNameAndArity ( pragma [ only_bind_into ] ( name ) , _) and
27472747 ArgIsInstantiationOfBlanketParam:: argIsInstantiationOf ( MkCallAndBlanketPos ( this , _) , impl , _) and
@@ -2756,12 +2756,11 @@ private module NonMethodResolution {
27562756 predicate hasTrait ( ) { exists ( this .getTrait ( ) ) }
27572757
27582758 pragma [ nomagic]
2759- NonMethodFunction resolveAssocCallTargetCand ( ImplItemNode i ) {
2759+ NonMethodFunction resolveCallTargetNonBlanketCand ( ImplItemNode i ) {
27602760 not this .hasTrait ( ) and
27612761 result = this .getPathResolutionResolved ( ) and
2762- result = i .getASuccessor ( _)
2763- or
2764- result = this .resolveCallTargetBlanketCand ( i )
2762+ result = i .getASuccessor ( _) and
2763+ FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
27652764 }
27662765
27672766 AstNode getNodeAt ( FunctionPosition pos ) {
@@ -2793,6 +2792,16 @@ private module NonMethodResolution {
27932792 trait = this .getTrait ( )
27942793 }
27952794
2795+ pragma [ nomagic]
2796+ predicate hasNoCompatibleNonBlanketTarget ( ) {
2797+ not exists ( this .resolveCallTargetViaPathResolution ( ) ) and
2798+ forall ( ImplOrTraitItemNode i , Function f |
2799+ this .( NonMethodArgsAreInstantiationsOfNonBlanketInput:: Call ) .hasTargetCand ( i , f )
2800+ |
2801+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreNotInstantiationsOf ( this , i , f )
2802+ )
2803+ }
2804+
27962805 /**
27972806 * Gets the target of this call, which can be resolved using only path resolution.
27982807 */
@@ -2811,7 +2820,9 @@ private module NonMethodResolution {
28112820 result = this .resolveCallTargetBlanketCand ( i ) and
28122821 not FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , _, _, _)
28132822 or
2814- NonMethodArgsAreInstantiationsOf:: argsAreInstantiationsOf ( this , i , result )
2823+ NonMethodArgsAreInstantiationsOfBlanket:: argsAreInstantiationsOf ( this , i , result )
2824+ or
2825+ NonMethodArgsAreInstantiationsOfNonBlanket:: argsAreInstantiationsOf ( this , i , result )
28152826 }
28162827
28172828 pragma [ nomagic]
@@ -2850,7 +2861,11 @@ private module NonMethodResolution {
28502861 ) {
28512862 exists ( NonMethodCall fc , FunctionPosition pos |
28522863 fcp = MkCallAndBlanketPos ( fc , pos ) and
2853- fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam )
2864+ fc .resolveCallTargetBlanketLikeCandidate ( impl , pos , blanketPath , blanketTypeParam ) and
2865+ // Only apply blanket implementations when no other implementations are possible;
2866+ // this is to account for codebases that use the (unstable) specialization feature
2867+ // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
2868+ ( fc .hasNoCompatibleNonBlanketTarget ( ) or not impl .isBlanketImplementation ( ) )
28542869 )
28552870 }
28562871 }
@@ -2885,37 +2900,29 @@ private module NonMethodResolution {
28852900 private module ArgIsInstantiationOfBlanketParam =
28862901 ArgIsInstantiationOf< CallAndBlanketPos , ArgIsInstantiationOfBlanketParamInput > ;
28872902
2888- private module NonMethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
2903+ private module NonMethodArgsAreInstantiationsOfBlanketInput implements
2904+ ArgsAreInstantiationsOfInputSig
2905+ {
28892906 predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
28902907 t .appliesTo ( f , i , pos ) and
2891- (
2892- exists ( Type t0 |
2893- // for now, we do not handle ambiguous targets when one of the types it iself
2894- // a type parameter; we should be checking the constraints on that type parameter
2895- // in this case
2896- not t0 instanceof TypeParameter
2897- |
2898- FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , _, t0 )
2899- or
2900- traitFunctionDependsOnPos ( _, _, pos , t0 , i , f )
2901- )
2908+ exists ( Type t0 |
2909+ // for now, we do not handle ambiguous targets when one of the types it iself
2910+ // a type parameter; we should be checking the constraints on that type parameter
2911+ // in this case
2912+ not t0 instanceof TypeParameter
2913+ |
2914+ FunctionOverloading:: functionResolutionDependsOnArgument ( i , f , pos , _, t0 )
29022915 or
2903- // match against the trait function itself
2904- exists ( Trait trait |
2905- FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2906- TSelfTypeParameter ( trait ) )
2907- )
2916+ traitFunctionDependsOnPos ( _, _, pos , t0 , i , f )
29082917 )
29092918 }
29102919
2911- class Call extends NonMethodCall {
2920+ final class Call extends NonMethodCall {
29122921 Type getArgType ( FunctionPosition pos , TypePath path ) {
29132922 result = inferType ( this .getNodeAt ( pos ) , path )
29142923 }
29152924
2916- predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2917- f = this .resolveAssocCallTargetCand ( i )
2918- or
2925+ predicate hasTraitResolvedCand ( ImplOrTraitItemNode i , Function f ) {
29192926 exists ( TraitItemNode trait , NonMethodFunction resolved , ImplItemNode i1 , Function f1 |
29202927 this .hasTraitResolved ( trait , resolved ) and
29212928 traitFunctionDependsOnPos ( trait , resolved , _, _, i1 , f1 )
@@ -2927,11 +2934,45 @@ private module NonMethodResolution {
29272934 i = trait
29282935 )
29292936 }
2937+
2938+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2939+ f = this .resolveCallTargetBlanketCand ( i )
2940+ or
2941+ this .hasTraitResolvedCand ( i , f ) and
2942+ BlanketImplementation:: isBlanketLike ( i , _, _)
2943+ }
2944+ }
2945+ }
2946+
2947+ private module NonMethodArgsAreInstantiationsOfBlanket =
2948+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfBlanketInput > ;
2949+
2950+ private module NonMethodArgsAreInstantiationsOfNonBlanketInput implements
2951+ ArgsAreInstantiationsOfInputSig
2952+ {
2953+ predicate toCheck ( ImplOrTraitItemNode i , Function f , FunctionPosition pos , AssocFunctionType t ) {
2954+ NonMethodArgsAreInstantiationsOfBlanketInput:: toCheck ( i , f , pos , t )
2955+ or
2956+ // match against the trait function itself
2957+ t .appliesTo ( f , i , pos ) and
2958+ exists ( Trait trait |
2959+ FunctionOverloading:: traitTypeParameterOccurrence ( trait , f , _, pos , _,
2960+ TSelfTypeParameter ( trait ) )
2961+ )
2962+ }
2963+
2964+ class Call extends NonMethodArgsAreInstantiationsOfBlanketInput:: Call {
2965+ predicate hasTargetCand ( ImplOrTraitItemNode i , Function f ) {
2966+ f = this .resolveCallTargetNonBlanketCand ( i )
2967+ or
2968+ this .hasTraitResolvedCand ( i , f ) and
2969+ not BlanketImplementation:: isBlanketLike ( i , _, _)
2970+ }
29302971 }
29312972 }
29322973
2933- private module NonMethodArgsAreInstantiationsOf =
2934- ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfInput > ;
2974+ private module NonMethodArgsAreInstantiationsOfNonBlanket =
2975+ ArgsAreInstantiationsOf< NonMethodArgsAreInstantiationsOfNonBlanketInput > ;
29352976}
29362977
29372978abstract private class TupleLikeConstructor extends Addressable {
0 commit comments