Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check all supertrait bounds when confirming dyn candidate #92285

Merged
merged 2 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,21 +468,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.predicates
.into_iter()
{
if let ty::PredicateKind::Trait(..) = 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
Expand Down
24 changes: 24 additions & 0 deletions src/test/ui/traits/object/enforce-supertrait-projection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
trait SuperTrait {
type A;
type B;
}

trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}

fn transmute<A, B>(x: A) -> B {
foo::<A, B, dyn Trait<A = A, B = B>>(x)
//~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
}

fn foo<A, B, T: ?Sized>(x: T::A) -> B
where
T: Trait<B = B>,
{
x
}

static X: u8 = 0;
fn main() {
let x = transmute::<&u8, &[u8; 1_000_000]>(&X);
println!("{:?}", x[100_000]);
}
26 changes: 26 additions & 0 deletions src/test/ui/traits/object/enforce-supertrait-projection.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
--> $DIR/enforce-supertrait-projection.rs:9:5
|
LL | fn transmute<A, B>(x: A) -> B {
| - - expected type parameter
| |
| found type parameter
LL | foo::<A, B, dyn Trait<A = A, B = B>>(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<A, B, T: ?Sized>(x: T::A) -> B
| --- required by a bound in this
LL | where
LL | T: Trait<B = B>,
| ^^^^^^^^^^^^ required by this bound in `foo`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0271`.
11 changes: 11 additions & 0 deletions src/test/ui/traits/object/supertrait-lifetime-bound.nll.stderr
Original file line number Diff line number Diff line change
@@ -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::<dyn Bar<&'a u32>, _>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`

error: aborting due to previous error

20 changes: 9 additions & 11 deletions src/test/ui/traits/object/supertrait-lifetime-bound.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
// check-pass
trait Foo: 'static { }

use std::any::Any;
trait Bar<T>: Foo { }

trait A<T>: Any {
fn m(&self) {}
}

impl<S, T: 'static> A<S> for T {}
fn test1<T: ?Sized + Bar<S>, 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::<dyn Bar<&'a u32>, _>();
//~^ ERROR the type `(dyn Bar<&'a u32> + 'static)` does not fulfill the required lifetime
}

fn main() {}
fn main() { }
15 changes: 15 additions & 0 deletions src/test/ui/traits/object/supertrait-lifetime-bound.stderr
Original file line number Diff line number Diff line change
@@ -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::<dyn Bar<&'a u32>, _>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: type must satisfy the static lifetime as required by this binding
--> $DIR/supertrait-lifetime-bound.rs:5:22
|
LL | fn test1<T: ?Sized + Bar<S>, S>() { }
| ^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0477`.