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