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

`}

`