@@ -1056,33 +1056,128 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10561056 . unwrap_or_else ( |_| {
10571057 span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
10581058 } ) ;
1059- self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1060- . or_else ( || {
1061- self . pick_autorefd_method (
1062- step,
1063- self_ty,
1064- hir:: Mutability :: Not ,
1065- unstable_candidates. as_deref_mut ( ) ,
1066- )
1067- . or_else ( || {
1068- self . pick_autorefd_method (
1059+
1060+ let by_value_pick =
1061+ self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) ) ;
1062+
1063+ // Check for shadowing of a by-reference method by a by-value method (see comments on check_for_shadowing)
1064+ if let Some ( by_value_pick) = by_value_pick {
1065+ if let Ok ( by_value_pick) = by_value_pick. as_ref ( ) {
1066+ if by_value_pick. kind == PickKind :: InherentImplPick {
1067+ let autoref_pick = self . pick_autorefd_method (
1068+ step,
1069+ self_ty,
1070+ hir:: Mutability :: Not ,
1071+ unstable_candidates. as_deref_mut ( ) ,
1072+ ) ;
1073+ if let Err ( e) = self . check_for_shadowing ( by_value_pick, autoref_pick) {
1074+ return Some ( Err ( e) ) ;
1075+ }
1076+
1077+ let autoref_mut_pick = self . pick_autorefd_method (
10691078 step,
10701079 self_ty,
10711080 hir:: Mutability :: Mut ,
10721081 unstable_candidates. as_deref_mut ( ) ,
1073- )
1074- } )
1075- . or_else ( || {
1076- self . pick_const_ptr_method (
1082+ ) ;
1083+ if let Err ( e) =
1084+ self . check_for_shadowing ( by_value_pick, autoref_mut_pick)
1085+ {
1086+ return Some ( Err ( e) ) ;
1087+ }
1088+ }
1089+ }
1090+ return Some ( by_value_pick) ;
1091+ }
1092+
1093+ let autoref_pick = self . pick_autorefd_method (
1094+ step,
1095+ self_ty,
1096+ hir:: Mutability :: Not ,
1097+ unstable_candidates. as_deref_mut ( ) ,
1098+ ) ;
1099+ // Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing)
1100+ if let Some ( autoref_pick) = autoref_pick {
1101+ if let Ok ( autoref_pick) = autoref_pick. as_ref ( ) {
1102+ // Check we're not shadowing others
1103+ if autoref_pick. kind == PickKind :: InherentImplPick {
1104+ let autoref_mut_pick = self . pick_autorefd_method (
10771105 step,
10781106 self_ty,
1107+ hir:: Mutability :: Mut ,
10791108 unstable_candidates. as_deref_mut ( ) ,
1080- )
1081- } )
1082- } )
1109+ ) ;
1110+ if let Err ( e) = self . check_for_shadowing ( autoref_pick, autoref_mut_pick)
1111+ {
1112+ return Some ( Err ( e) ) ;
1113+ }
1114+ }
1115+ }
1116+ return Some ( autoref_pick) ;
1117+ }
1118+
1119+ // Note that no shadowing errors are produced from here on,
1120+ // as we consider const ptr methods.
1121+ // We allow new methods that take *mut T to shadow
1122+ // methods which took *const T, so there is no entry in
1123+ // this list for the results of `pick_const_ptr_method`.
1124+ // The reason is that the standard pointer cast method
1125+ // (on a mutable pointer) always already shadows the
1126+ // cast method (on a const pointer). So, if we added
1127+ // `pick_const_ptr_method` to this method, the anti-
1128+ // shadowing algorithm would always complain about
1129+ // the conflict between *const::cast and *mut::cast.
1130+ // In practice therefore this does constrain us:
1131+ // we cannot add new
1132+ // self: *mut Self
1133+ // methods to types such as NonNull or anything else
1134+ // which implements Receiver, because this might in future
1135+ // shadow existing methods taking
1136+ // self: *const NonNull<Self>
1137+ // in the pointee. In practice, methods taking raw pointers
1138+ // are rare, and it seems that it should be easily possible
1139+ // to avoid such compatibility breaks.
1140+ self . pick_autorefd_method (
1141+ step,
1142+ self_ty,
1143+ hir:: Mutability :: Mut ,
1144+ unstable_candidates. as_deref_mut ( ) ,
1145+ )
1146+ . or_else ( || {
1147+ self . pick_const_ptr_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1148+ } )
10831149 } )
10841150 }
10851151
1152+ /// Check for cases where arbitrary self types allows shadowing
1153+ /// of methods that might be a compatibility break. Specifically,
1154+ /// we have something like:
1155+ /// ```ignore (does not compile until arbitrary self types is fully implemented)
1156+ /// struct NonNull<T>(T);
1157+ /// struct A;
1158+ /// impl A {
1159+ /// fn foo(self: &NonNull<A>) {}
1160+ /// // note this is by reference
1161+ /// }
1162+ /// ```
1163+ /// then we've come along and added this method to `NonNull`:
1164+ /// ```
1165+ /// # struct NonNull<T>(T);
1166+ /// impl<T> NonNull<T> {
1167+ /// fn foo(self) {} // note this is by value
1168+ /// }
1169+ /// ```
1170+ /// Report an error in this case.
1171+ fn check_for_shadowing (
1172+ & self ,
1173+ _possible_shadower : & Pick < ' tcx > ,
1174+ _possible_shadowed : Option < Result < Pick < ' tcx > , MethodError < ' tcx > > > ,
1175+ ) -> Result < ( ) , MethodError < ' tcx > > {
1176+ // At the moment, this function does nothing. A future
1177+ // commit will fill out the body here.
1178+ Ok ( ( ) )
1179+ }
1180+
10861181 /// For each type `T` in the step list, this attempts to find a method where
10871182 /// the (transformed) self type is exactly `T`. We do however do one
10881183 /// transformation on the adjustment: if we are passing a region pointer in,
0 commit comments