@@ -1056,33 +1056,128 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1056
1056
. unwrap_or_else ( |_| {
1057
1057
span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
1058
1058
} ) ;
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 (
1069
1078
step,
1070
1079
self_ty,
1071
1080
hir:: Mutability :: Mut ,
1072
1081
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 (
1077
1105
step,
1078
1106
self_ty,
1107
+ hir:: Mutability :: Mut ,
1079
1108
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
+ } )
1083
1149
} )
1084
1150
}
1085
1151
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
+
1086
1181
/// For each type `T` in the step list, this attempts to find a method where
1087
1182
/// the (transformed) self type is exactly `T`. We do however do one
1088
1183
/// transformation on the adjustment: if we are passing a region pointer in,
0 commit comments