Auto merge of #90329 - nbdd0121:typeck, r=nagisa · rust-lang/rust@ce3f3a5 (original) (raw)
`@@ -92,7 +92,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
`
92
92
`}
`
93
93
`}
`
94
94
``
95
``
`-
#[derive(Debug)]
`
``
95
`+
#[derive(Debug, Clone)]
`
96
96
`struct Candidate<'tcx> {
`
97
97
`// Candidates are (I'm not quite sure, but they are mostly) basically
`
98
98
`` // some metadata on top of a ty::AssocItem
(without substs).
``
`@@ -132,7 +132,7 @@ struct Candidate<'tcx> {
`
132
132
`import_ids: SmallVec<[LocalDefId; 1]>,
`
133
133
`}
`
134
134
``
135
``
`-
#[derive(Debug)]
`
``
135
`+
#[derive(Debug, Clone)]
`
136
136
`enum CandidateKind<'tcx> {
`
137
137
`InherentImplCandidate(
`
138
138
`SubstsRef<'tcx>,
`
`@@ -204,6 +204,7 @@ pub struct Pick<'tcx> {
`
204
204
`/// Indicates that we want to add an autoref (and maybe also unsize it), or if the receiver is
`
205
205
`` /// *mut T
, convert it to *const T
.
``
206
206
`pub autoref_or_ptr_adjustment: Option<AutorefOrPtrAdjustment<'tcx>>,
`
``
207
`+
pub self_ty: Ty<'tcx>,
`
207
208
`}
`
208
209
``
209
210
`#[derive(Clone, Debug, PartialEq, Eq)]
`
`@@ -1101,13 +1102,37 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1101
1102
`}
`
1102
1103
``
1103
1104
`fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
`
1104
``
`-
let steps = self.steps.clone();
`
``
1105
`+
let mut unstable_candidates = Vec::new();
`
``
1106
`+
let pick = self.pick_all_method(Some(&mut unstable_candidates));
`
``
1107
+
``
1108
`` +
// In this case unstable picking is done by pick_method
.
``
``
1109
`+
if !self.tcx.sess.opts.debugging_opts.pick_stable_methods_before_any_unstable {
`
``
1110
`+
return pick;
`
``
1111
`+
}
`
1105
1112
``
1106
``
`-
// find the first step that works
`
``
1113
`+
match pick {
`
``
1114
`+
// Emit a lint if there are unstable candidates alongside the stable ones.
`
``
1115
`+
//
`
``
1116
`+
// We suppress warning if we're picking the method only because it is a
`
``
1117
`+
// suggestion.
`
``
1118
`+
Some(Ok(ref p)) if !self.is_suggestion.0 && !unstable_candidates.is_empty() => {
`
``
1119
`+
self.emit_unstable_name_collision_hint(p, &unstable_candidates);
`
``
1120
`+
pick
`
``
1121
`+
}
`
``
1122
`+
Some(_) => pick,
`
``
1123
`+
None => self.pick_all_method(None),
`
``
1124
`+
}
`
``
1125
`+
}
`
``
1126
+
``
1127
`+
fn pick_all_method(
`
``
1128
`+
&mut self,
`
``
1129
`+
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
`
``
1130
`+
) -> Option<PickResult<'tcx>> {
`
``
1131
`+
let steps = self.steps.clone();
`
1107
1132
` steps
`
1108
1133
`.iter()
`
1109
1134
`.filter(|step| {
`
1110
``
`-
debug!("pick_core: step={:?}", step);
`
``
1135
`+
debug!("pick_all_method: step={:?}", step);
`
1111
1136
`// skip types that are from a type error or that would require dereferencing
`
1112
1137
`// a raw pointer
`
1113
1138
` !step.self_ty.references_error() && !step.from_unsafe_deref
`
`@@ -1123,11 +1148,30 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1123
1148
`.unwrap_or_else(|_| {
`
1124
1149
`span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty)
`
1125
1150
`});
`
1126
``
`-
self.pick_by_value_method(step, self_ty).or_else(|| {
`
1127
``
`-
self.pick_autorefd_method(step, self_ty, hir::Mutability::Not)
`
1128
``
`-
.or_else(|| self.pick_autorefd_method(step, self_ty, hir::Mutability::Mut))
`
1129
``
`-
.or_else(|| self.pick_const_ptr_method(step, self_ty))
`
1130
``
`-
})
`
``
1151
`+
self.pick_by_value_method(step, self_ty, unstable_candidates.as_deref_mut())
`
``
1152
`+
.or_else(|| {
`
``
1153
`+
self.pick_autorefd_method(
`
``
1154
`+
step,
`
``
1155
`+
self_ty,
`
``
1156
`+
hir::Mutability::Not,
`
``
1157
`+
unstable_candidates.as_deref_mut(),
`
``
1158
`+
)
`
``
1159
`+
.or_else(|| {
`
``
1160
`+
self.pick_autorefd_method(
`
``
1161
`+
step,
`
``
1162
`+
self_ty,
`
``
1163
`+
hir::Mutability::Mut,
`
``
1164
`+
unstable_candidates.as_deref_mut(),
`
``
1165
`+
)
`
``
1166
`+
})
`
``
1167
`+
.or_else(|| {
`
``
1168
`+
self.pick_const_ptr_method(
`
``
1169
`+
step,
`
``
1170
`+
self_ty,
`
``
1171
`+
unstable_candidates.as_deref_mut(),
`
``
1172
`+
)
`
``
1173
`+
})
`
``
1174
`+
})
`
1131
1175
`})
`
1132
1176
`.next()
`
1133
1177
`}
`
`@@ -1142,12 +1186,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1142
1186
`&mut self,
`
1143
1187
`step: &CandidateStep<'tcx>,
`
1144
1188
`self_ty: Ty<'tcx>,
`
``
1189
`+
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
`
1145
1190
`) -> Option<PickResult<'tcx>> {
`
1146
1191
`if step.unsize {
`
1147
1192
`return None;
`
1148
1193
`}
`
1149
1194
``
1150
``
`-
self.pick_method(self_ty).map(|r| {
`
``
1195
`+
self.pick_method(self_ty, unstable_candidates).map(|r| {
`
1151
1196
` r.map(|mut pick| {
`
1152
1197
` pick.autoderefs = step.autoderefs;
`
1153
1198
``
`@@ -1170,14 +1215,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1170
1215
`step: &CandidateStep<'tcx>,
`
1171
1216
`self_ty: Ty<'tcx>,
`
1172
1217
`mutbl: hir::Mutability,
`
``
1218
`+
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
`
1173
1219
`) -> Option<PickResult<'tcx>> {
`
1174
1220
`let tcx = self.tcx;
`
1175
1221
``
1176
1222
`// In general, during probing we erase regions.
`
1177
1223
`let region = tcx.lifetimes.re_erased;
`
1178
1224
``
1179
1225
`let autoref_ty = tcx.mk_ref(region, ty::TypeAndMut { ty: self_ty, mutbl });
`
1180
``
`-
self.pick_method(autoref_ty).map(|r| {
`
``
1226
`+
self.pick_method(autoref_ty, unstable_candidates).map(|r| {
`
1181
1227
` r.map(|mut pick| {
`
1182
1228
` pick.autoderefs = step.autoderefs;
`
1183
1229
` pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
`
`@@ -1196,6 +1242,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1196
1242
`&mut self,
`
1197
1243
`step: &CandidateStep<'tcx>,
`
1198
1244
`self_ty: Ty<'tcx>,
`
``
1245
`+
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
`
1199
1246
`) -> Option<PickResult<'tcx>> {
`
1200
1247
`// Don't convert an unsized reference to ptr
`
1201
1248
`if step.unsize {
`
`@@ -1209,7 +1256,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1209
1256
``
1210
1257
`let const_self_ty = ty::TypeAndMut { ty, mutbl: hir::Mutability::Not };
`
1211
1258
`let const_ptr_ty = self.tcx.mk_ptr(const_self_ty);
`
1212
``
`-
self.pick_method(const_ptr_ty).map(|r| {
`
``
1259
`+
self.pick_method(const_ptr_ty, unstable_candidates).map(|r| {
`
1213
1260
` r.map(|mut pick| {
`
1214
1261
` pick.autoderefs = step.autoderefs;
`
1215
1262
` pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr);
`
`@@ -1218,8 +1265,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1218
1265
`})
`
1219
1266
`}
`
1220
1267
``
1221
``
`-
fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
`
1222
``
`-
debug!("pick_method(self_ty={})", self.ty_to_string(self_ty));
`
``
1268
`+
fn pick_method_with_unstable(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
`
``
1269
`+
debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty));
`
1223
1270
``
1224
1271
`let mut possibly_unsatisfied_predicates = Vec::new();
`
1225
1272
`let mut unstable_candidates = Vec::new();
`
`@@ -1241,7 +1288,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1241
1288
`//
`
1242
1289
`// We suppress warning if we're picking the method only because it is a
`
1243
1290
`// suggestion.
`
1244
``
`-
self.emit_unstable_name_collision_hint(p, &unstable_candidates, self_ty);
`
``
1291
`+
self.emit_unstable_name_collision_hint(p, &unstable_candidates);
`
1245
1292
`}
`
1246
1293
`}
`
1247
1294
`return Some(pick);
`
`@@ -1251,7 +1298,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1251
1298
`debug!("searching unstable candidates");
`
1252
1299
`let res = self.consider_candidates(
`
1253
1300
` self_ty,
`
1254
``
`-
unstable_candidates.into_iter().map(|(c, _)| c),
`
``
1301
`+
unstable_candidates.iter().map(|(c, _)| c),
`
1255
1302
`&mut possibly_unsatisfied_predicates,
`
1256
1303
`None,
`
1257
1304
`);
`
`@@ -1261,6 +1308,42 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1261
1308
` res
`
1262
1309
`}
`
1263
1310
``
``
1311
`+
fn pick_method(
`
``
1312
`+
&mut self,
`
``
1313
`+
self_ty: Ty<'tcx>,
`
``
1314
`+
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
`
``
1315
`+
) -> Option<PickResult<'tcx>> {
`
``
1316
`+
if !self.tcx.sess.opts.debugging_opts.pick_stable_methods_before_any_unstable {
`
``
1317
`+
return self.pick_method_with_unstable(self_ty);
`
``
1318
`+
}
`
``
1319
+
``
1320
`+
debug!("pick_method(self_ty={})", self.ty_to_string(self_ty));
`
``
1321
+
``
1322
`+
let mut possibly_unsatisfied_predicates = Vec::new();
`
``
1323
+
``
1324
`+
for (kind, candidates) in
`
``
1325
`+
&[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
`
``
1326
`+
{
`
``
1327
`+
debug!("searching {} candidates", kind);
`
``
1328
`+
let res = self.consider_candidates(
`
``
1329
`+
self_ty,
`
``
1330
`+
candidates.iter(),
`
``
1331
`+
&mut possibly_unsatisfied_predicates,
`
``
1332
`+
unstable_candidates.as_deref_mut(),
`
``
1333
`+
);
`
``
1334
`+
if let Some(pick) = res {
`
``
1335
`+
return Some(pick);
`
``
1336
`+
}
`
``
1337
`+
}
`
``
1338
+
``
1339
`` +
// pick_method
may be called twice for the same self_ty if no stable methods
``
``
1340
`+
// match. Only extend once.
`
``
1341
`+
if unstable_candidates.is_some() {
`
``
1342
`+
self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
`
``
1343
`+
}
`
``
1344
`+
None
`
``
1345
`+
}
`
``
1346
+
1264
1347
`fn consider_candidates<'b, ProbesIter>(
`
1265
1348
`&self,
`
1266
1349
`self_ty: Ty<'tcx>,
`
`@@ -1269,10 +1352,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1269
1352
` ty::Predicate<'tcx>,
`
1270
1353
`Option<ty::Predicate<'tcx>>,
`
1271
1354
`)>,
`
1272
``
`-
unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>,
`
``
1355
`+
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
`
1273
1356
`) -> Option<PickResult<'tcx>>
`
1274
1357
`where
`
1275
1358
`ProbesIter: Iterator<Item = &'b Candidate<'tcx>> + Clone,
`
``
1359
`+
'tcx: 'b,
`
1276
1360
`{
`
1277
1361
`let mut applicable_candidates: Vec<_> = probes
`
1278
1362
`.clone()
`
`@@ -1285,7 +1369,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1285
1369
`debug!("applicable_candidates: {:?}", applicable_candidates);
`
1286
1370
``
1287
1371
`if applicable_candidates.len() > 1 {
`
1288
``
`-
if let Some(pick) = self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) {
`
``
1372
`+
if let Some(pick) =
`
``
1373
`+
self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates[..])
`
``
1374
`+
{
`
1289
1375
`return Some(Ok(pick));
`
1290
1376
`}
`
1291
1377
`}
`
`@@ -1295,7 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1295
1381
`if let stability::EvalResult::Deny { feature, .. } =
`
1296
1382
`self.tcx.eval_stability(p.item.def_id, None, self.span, None)
`
1297
1383
`{
`
1298
``
`-
uc.push((p, feature));
`
``
1384
`+
uc.push((p.clone(), feature));
`
1299
1385
`return false;
`
1300
1386
`}
`
1301
1387
`true
`
`@@ -1309,7 +1395,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1309
1395
``
1310
1396
` applicable_candidates.pop().map(|(probe, status)| {
`
1311
1397
`if status == ProbeResult::Match {
`
1312
``
`-
Ok(probe.to_unadjusted_pick())
`
``
1398
`+
Ok(probe.to_unadjusted_pick(self_ty))
`
1313
1399
`} else {
`
1314
1400
`Err(MethodError::BadReturnType)
`
1315
1401
`}
`
`@@ -1319,8 +1405,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1319
1405
`fn emit_unstable_name_collision_hint(
`
1320
1406
`&self,
`
1321
1407
`stable_pick: &Pick<'_>,
`
1322
``
`-
unstable_candidates: &[(&Candidate<'tcx>, Symbol)],
`
1323
``
`-
self_ty: Ty<'tcx>,
`
``
1408
`+
unstable_candidates: &[(Candidate<'tcx>, Symbol)],
`
1324
1409
`) {
`
1325
1410
`self.tcx.struct_span_lint_hir(
`
1326
1411
` lint::builtin::UNSTABLE_NAME_COLLISIONS,
`
`@@ -1351,7 +1436,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1351
1436
`"use the fully qualified path to the associated const",
`
1352
1437
`format!(
`
1353
1438
`"<{} as {}>::{}",
`
1354
``
`-
self_ty,
`
``
1439
`+
stable_pick.self_ty,
`
1355
1440
`self.tcx.def_path_str(def_id),
`
1356
1441
` stable_pick.item.ident
`
1357
1442
`),
`
`@@ -1591,6 +1676,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1591
1676
`/// use, so it's ok to just commit to "using the method from the trait Foo".
`
1592
1677
`fn collapse_candidates_to_trait_pick(
`
1593
1678
`&self,
`
``
1679
`+
self_ty: Ty<'tcx>,
`
1594
1680
`probes: &[(&Candidate<'tcx>, ProbeResult)],
`
1595
1681
`) -> Option<Pick<'tcx>> {
`
1596
1682
`// Do all probes correspond to the same trait?
`
`@@ -1610,6 +1696,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1610
1696
`import_ids: probes[0].0.import_ids.clone(),
`
1611
1697
`autoderefs: 0,
`
1612
1698
`autoref_or_ptr_adjustment: None,
`
``
1699
`+
self_ty,
`
1613
1700
`})
`
1614
1701
`}
`
1615
1702
``
`@@ -1828,7 +1915,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
`
1828
1915
`}
`
1829
1916
``
1830
1917
`impl<'tcx> Candidate<'tcx> {
`
1831
``
`-
fn to_unadjusted_pick(&self) -> Pick<'tcx> {
`
``
1918
`+
fn to_unadjusted_pick(&self, self_ty: Ty<'tcx>) -> Pick<'tcx> {
`
1832
1919
`Pick {
`
1833
1920
`item: self.item,
`
1834
1921
`kind: match self.kind {
`
`@@ -1852,6 +1939,7 @@ impl<'tcx> Candidate<'tcx> {
`
1852
1939
`import_ids: self.import_ids.clone(),
`
1853
1940
`autoderefs: 0,
`
1854
1941
`autoref_or_ptr_adjustment: None,
`
``
1942
`+
self_ty,
`
1855
1943
`}
`
1856
1944
`}
`
1857
1945
`}
`