Auto merge of #145396 - compiler-errors:revert-method-pref, r=lcnr
[BETA] Revert "Use DeepRejectCtxt in assemble_inherent_candidates_from_param" Fixes https://github.com/rust-lang/rust/issues/145185. Backporting this to stable and beta in favor of https://github.com/rust-lang/rust/pull/145262#issuecomment-3188760251. r? lcnr
This commit is contained in:
commit
47b72a3455
7 changed files with 118 additions and 58 deletions
|
|
@ -1,7 +1,6 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use std::assert_matches::debug_assert_matches;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cmp::max;
|
||||
use std::ops::Deref;
|
||||
|
|
@ -16,7 +15,7 @@ use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk,
|
|||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::elaborate::supertrait_def_ids;
|
||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
|
||||
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
|
||||
use rustc_middle::ty::{
|
||||
self, AssocItem, AssocItemContainer, GenericArgs, GenericArgsRef, GenericParamDefKind,
|
||||
ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, Upcast,
|
||||
|
|
@ -803,8 +802,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
ty::Param(_) => {
|
||||
self.assemble_inherent_candidates_from_param(raw_self_ty);
|
||||
ty::Param(p) => {
|
||||
self.assemble_inherent_candidates_from_param(p);
|
||||
}
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
|
|
@ -905,16 +904,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_candidates_from_param(&mut self, param_ty: Ty<'tcx>) {
|
||||
debug_assert_matches!(param_ty.kind(), ty::Param(_));
|
||||
|
||||
let tcx = self.tcx;
|
||||
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
|
||||
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
|
||||
let bound_predicate = predicate.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::ClauseKind::Trait(trait_predicate) => DeepRejectCtxt::relate_rigid_rigid(tcx)
|
||||
.types_may_unify(param_ty, trait_predicate.trait_ref.self_ty())
|
||||
.then(|| bound_predicate.rebind(trait_predicate.trait_ref)),
|
||||
ty::ClauseKind::Trait(trait_predicate) => {
|
||||
match *trait_predicate.trait_ref.self_ty().kind() {
|
||||
ty::Param(p) if p == param_ty => {
|
||||
Some(bound_predicate.rebind(trait_predicate.trait_ref))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
ty::ClauseKind::RegionOutlives(_)
|
||||
| ty::ClauseKind::TypeOutlives(_)
|
||||
| ty::ClauseKind::Projection(_)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/rigid-alias-bound-is-not-inherent.rs:42:7
|
||||
|
|
||||
LL | x.method();
|
||||
| ^^^^^^ multiple `method` found
|
||||
|
|
||||
note: candidate #1 is defined in the trait `Trait1`
|
||||
--> $DIR/rigid-alias-bound-is-not-inherent.rs:21:5
|
||||
|
|
||||
LL | fn method(&self) {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T`
|
||||
--> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
|
||||
|
|
||||
LL | fn method(&self) {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
help: disambiguate the method for candidate #1
|
||||
|
|
||||
LL - x.method();
|
||||
LL + Trait1::method(&x);
|
||||
|
|
||||
help: disambiguate the method for candidate #2
|
||||
|
|
||||
LL - x.method();
|
||||
LL + Trait2::method(&x);
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0034`.
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/rigid-alias-bound-is-not-inherent.rs:42:7
|
||||
|
|
||||
LL | x.method();
|
||||
| ^^^^^^ multiple `method` found
|
||||
|
|
||||
note: candidate #1 is defined in the trait `Trait1`
|
||||
--> $DIR/rigid-alias-bound-is-not-inherent.rs:21:5
|
||||
|
|
||||
LL | fn method(&self) {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in the trait `Trait2`
|
||||
--> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
|
||||
|
|
||||
LL | fn method(&self) {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
help: disambiguate the method for candidate #1
|
||||
|
|
||||
LL - x.method();
|
||||
LL + Trait1::method(&x);
|
||||
|
|
||||
help: disambiguate the method for candidate #2
|
||||
|
|
||||
LL - x.method();
|
||||
LL + Trait2::method(&x);
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0034`.
|
||||
46
tests/ui/methods/rigid-alias-bound-is-not-inherent.rs
Normal file
46
tests/ui/methods/rigid-alias-bound-is-not-inherent.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
// See the code below.
|
||||
//
|
||||
// We were using `DeepRejectCtxt` to ensure that `assemble_inherent_candidates_from_param`
|
||||
// did not rely on the param-env being eagerly normalized. Since aliases unify with all
|
||||
// types, this meant that a rigid param-env candidate like `<T as Deref>::Target: Trait1`
|
||||
// would be registered as a "WhereClauseCandidate", which is treated as inherent. Since
|
||||
// we evaluate these candidates for all self types in the deref chain, this candidate
|
||||
// would be satisfied for `<T as Deref>::Target`, meaning that it would be preferred over
|
||||
// an "extension" candidate like `<T as Deref>::Target: Trait2` even though it holds.
|
||||
// This is problematic, since it causes ambiguities to be broken somewhat arbitrarily.
|
||||
// And as a side-effect, it also caused our computation of "used" traits to be miscalculated
|
||||
// since inherent candidates don't count as an import usage.
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
trait Trait1 {
|
||||
fn method(&self) {
|
||||
println!("1");
|
||||
}
|
||||
}
|
||||
|
||||
trait Trait2 {
|
||||
fn method(&self) {
|
||||
println!("2");
|
||||
}
|
||||
}
|
||||
impl<T: Other + ?Sized> Trait2 for T {}
|
||||
|
||||
trait Other {}
|
||||
|
||||
fn foo<T>(x: T)
|
||||
where
|
||||
T: Deref,
|
||||
<T as Deref>::Target: Trait1 + Other,
|
||||
{
|
||||
// Make sure that we don't prefer methods from where clauses for rigid aliases,
|
||||
// just for params. We could revisit this behavior, but it would be a lang change.
|
||||
x.method();
|
||||
//~^ ERROR multiple applicable items in scope
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/214>.
|
||||
// See comment below.
|
||||
|
||||
trait A {
|
||||
fn hello(&self) {}
|
||||
}
|
||||
|
||||
trait B {
|
||||
fn hello(&self) {}
|
||||
}
|
||||
|
||||
impl<T> A for T {}
|
||||
impl<T> B for T {}
|
||||
|
||||
fn test<F, R>(q: F::Item)
|
||||
where
|
||||
F: Iterator<Item = R>,
|
||||
// We want to prefer `A` for `R.hello()`
|
||||
F::Item: A,
|
||||
{
|
||||
q.hello();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/214>.
|
||||
|
||||
fn execute<K, F, R>(q: F::Item) -> R
|
||||
where
|
||||
F: Iterator<Item = R>,
|
||||
// Both of the below bounds should be considered for `.into()`, and then be combined
|
||||
// into a single `R: Into<?0>` bound which can be inferred to `?0 = R`.
|
||||
F::Item: Into<K>,
|
||||
R: Into<String>,
|
||||
{
|
||||
q.into()
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue