diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index d4502be6ccfee..3fceada251049 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -24,7 +24,9 @@ use super::elaborate; use crate::infer::TyCtxtInferExt; pub use crate::traits::DynCompatibilityViolation; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{MethodViolationCode, Obligation, ObligationCause, util}; +use crate::traits::{ + MethodViolationCode, Obligation, ObligationCause, normalize_param_env_or_error, util, +}; /// Returns the dyn-compatibility violations that affect HIR ty lowering. /// @@ -579,8 +581,8 @@ fn receiver_is_dispatchable<'tcx>( let unsized_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id); - // create a modified param env, with `Self: Unsize` and `U: Trait` added to caller bounds - // `U: ?Sized` is already implied here + // create a modified param env, with `Self: Unsize` and `U: Trait` (and all of + // its supertraits) added to caller bounds. `U: ?Sized` is already implied here. let param_env = { let param_env = tcx.param_env(method.def_id); @@ -598,10 +600,13 @@ fn receiver_is_dispatchable<'tcx>( ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx) }; - let caller_bounds = - param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]); - - ty::ParamEnv::new(tcx.mk_clauses_from_iter(caller_bounds)) + normalize_param_env_or_error( + tcx, + ty::ParamEnv::new(tcx.mk_clauses_from_iter( + param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]), + )), + ObligationCause::dummy_with_span(tcx.def_span(method.def_id)), + ) }; // Receiver: DispatchFromDyn U]> diff --git a/tests/ui/associated-types/issue-59324.rs b/tests/ui/associated-types/issue-59324.rs index 7421e08c89888..3abe84730526d 100644 --- a/tests/ui/associated-types/issue-59324.rs +++ b/tests/ui/associated-types/issue-59324.rs @@ -15,6 +15,7 @@ pub trait ThriftService: { fn get_service( //~^ ERROR the trait bound `Bug: Foo` is not satisfied + //~| ERROR the trait bound `Bug: Foo` is not satisfied &self, ) -> Self::AssocType; //~^ ERROR the trait bound `Bug: Foo` is not satisfied diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index dc8f9cfe895b5..f5e696b7ac1ce 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -32,6 +32,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied | LL | / fn get_service( LL | | +LL | | LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` @@ -41,8 +42,18 @@ help: consider further restricting type parameter `Bug` with trait `Foo` LL | pub trait ThriftService: | +++++ +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` + error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:23:29 + --> $DIR/issue-59324.rs:24:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` @@ -54,7 +65,7 @@ LL | pub trait Foo: NotFoo { | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:19:10 + --> $DIR/issue-59324.rs:20:10 | LL | ) -> Self::AssocType; | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` @@ -65,7 +76,7 @@ LL | pub trait ThriftService: | +++++ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:23:29 + --> $DIR/issue-59324.rs:24:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` @@ -78,7 +89,7 @@ LL | pub trait Foo: NotFoo { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time - --> $DIR/issue-59324.rs:23:29 + --> $DIR/issue-59324.rs:24:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -95,6 +106,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn with_factory(factory: &dyn ThriftService<()>) {} | + -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs new file mode 100644 index 0000000000000..55c070eb03682 --- /dev/null +++ b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs @@ -0,0 +1,38 @@ +//@ check-pass + +#![feature(derive_coerce_pointee)] +#![feature(arbitrary_self_types)] + +use std::ops::Deref; +use std::marker::CoercePointee; +use std::sync::Arc; + +trait MyTrait {} + +#[derive(CoercePointee)] +#[repr(transparent)] +struct MyArc>(Arc); + +impl> Deref for MyArc { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +// This is variant on "tests/ui/self/dyn-dispatch-requires-supertrait.rs" but with +// a supertrait that requires normalization to match the pred in the old solver. +trait MyOtherTrait: MyTrait<::Assoc> { + fn foo(self: MyArc); +} + +fn test(_: MyArc) {} + +fn main() {} diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait.rs b/tests/ui/self/dyn-dispatch-requires-supertrait.rs new file mode 100644 index 0000000000000..f2661c406fef0 --- /dev/null +++ b/tests/ui/self/dyn-dispatch-requires-supertrait.rs @@ -0,0 +1,38 @@ +//@ check-pass + +#![feature(derive_coerce_pointee)] +#![feature(arbitrary_self_types)] + +use std::ops::Deref; +use std::marker::CoercePointee; +use std::sync::Arc; + +trait MyTrait {} + +#[derive(CoercePointee)] +#[repr(transparent)] +struct MyArc +where + T: MyTrait + ?Sized, +{ + inner: Arc +} + +impl Deref for MyArc { + type Target = T; + fn deref(&self) -> &T { + &self.inner + } +} + +// Proving that `MyArc` is dyn-dispatchable requires proving `MyArc` implements +// `DispatchFromDyn>`. The `DispatchFromDyn` impl that is generated from the +// `CoercePointee` implementation requires the pointee impls `MyTrait`, but previously we +// were only assuming the pointee impl'd `MyOtherTrait`. Elaboration comes to the rescue here. +trait MyOtherTrait: MyTrait { + fn foo(self: MyArc); +} + +fn test(_: MyArc) {} + +fn main() {}