Skip to content

Commit 1c256fb

Browse files
authored
Unrolled build for rust-lang#138941
Rollup merge of rust-lang#138941 - compiler-errors:receiver-is-dispatchable-bounds, r=BoxyUwU Do not mix normalized and unnormalized caller bounds when constructing param-env for `receiver_is_dispatchable` See comments in code and in test I added. r? `@BoxyUwU` since you reviewed the last PR, or reassign Fixes rust-lang#138937
2 parents 70dab5a + 4f2baaa commit 1c256fb

File tree

3 files changed

+61
-26
lines changed

3 files changed

+61
-26
lines changed

compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -583,27 +583,36 @@ fn receiver_is_dispatchable<'tcx>(
583583
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
584584
// its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
585585
let param_env = {
586-
let param_env = tcx.param_env(method.def_id);
586+
// N.B. We generally want to emulate the construction of the `unnormalized_param_env`
587+
// in the param-env query here. The fact that we don't just start with the clauses
588+
// in the param-env of the method is because those are already normalized, and mixing
589+
// normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
590+
// will cause ambiguity that the user can't really avoid.
591+
//
592+
// We leave out certain complexities of the param-env query here. Specifically, we:
593+
// 1. Do not add `~const` bounds since there are no `dyn const Trait`s.
594+
// 2. Do not add RPITIT self projection bounds for defaulted methods, since we
595+
// are not constructing a param-env for "inside" of the body of the defaulted
596+
// method, so we don't really care about projecting to a specific RPIT type,
597+
// and because RPITITs are not dyn compatible (yet).
598+
let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;
587599

588600
// Self: Unsize<U>
589601
let unsize_predicate =
590-
ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx);
602+
ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
603+
predicates.push(unsize_predicate.upcast(tcx));
591604

592605
// U: Trait<Arg1, ..., ArgN>
593-
let trait_predicate = {
594-
let trait_def_id = method.trait_container(tcx).unwrap();
595-
let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
596-
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
597-
});
598-
599-
ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
600-
};
606+
let trait_def_id = method.trait_container(tcx).unwrap();
607+
let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
608+
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
609+
});
610+
let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
611+
predicates.push(trait_predicate.upcast(tcx));
601612

602613
normalize_param_env_or_error(
603614
tcx,
604-
ty::ParamEnv::new(tcx.mk_clauses_from_iter(
605-
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
606-
)),
615+
ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
607616
ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
608617
)
609618
};

tests/ui/associated-types/issue-59324.stderr

+13-13
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,18 @@ LL | |
3636
LL | | &self,
3737
LL | | ) -> Self::AssocType;
3838
| |_________________________^ the trait `Foo` is not implemented for `Bug`
39+
40+
error[E0277]: the trait bound `(): Foo` is not satisfied
41+
--> $DIR/issue-59324.rs:24:29
3942
|
40-
help: consider further restricting type parameter `Bug` with trait `Foo`
43+
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
44+
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
4145
|
42-
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
43-
| +++++
46+
help: this trait has no implementations, consider adding one
47+
--> $DIR/issue-59324.rs:3:1
48+
|
49+
LL | pub trait Foo: NotFoo {
50+
| ^^^^^^^^^^^^^^^^^^^^^
4451

4552
error[E0277]: the trait bound `Bug: Foo` is not satisfied
4653
--> $DIR/issue-59324.rs:16:5
@@ -51,18 +58,11 @@ LL | |
5158
LL | | &self,
5259
LL | | ) -> Self::AssocType;
5360
| |_________________________^ the trait `Foo` is not implemented for `Bug`
54-
55-
error[E0277]: the trait bound `(): Foo` is not satisfied
56-
--> $DIR/issue-59324.rs:24:29
5761
|
58-
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
59-
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
60-
|
61-
help: this trait has no implementations, consider adding one
62-
--> $DIR/issue-59324.rs:3:1
62+
help: consider further restricting type parameter `Bug` with trait `Foo`
6363
|
64-
LL | pub trait Foo: NotFoo {
65-
| ^^^^^^^^^^^^^^^^^^^^^
64+
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
65+
| +++++
6666

6767
error[E0277]: the trait bound `Bug: Foo` is not satisfied
6868
--> $DIR/issue-59324.rs:20:10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//@ check-pass
2+
3+
// Regression test for <https://github.com/rust-lang/rust/issues/138937>.
4+
5+
// Previously, we'd take the normalized param env's clauses which included
6+
// `<PF as TraitC>::Value = i32`, which comes from the supertraits of `TraitD`
7+
// after normalizing `<PF as TraitC>::Value = <PF as TraitD>::Scalar`. Since
8+
// `normalize_param_env_or_error` ends up re-elaborating `PF: TraitD`, we'd
9+
// end up with both versions of this predicate (normalized and unnormalized).
10+
// Since these projections preds are not equal, we'd fail with ambiguity.
11+
12+
trait TraitB<T> {}
13+
14+
trait TraitC: TraitB<Self::Value> {
15+
type Value;
16+
}
17+
18+
trait TraitD: TraitC<Value = Self::Scalar> {
19+
type Scalar;
20+
}
21+
22+
trait TraitE {
23+
fn apply<PF: TraitD<Scalar = i32>>(&self);
24+
}
25+
26+
fn main() {}

0 commit comments

Comments
 (0)