Skip to content

Commit 7e0e0a3

Browse files
authored
Unrolled build for #152225
Rollup merge of #152225 - Amanieu:type-supertrait-shadowing, r=jackh726 Add supertrait item shadowing for type-level path resolution This makes type-level name resolution (used primarily for associated types) also prefer subtrait items to supertrait items in case of ambiguity. This addresses the concern from #148605 about the inconsistency with name resolution in expressions and method calls.
2 parents 8b95a26 + af3eaee commit 7e0e0a3

45 files changed

Lines changed: 1246 additions & 455 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
409409

410410
pub(super) fn report_ambiguous_assoc_item(
411411
&self,
412-
bound1: ty::PolyTraitRef<'tcx>,
413-
bound2: ty::PolyTraitRef<'tcx>,
414-
matching_candidates: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
412+
matching_candidates: &[ty::PolyTraitRef<'tcx>],
415413
qself: AssocItemQSelf,
416414
assoc_tag: ty::AssocTag,
417415
assoc_ident: Ident,
@@ -443,7 +441,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
443441
// predicates!).
444442
// FIXME: Turn this into a structured, translatable & more actionable suggestion.
445443
let mut where_bounds = vec![];
446-
for bound in [bound1, bound2].into_iter().chain(matching_candidates) {
444+
for &bound in matching_candidates {
447445
let bound_id = bound.def_id();
448446
let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind(
449447
tcx,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use std::{assert_matches, slice};
2424
use rustc_abi::FIRST_VARIANT;
2525
use rustc_ast::LitKind;
2626
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
27+
use rustc_data_structures::sso::SsoHashSet;
2728
use rustc_errors::codes::*;
2829
use rustc_errors::{
2930
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, StashKey,
@@ -1262,6 +1263,74 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12621263
)
12631264
}
12641265

1266+
/// When there are multiple traits which contain an identically named
1267+
/// associated item, this function eliminates any traits which are a
1268+
/// supertrait of another candidate trait.
1269+
///
1270+
/// This is the type-level analogue of
1271+
/// `rustc_hir_typeck::method::probe::ProbeContext::collapse_candidates_to_subtrait_pick`;
1272+
/// keep both implementations in sync.
1273+
///
1274+
/// This implements RFC #3624.
1275+
fn collapse_candidates_to_subtrait_pick(
1276+
&self,
1277+
matching_candidates: &[ty::PolyTraitRef<'tcx>],
1278+
) -> Option<ty::PolyTraitRef<'tcx>> {
1279+
if !self.tcx().features().supertrait_item_shadowing() {
1280+
return None;
1281+
}
1282+
1283+
let mut child_trait = matching_candidates[0];
1284+
let mut supertraits: SsoHashSet<_> =
1285+
traits::supertrait_def_ids(self.tcx(), child_trait.def_id()).collect();
1286+
1287+
let mut remaining_candidates: Vec<_> = matching_candidates[1..].iter().copied().collect();
1288+
while !remaining_candidates.is_empty() {
1289+
let mut made_progress = false;
1290+
let mut next_round = vec![];
1291+
1292+
for remaining_trait in remaining_candidates {
1293+
if supertraits.contains(&remaining_trait.def_id()) {
1294+
made_progress = true;
1295+
continue;
1296+
}
1297+
1298+
// This candidate is not a supertrait of the `child_trait`.
1299+
// Check if it's a subtrait of the `child_trait`, instead.
1300+
// If it is, then it must have been a subtrait of every
1301+
// other pick we've eliminated at this point. It will
1302+
// take over at this point.
1303+
let remaining_trait_supertraits: SsoHashSet<_> =
1304+
traits::supertrait_def_ids(self.tcx(), remaining_trait.def_id()).collect();
1305+
if remaining_trait_supertraits.contains(&child_trait.def_id()) {
1306+
child_trait = remaining_trait;
1307+
supertraits = remaining_trait_supertraits;
1308+
made_progress = true;
1309+
continue;
1310+
}
1311+
1312+
// Neither `child_trait` or the current candidate are
1313+
// supertraits of each other.
1314+
// Don't bail here, since we may be comparing two supertraits
1315+
// of a common subtrait. These two supertraits won't be related
1316+
// at all, but we will pick them up next round when we find their
1317+
// child as we continue iterating in this round.
1318+
next_round.push(remaining_trait);
1319+
}
1320+
1321+
if made_progress {
1322+
// If we've made progress, iterate again.
1323+
remaining_candidates = next_round;
1324+
} else {
1325+
// Otherwise, we must have at least two candidates which
1326+
// are not related to each other at all.
1327+
return None;
1328+
}
1329+
}
1330+
1331+
Some(child_trait)
1332+
}
1333+
12651334
/// Search for a single trait bound whose trait defines the associated item given by
12661335
/// `assoc_ident`.
12671336
///
@@ -1296,10 +1365,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12961365
};
12971366

12981367
if let Some(bound2) = matching_candidates.next() {
1368+
let all_matching_candidates: Vec<_> =
1369+
[bound1, bound2].into_iter().chain(matching_candidates).collect();
1370+
if let Some(bound) = self.collapse_candidates_to_subtrait_pick(&all_matching_candidates)
1371+
{
1372+
return Ok(bound);
1373+
}
1374+
12991375
return Err(self.report_ambiguous_assoc_item(
1300-
bound1,
1301-
bound2,
1302-
matching_candidates,
1376+
&all_matching_candidates,
13031377
qself,
13041378
assoc_tag,
13051379
assoc_ident,

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,6 +2359,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
23592359
/// multiple conflicting picks if there is one pick whose trait container is a subtrait
23602360
/// of the trait containers of all of the other picks.
23612361
///
2362+
/// This is the method-probe analogue of
2363+
/// `rustc_hir_analysis::hir_ty_lowering::HirTyLowerer::collapse_candidates_to_subtrait_pick`;
2364+
/// keep both implementations in sync.
2365+
///
23622366
/// This implements RFC #3624.
23632367
fn collapse_candidates_to_subtrait_pick(
23642368
&self,

tests/ui/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,10 @@ Generic collection of tests for suggestions, when no more specific directories a
13511351

13521352
**FIXME**: Some overlap with `tests/ui/did_you_mean/`, that directory should probably be moved under here.
13531353

1354+
## `tests/ui/supertrait-shadowing/`
1355+
1356+
Tests for supertrait item shadowing (RFC 3624).
1357+
13541358
## `tests/ui/svh/`: Strict Version Hash
13551359

13561360
Tests on the *Strict Version Hash* (SVH, also known as the "crate hash").

tests/ui/methods/supertrait-shadowing/assoc-const.rs

Lines changed: 0 additions & 22 deletions
This file was deleted.

tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs

Lines changed: 0 additions & 33 deletions
This file was deleted.

tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs

Lines changed: 0 additions & 43 deletions
This file was deleted.

tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr

Lines changed: 0 additions & 68 deletions
This file was deleted.

tests/ui/methods/supertrait-shadowing/common-ancestor.rs

Lines changed: 0 additions & 26 deletions
This file was deleted.

tests/ui/methods/supertrait-shadowing/definition-site.rs

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)