@@ -1075,33 +1075,133 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1075
1075
. unwrap_or_else ( |_| {
1076
1076
span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
1077
1077
} ) ;
1078
- self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1079
- . or_else ( || {
1080
- self . pick_autorefd_method (
1081
- step,
1082
- self_ty,
1083
- hir:: Mutability :: Not ,
1084
- unstable_candidates. as_deref_mut ( ) ,
1085
- )
1086
- . or_else ( || {
1087
- self . pick_autorefd_method (
1078
+
1079
+ let by_value_pick =
1080
+ self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) ) ;
1081
+
1082
+ // Check for shadowing of a by-reference method by a by-value method (see comments on check_for_shadowing)
1083
+ if let Some ( by_value_pick) = by_value_pick {
1084
+ if let Ok ( by_value_pick) = by_value_pick. as_ref ( ) {
1085
+ if by_value_pick. kind == PickKind :: InherentImplPick {
1086
+ if let Err ( e) = self . check_for_shadowed_autorefd_method (
1087
+ by_value_pick,
1088
+ step,
1089
+ self_ty,
1090
+ hir:: Mutability :: Not ,
1091
+ unstable_candidates. is_some ( ) ,
1092
+ ) {
1093
+ return Some ( Err ( e) ) ;
1094
+ }
1095
+ if let Err ( e) = self . check_for_shadowed_autorefd_method (
1096
+ by_value_pick,
1088
1097
step,
1089
1098
self_ty,
1090
1099
hir:: Mutability :: Mut ,
1091
- unstable_candidates. as_deref_mut ( ) ,
1092
- )
1093
- } )
1094
- . or_else ( || {
1095
- self . pick_const_ptr_method (
1100
+ unstable_candidates. is_some ( ) ,
1101
+ ) {
1102
+ return Some ( Err ( e) ) ;
1103
+ }
1104
+ }
1105
+ }
1106
+ return Some ( by_value_pick) ;
1107
+ }
1108
+
1109
+ let autoref_pick = self . pick_autorefd_method (
1110
+ step,
1111
+ self_ty,
1112
+ hir:: Mutability :: Not ,
1113
+ unstable_candidates. as_deref_mut ( ) ,
1114
+ ) ;
1115
+ // Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing)
1116
+ if let Some ( autoref_pick) = autoref_pick {
1117
+ if let Ok ( autoref_pick) = autoref_pick. as_ref ( ) {
1118
+ // Check we're not shadowing others
1119
+ if autoref_pick. kind == PickKind :: InherentImplPick {
1120
+ if let Err ( e) = self . check_for_shadowed_autorefd_method (
1121
+ autoref_pick,
1096
1122
step,
1097
1123
self_ty,
1098
- unstable_candidates. as_deref_mut ( ) ,
1099
- )
1100
- } )
1101
- } )
1124
+ hir:: Mutability :: Mut ,
1125
+ unstable_candidates. is_some ( ) ,
1126
+ ) {
1127
+ return Some ( Err ( e) ) ;
1128
+ }
1129
+ }
1130
+ }
1131
+ return Some ( autoref_pick) ;
1132
+ }
1133
+
1134
+ // Note that no shadowing errors are produced from here on,
1135
+ // as we consider const ptr methods.
1136
+ // We allow new methods that take *mut T to shadow
1137
+ // methods which took *const T, so there is no entry in
1138
+ // this list for the results of `pick_const_ptr_method`.
1139
+ // The reason is that the standard pointer cast method
1140
+ // (on a mutable pointer) always already shadows the
1141
+ // cast method (on a const pointer). So, if we added
1142
+ // `pick_const_ptr_method` to this method, the anti-
1143
+ // shadowing algorithm would always complain about
1144
+ // the conflict between *const::cast and *mut::cast.
1145
+ // In practice therefore this does constrain us:
1146
+ // we cannot add new
1147
+ // self: *mut Self
1148
+ // methods to types such as NonNull or anything else
1149
+ // which implements Receiver, because this might in future
1150
+ // shadow existing methods taking
1151
+ // self: *const NonNull<Self>
1152
+ // in the pointee. In practice, methods taking raw pointers
1153
+ // are rare, and it seems that it should be easily possible
1154
+ // to avoid such compatibility breaks.
1155
+ self . pick_autorefd_method (
1156
+ step,
1157
+ self_ty,
1158
+ hir:: Mutability :: Mut ,
1159
+ unstable_candidates. as_deref_mut ( ) ,
1160
+ )
1161
+ . or_else ( || {
1162
+ self . pick_const_ptr_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1163
+ } )
1102
1164
} )
1103
1165
}
1104
1166
1167
+ /// Check for cases where arbitrary self types allows shadowing
1168
+ /// of methods that might be a compatibility break. Specifically,
1169
+ /// we have something like:
1170
+ /// ```compile_fail
1171
+ /// # use std::ptr::NonNull;
1172
+ /// struct A;
1173
+ /// impl A {
1174
+ /// fn foo(self: &NonNull<A>) {}
1175
+ /// // note this is by reference
1176
+ /// }
1177
+ /// ```
1178
+ /// then we've come along and added this method to `NonNull`:
1179
+ /// ```
1180
+ /// # struct NonNull;
1181
+ /// # impl NonNull {
1182
+ /// fn foo(self) {} // note this is by value
1183
+ /// # }
1184
+ /// ```
1185
+ /// Report an error in this case.
1186
+ fn check_for_shadowed_autorefd_method (
1187
+ & self ,
1188
+ _possible_shadower : & Pick < ' tcx > ,
1189
+ step : & CandidateStep < ' tcx > ,
1190
+ self_ty : Ty < ' tcx > ,
1191
+ mutbl : hir:: Mutability ,
1192
+ tracking_unstable_candidates : bool ,
1193
+ ) -> Result < ( ) , MethodError < ' tcx > > {
1194
+ let mut empty_vec = vec ! [ ] ;
1195
+ let unstable_candidates_for_shadow_probe =
1196
+ if tracking_unstable_candidates { Some ( & mut empty_vec) } else { None } ;
1197
+ let _potentially_shadowed_pick =
1198
+ self . pick_autorefd_method ( step, self_ty, mutbl, unstable_candidates_for_shadow_probe) ;
1199
+
1200
+ // At the moment, this function does no checks. A future
1201
+ // commit will fill out the body here.
1202
+ Ok ( ( ) )
1203
+ }
1204
+
1105
1205
/// For each type `T` in the step list, this attempts to find a method where
1106
1206
/// the (transformed) self type is exactly `T`. We do however do one
1107
1207
/// transformation on the adjustment: if we are passing a region pointer in,
@@ -1221,6 +1321,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1221
1321
1222
1322
// `pick_method` may be called twice for the same self_ty if no stable methods
1223
1323
// match. Only extend once.
1324
+ // FIXME: this shouldn't be done when we're probing just for shadowing possibilities.
1224
1325
if unstable_candidates. is_some ( ) {
1225
1326
self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
1226
1327
}
0 commit comments