From f14a5fd7127af1e774b76deea5a749ced33b23a1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 25 Dec 2021 22:45:05 -0800 Subject: [PATCH 1/2] check Projection supertrait bounds when confirming dyn candidate --- .../src/traits/select/confirmation.rs | 4 ++- .../object/enforce-supertrait-projection.rs | 24 +++++++++++++++++ .../enforce-supertrait-projection.stderr | 26 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/traits/object/enforce-supertrait-projection.rs create mode 100644 src/test/ui/traits/object/enforce-supertrait-projection.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index c7e0c35436afb..8fd7664d57885 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -468,7 +468,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .predicates .into_iter() { - if let ty::PredicateKind::Trait(..) = super_trait.kind().skip_binder() { + if let ty::PredicateKind::Trait(..) | ty::PredicateKind::Projection(..) = + super_trait.kind().skip_binder() + { let normalized_super_trait = normalize_with_depth_to( self, obligation.param_env, diff --git a/src/test/ui/traits/object/enforce-supertrait-projection.rs b/src/test/ui/traits/object/enforce-supertrait-projection.rs new file mode 100644 index 0000000000000..0ea944ec2df55 --- /dev/null +++ b/src/test/ui/traits/object/enforce-supertrait-projection.rs @@ -0,0 +1,24 @@ +trait SuperTrait { + type A; + type B; +} + +trait Trait: SuperTrait::B> {} + +fn transmute(x: A) -> B { + foo::>(x) + //~^ ERROR type mismatch resolving ` as SuperTrait>::A == B` +} + +fn foo(x: T::A) -> B +where + T: Trait, +{ + x +} + +static X: u8 = 0; +fn main() { + let x = transmute::<&u8, &[u8; 1_000_000]>(&X); + println!("{:?}", x[100_000]); +} diff --git a/src/test/ui/traits/object/enforce-supertrait-projection.stderr b/src/test/ui/traits/object/enforce-supertrait-projection.stderr new file mode 100644 index 0000000000000..a3d17fabbe47f --- /dev/null +++ b/src/test/ui/traits/object/enforce-supertrait-projection.stderr @@ -0,0 +1,26 @@ +error[E0271]: type mismatch resolving ` as SuperTrait>::A == B` + --> $DIR/enforce-supertrait-projection.rs:9:5 + | +LL | fn transmute(x: A) -> B { + | - - expected type parameter + | | + | found type parameter +LL | foo::>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` + | + = note: expected type parameter `B` + found type parameter `A` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +note: required by a bound in `foo` + --> $DIR/enforce-supertrait-projection.rs:15:8 + | +LL | fn foo(x: T::A) -> B + | --- required by a bound in this +LL | where +LL | T: Trait, + | ^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. From 67ef11dc2a64153a381c7b58475a2b65214557af Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 31 Jan 2022 19:11:23 -0800 Subject: [PATCH 2/2] check all dyn obligations, actually --- .../src/traits/select/confirmation.rs | 30 ++++++++----------- .../supertrait-lifetime-bound.nll.stderr | 11 +++++++ .../object/supertrait-lifetime-bound.rs | 20 ++++++------- .../object/supertrait-lifetime-bound.stderr | 15 ++++++++++ 4 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/traits/object/supertrait-lifetime-bound.nll.stderr create mode 100644 src/test/ui/traits/object/supertrait-lifetime-bound.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 8fd7664d57885..c3f3baf9d3d47 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -468,23 +468,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .predicates .into_iter() { - if let ty::PredicateKind::Trait(..) | ty::PredicateKind::Projection(..) = - super_trait.kind().skip_binder() - { - let normalized_super_trait = normalize_with_depth_to( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - super_trait, - &mut nested, - ); - nested.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env, - normalized_super_trait, - )); - } + let normalized_super_trait = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + super_trait, + &mut nested, + ); + nested.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env, + normalized_super_trait, + )); } let assoc_types: Vec<_> = tcx diff --git a/src/test/ui/traits/object/supertrait-lifetime-bound.nll.stderr b/src/test/ui/traits/object/supertrait-lifetime-bound.nll.stderr new file mode 100644 index 0000000000000..ed2f8624357bb --- /dev/null +++ b/src/test/ui/traits/object/supertrait-lifetime-bound.nll.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/supertrait-lifetime-bound.rs:10:5 + | +LL | fn test2<'a>() { + | -- lifetime `'a` defined here +... +LL | test1::, _>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/traits/object/supertrait-lifetime-bound.rs b/src/test/ui/traits/object/supertrait-lifetime-bound.rs index 9d834727a4a1b..5349771693a2a 100644 --- a/src/test/ui/traits/object/supertrait-lifetime-bound.rs +++ b/src/test/ui/traits/object/supertrait-lifetime-bound.rs @@ -1,16 +1,14 @@ -// check-pass +trait Foo: 'static { } -use std::any::Any; +trait Bar: Foo { } -trait A: Any { - fn m(&self) {} -} - -impl A for T {} +fn test1, S>() { } -fn call_obj<'a>() { - let obj: &dyn A<&'a ()> = &(); - obj.m(); +fn test2<'a>() { + // Here: the type `dyn Bar<&'a u32>` references `'a`, + // and so it does not outlive `'static`. + test1::, _>(); + //~^ ERROR the type `(dyn Bar<&'a u32> + 'static)` does not fulfill the required lifetime } -fn main() {} +fn main() { } diff --git a/src/test/ui/traits/object/supertrait-lifetime-bound.stderr b/src/test/ui/traits/object/supertrait-lifetime-bound.stderr new file mode 100644 index 0000000000000..c3d7f8cd0c1cd --- /dev/null +++ b/src/test/ui/traits/object/supertrait-lifetime-bound.stderr @@ -0,0 +1,15 @@ +error[E0477]: the type `(dyn Bar<&'a u32> + 'static)` does not fulfill the required lifetime + --> $DIR/supertrait-lifetime-bound.rs:10:5 + | +LL | test1::, _>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/supertrait-lifetime-bound.rs:5:22 + | +LL | fn test1, S>() { } + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`.