Implement RFC 3624 supertrait_item_shadowing
This commit is contained in:
parent
9fcc9cf4a2
commit
0c85044a5d
5 changed files with 142 additions and 4 deletions
|
|
@ -633,6 +633,8 @@ declare_features! (
|
|||
(unstable, strict_provenance_lints, "1.61.0", Some(130351)),
|
||||
/// Allows string patterns to dereference values to match them.
|
||||
(unstable, string_deref_patterns, "1.67.0", Some(87121)),
|
||||
/// Allows subtrait items to shadow supertrait items.
|
||||
(unstable, supertrait_item_shadowing, "CURRENT_RUSTC_VERSION", Some(89151)),
|
||||
/// Allows using `#[thread_local]` on `static` items.
|
||||
(unstable, thread_local, "1.0.0", Some(29594)),
|
||||
/// Allows defining `trait X = A + B;` alias items.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::cmp::max;
|
|||
use std::ops::Deref;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::HirId;
|
||||
|
|
@ -33,6 +34,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
|
|||
CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult,
|
||||
};
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
|
||||
use rustc_type_ir::elaborate::supertrait_def_ids;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
|
|
@ -1614,10 +1616,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
debug!("applicable_candidates: {:?}", applicable_candidates);
|
||||
|
||||
if applicable_candidates.len() > 1 {
|
||||
if let Some(pick) =
|
||||
self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates)
|
||||
{
|
||||
return Some(Ok(pick));
|
||||
if self.tcx.features().supertrait_item_shadowing() {
|
||||
if let Some(pick) =
|
||||
self.collapse_candidates_to_subtrait_pick(self_ty, &applicable_candidates)
|
||||
{
|
||||
return Some(Ok(pick));
|
||||
}
|
||||
} else {
|
||||
if let Some(pick) =
|
||||
self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates)
|
||||
{
|
||||
return Some(Ok(pick));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2084,6 +2094,52 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Much like `collapse_candidates_to_trait_pick`, this method allows us to collapse
|
||||
/// multiple conflicting picks if there is one pick whose trait container is a subtrait
|
||||
/// of the trait containers of all of the other picks.
|
||||
///
|
||||
/// This implements RFC #3624.
|
||||
fn collapse_candidates_to_subtrait_pick(
|
||||
&self,
|
||||
self_ty: Ty<'tcx>,
|
||||
probes: &[(&Candidate<'tcx>, ProbeResult)],
|
||||
) -> Option<Pick<'tcx>> {
|
||||
let mut child_pick = probes[0].0;
|
||||
let mut supertraits: SsoHashSet<_> =
|
||||
supertrait_def_ids(self.tcx, child_pick.item.trait_container(self.tcx)?).collect();
|
||||
|
||||
// All other picks should be a supertrait of the `child_pick`.
|
||||
// If it's not, then we update the `child_pick` and the `supertraits`
|
||||
// list.
|
||||
for (p, _) in &probes[1..] {
|
||||
let p_container = p.item.trait_container(self.tcx)?;
|
||||
if !supertraits.contains(&p_container) {
|
||||
// This pick is not a supertrait of the `child_pick`.
|
||||
// Check if it's a subtrait of the `child_pick`, which
|
||||
// is sufficient to imply that all of the previous picks
|
||||
// are also supertraits of this pick.
|
||||
supertraits = supertrait_def_ids(self.tcx, p_container).collect();
|
||||
if supertraits.contains(&child_pick.item.trait_container(self.tcx).unwrap()) {
|
||||
child_pick = *p;
|
||||
} else {
|
||||
// `child_pick` is not a supertrait of this pick. Bail.
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(Pick {
|
||||
item: child_pick.item,
|
||||
kind: TraitPick,
|
||||
import_ids: child_pick.import_ids.clone(),
|
||||
autoderefs: 0,
|
||||
autoref_or_ptr_adjustment: None,
|
||||
self_ty,
|
||||
unstable_candidates: vec![],
|
||||
receiver_steps: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
|
||||
/// candidate method where the method name may have been misspelled. Similarly to other
|
||||
/// edit distance based suggestions, we provide at most one such suggestion.
|
||||
|
|
|
|||
|
|
@ -1995,6 +1995,7 @@ symbols! {
|
|||
sub_assign,
|
||||
sub_with_overflow,
|
||||
suggestion,
|
||||
supertrait_item_shadowing,
|
||||
surface_async_drop_in_place,
|
||||
sym,
|
||||
sync,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
trait Sup {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
trait Trait: Sup {
|
||||
fn method(&self) {}
|
||||
}
|
||||
|
||||
impl Sup for i32 {}
|
||||
impl Trait for i32 {}
|
||||
|
||||
fn poly<T: Trait>(x: T) {
|
||||
x.method();
|
||||
//~^ ERROR multiple applicable items in scope
|
||||
}
|
||||
|
||||
fn concrete() {
|
||||
1.method();
|
||||
//~^ ERROR multiple applicable items in scope
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/feature-gate-supertrait-item-shadowing.rs:13:7
|
||||
|
|
||||
LL | x.method();
|
||||
| ^^^^^^ multiple `method` found
|
||||
|
|
||||
note: candidate #1 is defined in the trait `Sup`
|
||||
--> $DIR/feature-gate-supertrait-item-shadowing.rs:2:5
|
||||
|
|
||||
LL | fn method(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in the trait `Trait`
|
||||
--> $DIR/feature-gate-supertrait-item-shadowing.rs:6:5
|
||||
|
|
||||
LL | fn method(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
help: disambiguate the method for candidate #1
|
||||
|
|
||||
LL - x.method();
|
||||
LL + Sup::method(&x);
|
||||
|
|
||||
help: disambiguate the method for candidate #2
|
||||
|
|
||||
LL - x.method();
|
||||
LL + Trait::method(&x);
|
||||
|
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/feature-gate-supertrait-item-shadowing.rs:18:7
|
||||
|
|
||||
LL | 1.method();
|
||||
| ^^^^^^ multiple `method` found
|
||||
|
|
||||
note: candidate #1 is defined in an impl of the trait `Sup` for the type `i32`
|
||||
--> $DIR/feature-gate-supertrait-item-shadowing.rs:2:5
|
||||
|
|
||||
LL | fn method(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in an impl of the trait `Trait` for the type `i32`
|
||||
--> $DIR/feature-gate-supertrait-item-shadowing.rs:6:5
|
||||
|
|
||||
LL | fn method(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
help: disambiguate the method for candidate #1
|
||||
|
|
||||
LL - 1.method();
|
||||
LL + Sup::method(&1);
|
||||
|
|
||||
help: disambiguate the method for candidate #2
|
||||
|
|
||||
LL - 1.method();
|
||||
LL + Trait::method(&1);
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0034`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue