Skip to content

Commit 1051286

Browse files
Implement RFC 3624 supertrait_item_shadowing
1 parent 0321e73 commit 1051286

File tree

5 files changed

+137
-4
lines changed

5 files changed

+137
-4
lines changed

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ declare_features! (
601601
(unstable, strict_provenance, "1.61.0", Some(95228)),
602602
/// Allows string patterns to dereference values to match them.
603603
(unstable, string_deref_patterns, "1.67.0", Some(87121)),
604+
/// Allows subtrait items to shadow supertrait items.
605+
(unstable, supertrait_item_shadowing, "CURRENT_RUSTC_VERSION", Some(89151)),
604606
/// Allows the use of `#[target_feature]` on safe functions.
605607
(unstable, target_feature_11, "1.45.0", Some(69098)),
606608
/// Allows using `#[thread_local]` on `static` items.

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::iter;
44
use std::ops::Deref;
55

66
use rustc_data_structures::fx::FxHashSet;
7+
use rustc_data_structures::sso::SsoHashSet;
78
use rustc_errors::Applicability;
89
use rustc_hir as hir;
910
use rustc_hir::HirId;
@@ -35,6 +36,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
3536
CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult,
3637
};
3738
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
39+
use rustc_type_ir::elaborate::supertrait_def_ids;
3840
use smallvec::{SmallVec, smallvec};
3941
use tracing::{debug, instrument};
4042

@@ -1317,10 +1319,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13171319
debug!("applicable_candidates: {:?}", applicable_candidates);
13181320

13191321
if applicable_candidates.len() > 1 {
1320-
if let Some(pick) =
1321-
self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates)
1322-
{
1323-
return Some(Ok(pick));
1322+
if self.tcx.features().supertrait_item_shadowing {
1323+
if let Some(pick) =
1324+
self.collapse_candidates_to_subtrait_pick(self_ty, &applicable_candidates)
1325+
{
1326+
return Some(Ok(pick));
1327+
}
1328+
} else {
1329+
if let Some(pick) =
1330+
self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates)
1331+
{
1332+
return Some(Ok(pick));
1333+
}
13241334
}
13251335
}
13261336

@@ -1754,6 +1764,51 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
17541764
})
17551765
}
17561766

1767+
/// Much like `collapse_candidates_to_trait_pick`, this method allows us to collapse
1768+
/// multiple conflicting picks if there is one pick whose trait container is a subtrait
1769+
/// of the trait containers of all of the other picks.
1770+
///
1771+
/// This implements RFC #3624.
1772+
fn collapse_candidates_to_subtrait_pick(
1773+
&self,
1774+
self_ty: Ty<'tcx>,
1775+
probes: &[(&Candidate<'tcx>, ProbeResult)],
1776+
) -> Option<Pick<'tcx>> {
1777+
let mut child_pick = probes[0].0;
1778+
let mut supertraits: SsoHashSet<_> =
1779+
supertrait_def_ids(self.tcx, child_pick.item.trait_container(self.tcx)?).collect();
1780+
1781+
// All other picks should be a supertrait of the `child_pick`.
1782+
// If it's not, then we update the `child_pick` and the `supertraits`
1783+
// list.
1784+
for (p, _) in &probes[1..] {
1785+
let p_container = p.item.trait_container(self.tcx)?;
1786+
if !supertraits.contains(&p_container) {
1787+
// This pick is not a supertrait of the `child_pick`.
1788+
// Check if it's a subtrait of the `child_pick`, which
1789+
// is sufficient to imply that all of the previous picks
1790+
// are also supertraits of this pick.
1791+
supertraits = supertrait_def_ids(self.tcx, p_container).collect();
1792+
if supertraits.contains(&child_pick.item.trait_container(self.tcx).unwrap()) {
1793+
child_pick = *p;
1794+
} else {
1795+
// `child_pick` is not a supertrait of this pick. Bail.
1796+
return None;
1797+
}
1798+
}
1799+
}
1800+
1801+
Some(Pick {
1802+
item: child_pick.item,
1803+
kind: TraitPick,
1804+
import_ids: child_pick.import_ids.clone(),
1805+
autoderefs: 0,
1806+
autoref_or_ptr_adjustment: None,
1807+
self_ty,
1808+
unstable_candidates: vec![],
1809+
})
1810+
}
1811+
17571812
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
17581813
/// candidate method where the method name may have been misspelled. Similarly to other
17591814
/// edit distance based suggestions, we provide at most one such suggestion.

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,7 @@ symbols! {
19221922
sub_assign,
19231923
sub_with_overflow,
19241924
suggestion,
1925+
supertrait_item_shadowing,
19251926
surface_async_drop_in_place,
19261927
sym,
19271928
sync,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
trait Sup {
2+
fn method(&self) {}
3+
}
4+
5+
trait Trait: Sup {
6+
fn method(&self) {}
7+
}
8+
9+
impl Sup for i32 {}
10+
impl Trait for i32 {}
11+
12+
fn poly<T: Trait>(x: T) {
13+
x.method();
14+
//~^ ERROR multiple applicable items in scope
15+
}
16+
17+
fn concrete() {
18+
1.method();
19+
//~^ ERROR multiple applicable items in scope
20+
}
21+
22+
fn main() {}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
error[E0034]: multiple applicable items in scope
2+
--> $DIR/feature-gate-supertrait-item-shadowing.rs:13:7
3+
|
4+
LL | x.method();
5+
| ^^^^^^ multiple `method` found
6+
|
7+
note: candidate #1 is defined in the trait `Sup`
8+
--> $DIR/feature-gate-supertrait-item-shadowing.rs:2:5
9+
|
10+
LL | fn method(&self) {}
11+
| ^^^^^^^^^^^^^^^^
12+
note: candidate #2 is defined in the trait `Trait`
13+
--> $DIR/feature-gate-supertrait-item-shadowing.rs:6:5
14+
|
15+
LL | fn method(&self) {}
16+
| ^^^^^^^^^^^^^^^^
17+
help: disambiguate the method for candidate #1
18+
|
19+
LL | Sup::method(&x);
20+
| ~~~~~~~~~~~~~~~
21+
help: disambiguate the method for candidate #2
22+
|
23+
LL | Trait::method(&x);
24+
| ~~~~~~~~~~~~~~~~~
25+
26+
error[E0034]: multiple applicable items in scope
27+
--> $DIR/feature-gate-supertrait-item-shadowing.rs:18:7
28+
|
29+
LL | 1.method();
30+
| ^^^^^^ multiple `method` found
31+
|
32+
note: candidate #1 is defined in an impl of the trait `Sup` for the type `i32`
33+
--> $DIR/feature-gate-supertrait-item-shadowing.rs:2:5
34+
|
35+
LL | fn method(&self) {}
36+
| ^^^^^^^^^^^^^^^^
37+
note: candidate #2 is defined in an impl of the trait `Trait` for the type `i32`
38+
--> $DIR/feature-gate-supertrait-item-shadowing.rs:6:5
39+
|
40+
LL | fn method(&self) {}
41+
| ^^^^^^^^^^^^^^^^
42+
help: disambiguate the method for candidate #1
43+
|
44+
LL | Sup::method(&1);
45+
| ~~~~~~~~~~~~~~~
46+
help: disambiguate the method for candidate #2
47+
|
48+
LL | Trait::method(&1);
49+
| ~~~~~~~~~~~~~~~~~
50+
51+
error: aborting due to 2 previous errors
52+
53+
For more information about this error, try `rustc --explain E0034`.

0 commit comments

Comments
 (0)