@@ -1071,26 +1071,130 @@ 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, & mut unstable_candidates) . or_else ( || {
1075
- self . pick_autorefd_method (
1076
- step,
1077
- self_ty,
1078
- hir:: Mutability :: Not ,
1079
- & mut unstable_candidates,
1080
- )
1081
- . or_else ( || {
1082
- self . pick_autorefd_method (
1083
- step,
1084
- self_ty,
1085
- hir:: Mutability :: Mut ,
1086
- & mut unstable_candidates,
1087
- )
1088
- } )
1089
- . or_else ( || self . pick_const_ptr_method ( step, self_ty, & mut unstable_candidates) )
1090
- } )
1074
+
1075
+ let by_value_pick =
1076
+ self . pick_by_value_method ( step, self_ty, & mut unstable_candidates) ;
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,
1093
+ step,
1094
+ self_ty,
1095
+ hir:: Mutability :: Mut ,
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
+ & mut unstable_candidates,
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,
1118
+ step,
1119
+ self_ty,
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
+ & mut unstable_candidates,
1156
+ )
1157
+ . or_else ( || self . pick_const_ptr_method ( step, self_ty, & mut unstable_candidates) )
1091
1158
} )
1092
1159
}
1093
1160
1161
+ /// Check for cases where arbitrary self types allows shadowing
1162
+ /// of methods that might be a compatibility break. Specifically,
1163
+ /// we have something like:
1164
+ /// ```
1165
+ /// struct A;
1166
+ /// impl A {
1167
+ /// fn foo(self: &NonNull<A>) {}
1168
+ /// // note this is by reference
1169
+ /// }
1170
+ /// ```
1171
+ /// then we've come along and added this method to `NonNull`:
1172
+ /// ```
1173
+ /// fn foo(self) // note this is by value
1174
+ /// ```
1175
+ /// Report an error in this case.
1176
+ fn check_for_shadowed_autorefd_method (
1177
+ & self ,
1178
+ _possible_shadower : & Pick < ' tcx > ,
1179
+ step : & CandidateStep < ' tcx > ,
1180
+ self_ty : Ty < ' tcx > ,
1181
+ mutbl : hir:: Mutability ,
1182
+ tracking_unstable_candidates : bool ,
1183
+ ) -> Result < ( ) , MethodError < ' tcx > > {
1184
+ let mut unstable_candidates_for_shadow_probe =
1185
+ if tracking_unstable_candidates { Some ( vec ! [ ] ) } else { None } ;
1186
+ let _potentially_shadowed_pick = self . pick_autorefd_method (
1187
+ step,
1188
+ self_ty,
1189
+ mutbl,
1190
+ & mut unstable_candidates_for_shadow_probe,
1191
+ ) ;
1192
+
1193
+ // At the moment, this function does no checks. A future
1194
+ // commit will fill out the body here.
1195
+ Ok ( ( ) )
1196
+ }
1197
+
1094
1198
/// For each type `T` in the step list, this attempts to find a method where
1095
1199
/// the (transformed) self type is exactly `T`. We do however do one
1096
1200
/// transformation on the adjustment: if we are passing a region pointer in,
@@ -1210,6 +1314,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1210
1314
1211
1315
// `pick_method` may be called twice for the same self_ty if no stable methods
1212
1316
// match. Only extend once.
1317
+ // FIXME: this shouldn't be done when we're probing just for shadowing possibilities.
1213
1318
if unstable_candidates. is_some ( ) {
1214
1319
self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
1215
1320
}
0 commit comments