Rollup merge of #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 #138937
This commit is contained in:
commit
781240939f
3 changed files with 63 additions and 28 deletions
|
@ -583,27 +583,36 @@ fn receiver_is_dispatchable<'tcx>(
|
||||||
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
|
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
|
||||||
// its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
|
// its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
|
||||||
let param_env = {
|
let param_env = {
|
||||||
let param_env = tcx.param_env(method.def_id);
|
// N.B. We generally want to emulate the construction of the `unnormalized_param_env`
|
||||||
|
// in the param-env query here. The fact that we don't just start with the clauses
|
||||||
|
// in the param-env of the method is because those are already normalized, and mixing
|
||||||
|
// normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
|
||||||
|
// will cause ambiguity that the user can't really avoid.
|
||||||
|
//
|
||||||
|
// We leave out certain complexities of the param-env query here. Specifically, we:
|
||||||
|
// 1. Do not add `~const` bounds since there are no `dyn const Trait`s.
|
||||||
|
// 2. Do not add RPITIT self projection bounds for defaulted methods, since we
|
||||||
|
// are not constructing a param-env for "inside" of the body of the defaulted
|
||||||
|
// method, so we don't really care about projecting to a specific RPIT type,
|
||||||
|
// and because RPITITs are not dyn compatible (yet).
|
||||||
|
let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;
|
||||||
|
|
||||||
// Self: Unsize<U>
|
// Self: Unsize<U>
|
||||||
let unsize_predicate =
|
let unsize_predicate =
|
||||||
ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx);
|
ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
|
||||||
|
predicates.push(unsize_predicate.upcast(tcx));
|
||||||
|
|
||||||
// U: Trait<Arg1, ..., ArgN>
|
// U: Trait<Arg1, ..., ArgN>
|
||||||
let trait_predicate = {
|
|
||||||
let trait_def_id = method.trait_container(tcx).unwrap();
|
let trait_def_id = method.trait_container(tcx).unwrap();
|
||||||
let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
|
let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
|
||||||
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
|
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
|
||||||
});
|
});
|
||||||
|
let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
|
||||||
ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
|
predicates.push(trait_predicate.upcast(tcx));
|
||||||
};
|
|
||||||
|
|
||||||
normalize_param_env_or_error(
|
normalize_param_env_or_error(
|
||||||
tcx,
|
tcx,
|
||||||
ty::ParamEnv::new(tcx.mk_clauses_from_iter(
|
ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
|
||||||
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
|
|
||||||
)),
|
|
||||||
ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
|
ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,21 +27,6 @@ help: consider further restricting type parameter `Bug` with trait `Foo`
|
||||||
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
|
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error[E0277]: the trait bound `Bug: Foo` is not satisfied
|
|
||||||
--> $DIR/issue-59324.rs:16:5
|
|
||||||
|
|
|
||||||
LL | / fn get_service(
|
|
||||||
LL | |
|
|
||||||
LL | |
|
|
||||||
LL | | &self,
|
|
||||||
LL | | ) -> Self::AssocType;
|
|
||||||
| |_________________________^ the trait `Foo` is not implemented for `Bug`
|
|
||||||
|
|
|
||||||
help: consider further restricting type parameter `Bug` with trait `Foo`
|
|
||||||
|
|
|
||||||
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
|
|
||||||
| +++++
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `Bug: Foo` is not satisfied
|
error[E0277]: the trait bound `Bug: Foo` is not satisfied
|
||||||
--> $DIR/issue-59324.rs:16:5
|
--> $DIR/issue-59324.rs:16:5
|
||||||
|
|
|
|
||||||
|
@ -64,6 +49,21 @@ help: this trait has no implementations, consider adding one
|
||||||
LL | pub trait Foo: NotFoo {
|
LL | pub trait Foo: NotFoo {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Bug: Foo` is not satisfied
|
||||||
|
--> $DIR/issue-59324.rs:16:5
|
||||||
|
|
|
||||||
|
LL | / fn get_service(
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | &self,
|
||||||
|
LL | | ) -> Self::AssocType;
|
||||||
|
| |_________________________^ the trait `Foo` is not implemented for `Bug`
|
||||||
|
|
|
||||||
|
help: consider further restricting type parameter `Bug` with trait `Foo`
|
||||||
|
|
|
||||||
|
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
|
||||||
|
| +++++
|
||||||
|
|
||||||
error[E0277]: the trait bound `Bug: Foo` is not satisfied
|
error[E0277]: the trait bound `Bug: Foo` is not satisfied
|
||||||
--> $DIR/issue-59324.rs:20:10
|
--> $DIR/issue-59324.rs:20:10
|
||||||
|
|
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/issues/138937>.
|
||||||
|
|
||||||
|
// Previously, we'd take the normalized param env's clauses which included
|
||||||
|
// `<PF as TraitC>::Value = i32`, which comes from the supertraits of `TraitD`
|
||||||
|
// after normalizing `<PF as TraitC>::Value = <PF as TraitD>::Scalar`. Since
|
||||||
|
// `normalize_param_env_or_error` ends up re-elaborating `PF: TraitD`, we'd
|
||||||
|
// end up with both versions of this predicate (normalized and unnormalized).
|
||||||
|
// Since these projections preds are not equal, we'd fail with ambiguity.
|
||||||
|
|
||||||
|
trait TraitB<T> {}
|
||||||
|
|
||||||
|
trait TraitC: TraitB<Self::Value> {
|
||||||
|
type Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait TraitD: TraitC<Value = Self::Scalar> {
|
||||||
|
type Scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait TraitE {
|
||||||
|
fn apply<PF: TraitD<Scalar = i32>>(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue