Skip to content

Commit

Permalink
Added tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Regueiro committed May 5, 2020
1 parent 29de923 commit 9549fbd
Show file tree
Hide file tree
Showing 22 changed files with 792 additions and 9 deletions.
4 changes: 3 additions & 1 deletion src/librustc_infer/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let trait_ref = Binder::bind(TraitRef::identity(self.tcx, exp_found.found));
let supertraits = crate::traits::util::supertraits(self.tcx, trait_ref);
if supertraits.into_iter().any(|trait_ref| trait_ref.def_id() == exp_found.expected) {
diag.note("add `#![feature(trait_upcasting)]` to the crate attributes to enable");
diag.note(
"add `#![feature(trait_upcasting)]` to the crate attributes to enable \
trait upcasting");
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/test/ui/feature-gates/feature-gate-trait_upcasting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ fn main() {
let bar: &dyn Bar = &();
let foo: &dyn Foo = bar;
//~^ ERROR mismatched types [E0308]
//~| NOTE expected type `&dyn Foo`
//~| NOTE expected trait `Foo`, found trait `Bar`
//~| NOTE add `#![feature(trait_upcasting)]` to the crate attributes to enable
//~| NOTE expected due to this
//~| NOTE expected reference `&dyn Foo`
//~| NOTE add `#![feature(trait_upcasting)]` to the crate attributes to enable trait upcasting
}
10 changes: 6 additions & 4 deletions src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ error[E0308]: mismatched types
--> $DIR/feature-gate-trait_upcasting.rs:11:25
|
LL | let foo: &dyn Foo = bar;
| ^^^ expected trait `Foo`, found trait `Bar`
| -------- ^^^ expected trait `Foo`, found trait `Bar`
| |
| expected due to this
|
= note: add `#![feature(trait_upcasting)]` to the crate attributes to enable
= note: expected type `&dyn Foo`
found type `&dyn Bar`
= note: expected reference `&dyn Foo`
found reference `&dyn Bar`
= note: add `#![feature(trait_upcasting)]` to the crate attributes to enable trait upcasting

error: aborting due to previous error

Expand Down
80 changes: 80 additions & 0 deletions src/test/ui/traits/trait-upcasting/basic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// run-pass

#![feature(trait_upcasting)]

trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
fn a(&self) -> i32 { 10 }

fn z(&self) -> i32 { 11 }

fn y(&self) -> i32 { 12 }
}

trait Bar: Foo {
fn b(&self) -> i32 { 20 }

fn w(&self) -> i32 { 21 }
}

trait Baz: Bar {
fn c(&self) -> i32 { 30 }
}

impl Foo for i32 {
fn a(&self) -> i32 { 100 }
}

impl Bar for i32 {
fn b(&self) -> i32 { 200 }
}

impl Baz for i32 {
fn c(&self) -> i32 { 300 }
}

fn main() {
let baz: &dyn Baz = &1;
let _: &dyn std::fmt::Debug = baz;
let _: &(dyn Send + Sync) = baz;
let _: &dyn Send = baz;
let _: &dyn Sync = baz;
assert_eq!(*baz, 1);
assert_eq!(baz.a(), 100);
assert_eq!(baz.b(), 200);
assert_eq!(baz.c(), 300);
assert_eq!(baz.z(), 11);
assert_eq!(baz.y(), 12);
assert_eq!(baz.w(), 21);

let bar: &dyn Bar = baz;
let _: &dyn std::fmt::Debug = bar;
let _: &(dyn Send + Sync) = bar;
let _: &dyn Send = bar;
let _: &dyn Sync = bar;
assert_eq!(*bar, 1);
assert_eq!(bar.a(), 100);
assert_eq!(bar.b(), 200);
assert_eq!(bar.z(), 11);
assert_eq!(bar.y(), 12);
assert_eq!(bar.w(), 21);

let foo: &dyn Foo = baz;
let _: &dyn std::fmt::Debug = foo;
let _: &(dyn Send + Sync) = foo;
let _: &dyn Send = foo;
let _: &dyn Sync = foo;
assert_eq!(*foo, 1);
assert_eq!(foo.a(), 100);
assert_eq!(foo.z(), 11);
assert_eq!(foo.y(), 12);

let foo: &dyn Foo = bar;
let _: &dyn std::fmt::Debug = foo;
let _: &(dyn Send + Sync) = foo;
let _: &dyn Send = foo;
let _: &dyn Sync = foo;
assert_eq!(*foo, 1);
assert_eq!(foo.a(), 100);
assert_eq!(foo.z(), 11);
assert_eq!(foo.y(), 12);
}
13 changes: 13 additions & 0 deletions src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
trait A: B + A {}
//~^ ERROR cycle detected when computing the supertraits of `A` [E0391]

trait B {}

impl A for () {}

impl B for () {}

fn main() {
let a: Box<dyn A> = Box::new(());
let _b: Box<dyn B> = a;
}
16 changes: 16 additions & 0 deletions src/test/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0391]: cycle detected when computing the supertraits of `A`
--> $DIR/cyclic-trait-resolution.rs:1:14
|
LL | trait A: B + A {}
| ^
|
= note: ...which again requires computing the supertraits of `A`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/cyclic-trait-resolution.rs:1:1
|
LL | trait A: B + A {}
| ^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0391`.
108 changes: 108 additions & 0 deletions src/test/ui/traits/trait-upcasting/diamond.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// run-pass

#![feature(trait_upcasting)]

trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
fn a(&self) -> i32 { 10 }

fn z(&self) -> i32 { 11 }

fn y(&self) -> i32 { 12 }
}

trait Bar1: Foo {
fn b(&self) -> i32 { 20 }

fn w(&self) -> i32 { 21 }
}

trait Bar2: Foo {
fn c(&self) -> i32 { 30 }

fn v(&self) -> i32 { 31 }
}

trait Baz: Bar1 + Bar2 {
fn d(&self) -> i32 { 40 }
}

impl Foo for i32 {
fn a(&self) -> i32 { 100 }
}

impl Bar1 for i32 {
fn b(&self) -> i32 { 200 }
}

impl Bar2 for i32 {
fn c(&self) -> i32 { 300 }
}

impl Baz for i32 {
fn d(&self) -> i32 { 400 }
}

fn main() {
let baz: &dyn Baz = &1;
let _: &dyn std::fmt::Debug = baz;
let _: &(dyn Send + Sync) = baz;
let _: &dyn Send = baz;
let _: &dyn Sync = baz;
assert_eq!(*baz, 1);
assert_eq!(baz.a(), 100);
assert_eq!(baz.b(), 200);
assert_eq!(baz.c(), 300);
assert_eq!(baz.d(), 400);
assert_eq!(baz.z(), 11);
assert_eq!(baz.y(), 12);
assert_eq!(baz.w(), 21);
assert_eq!(baz.v(), 31);

let bar1: &dyn Bar1 = baz;
let _: &dyn std::fmt::Debug = bar1;
let _: &(dyn Send + Sync) = bar1;
let _: &dyn Send = bar1;
let _: &dyn Sync = bar1;
assert_eq!(*bar1, 1);
assert_eq!(bar1.a(), 100);
assert_eq!(bar1.b(), 200);
assert_eq!(bar1.z(), 11);
assert_eq!(bar1.y(), 12);
assert_eq!(bar1.w(), 21);

let bar2: &dyn Bar2 = baz;
let _: &dyn std::fmt::Debug = bar2;
let _: &(dyn Send + Sync) = bar2;
let _: &dyn Send = bar2;
let _: &dyn Sync = bar2;
assert_eq!(*bar2, 1);
assert_eq!(bar2.a(), 100);
assert_eq!(bar2.c(), 300);
assert_eq!(bar2.z(), 11);
assert_eq!(bar2.y(), 12);
assert_eq!(bar2.v(), 31);

let foo: &dyn Foo = baz;
let _: &dyn std::fmt::Debug = foo;
let _: &(dyn Send + Sync) = foo;
let _: &dyn Send = foo;
let _: &dyn Sync = foo;
assert_eq!(*foo, 1);
assert_eq!(foo.a(), 100);

let foo: &dyn Foo = bar1;
let _: &dyn std::fmt::Debug = foo;
let _: &(dyn Send + Sync) = foo;
let _: &dyn Send = foo;
let _: &dyn Sync = foo;
assert_eq!(*foo, 1);
assert_eq!(foo.a(), 100);

let foo: &dyn Foo = bar2;
let _: &dyn std::fmt::Debug = foo;
let _: &(dyn Send + Sync) = foo;
let _: &dyn Send = foo;
let _: &dyn Sync = foo;
assert_eq!(*foo, 1);
assert_eq!(foo.a(), 100);
}
68 changes: 68 additions & 0 deletions src/test/ui/traits/trait-upcasting/invalid-upcast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#![feature(trait_upcasting)]

trait Foo {
fn a(&self) -> i32 { 10 }

fn z(&self) -> i32 { 11 }

fn y(&self) -> i32 { 12 }
}

trait Bar {
fn b(&self) -> i32 { 20 }

fn w(&self) -> i32 { 21 }
}

trait Baz {
fn c(&self) -> i32 { 30 }
}

impl Foo for i32 {
fn a(&self) -> i32 { 100 }
}

impl Bar for i32 {
fn b(&self) -> i32 { 200 }
}

impl Baz for i32 {
fn c(&self) -> i32 { 300 }
}

fn main() {
let baz: &dyn Baz = &1;
let _: &dyn std::fmt::Debug = baz;
//~^ ERROR `dyn Baz` doesn't implement `std::fmt::Debug` [E0277]
let _: &dyn Send = baz;
//~^ ERROR `dyn Baz` cannot be sent between threads safely [E0277]
let _: &dyn Sync = baz;
//~^ ERROR `dyn Baz` cannot be shared between threads safely [E0277]

let bar: &dyn Bar = baz;
//~^ ERROR the trait bound `dyn Baz: Bar` is not satisfied [E0277]
let _: &dyn std::fmt::Debug = bar;
//~^ ERROR `dyn Bar` doesn't implement `std::fmt::Debug` [E0277]
let _: &dyn Send = bar;
//~^ ERROR `dyn Bar` cannot be sent between threads safely [E0277]
let _: &dyn Sync = bar;
//~^ ERROR `dyn Bar` cannot be shared between threads safely [E0277]

let foo: &dyn Foo = baz;
//~^ ERROR the trait bound `dyn Baz: Foo` is not satisfied [E0277]
let _: &dyn std::fmt::Debug = foo;
//~^ ERROR `dyn Foo` doesn't implement `std::fmt::Debug` [E0277]
let _: &dyn Send = foo;
//~^ ERROR `dyn Foo` cannot be sent between threads safely [E0277]
let _: &dyn Sync = foo;
//~^ ERROR `dyn Foo` cannot be shared between threads safely [E0277]

let foo: &dyn Foo = bar;
//~^ ERROR the trait bound `dyn Bar: Foo` is not satisfied [E0277]
let _: &dyn std::fmt::Debug = foo;
//~^ ERROR `dyn Foo` doesn't implement `std::fmt::Debug` [E0277]
let _: &dyn Send = foo;
//~^ ERROR `dyn Foo` cannot be sent between threads safely [E0277]
let _: &dyn Sync = foo;
//~^ ERROR `dyn Foo` cannot be shared between threads safely [E0277]
}
Loading

0 comments on commit 9549fbd

Please sign in to comment.