Skip to content

Commit 987a165

Browse files
Auto merge of #145262 - compiler-errors:prefer-only-param, r=<try>
Make sure to treat only param where clauses as inherent
2 parents fce0e74 + 04329e3 commit 987a165

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,29 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
19451945
);
19461946
(xform_self_ty, xform_ret_ty) =
19471947
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
1948+
1949+
if matches!(probe.kind, WhereClauseCandidate(_)) {
1950+
// `WhereClauseCandidate` requires that the self type is a param,
1951+
// because it has special behavior with candidate preference as an
1952+
// inherent pick.
1953+
match ocx.structurally_normalize_ty(
1954+
cause,
1955+
self.param_env,
1956+
trait_ref.self_ty(),
1957+
) {
1958+
Ok(ty) => {
1959+
if !matches!(ty.kind(), ty::Param(_)) {
1960+
debug!("--> not a param ty: {xform_self_ty:?}");
1961+
return ProbeResult::NoMatch;
1962+
}
1963+
}
1964+
Err(errors) => {
1965+
debug!("--> cannot relate self-types {:?}", errors);
1966+
return ProbeResult::NoMatch;
1967+
}
1968+
}
1969+
}
1970+
19481971
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
19491972
match ocx.relate(cause, self.param_env, self.variance(), self_ty, xform_self_ty)
19501973
{
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// See the code below.
2+
//
3+
// We were using `DeepRejectCtxt` to ensure that `assemble_inherent_candidates_from_param`
4+
// did not rely on the param-env being eagerly normalized. Since aliases unify with all
5+
// types, this meant that a rigid param-env candidate like `<T as Deref>::Target: Trait1`
6+
// would be registered as a "WhereClauseCandidate", which is treated as inherent. Since
7+
// we evaluate these candidates for all self types in the deref chain, this candidate
8+
// would be satisfied for `<T as Deref>::Target`, meaning that it would be preferred over
9+
// an "extension" candidate like `<T as Deref>::Target: Trait2` even though it holds.
10+
// This is problematic, since it causes ambiguities to be broken somewhat arbitrarily.
11+
// And as a side-effect, it also caused our computation of "used" traits to be miscalculated
12+
// since inherent candidates don't count as an import usage.
13+
14+
use std::ops::Deref;
15+
16+
trait Trait1 {
17+
fn method(&self) {
18+
println!("1");
19+
}
20+
}
21+
22+
trait Trait2 {
23+
fn method(&self) {
24+
println!("2");
25+
}
26+
}
27+
impl<T: Other + ?Sized> Trait2 for T {}
28+
29+
trait Other {}
30+
31+
fn foo<T>(x: T)
32+
where
33+
T: Deref,
34+
<T as Deref>::Target: Trait1 + Other,
35+
{
36+
// Make sure that we don't prefer methods from where clauses for rigid aliases,
37+
// just for params. We could revisit this behavior, but it would be a lang change.
38+
x.method();
39+
//~^ ERROR multiple applicable items in scope
40+
}
41+
42+
fn main() {}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0034]: multiple applicable items in scope
2+
--> $DIR/rigid-alias-bound-is-not-inherent.rs:38:7
3+
|
4+
LL | x.method();
5+
| ^^^^^^ multiple `method` found
6+
|
7+
note: candidate #1 is defined in the trait `Trait1`
8+
--> $DIR/rigid-alias-bound-is-not-inherent.rs:17:5
9+
|
10+
LL | fn method(&self) {
11+
| ^^^^^^^^^^^^^^^^
12+
note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T`
13+
--> $DIR/rigid-alias-bound-is-not-inherent.rs:23:5
14+
|
15+
LL | fn method(&self) {
16+
| ^^^^^^^^^^^^^^^^
17+
help: disambiguate the method for candidate #1
18+
|
19+
LL - x.method();
20+
LL + Trait1::method(&x);
21+
|
22+
help: disambiguate the method for candidate #2
23+
|
24+
LL - x.method();
25+
LL + Trait2::method(&x);
26+
|
27+
28+
error: aborting due to 1 previous error
29+
30+
For more information about this error, try `rustc --explain E0034`.

0 commit comments

Comments
 (0)