diff --git a/src/test/compile-fail/chalkify/chalk_initial_program.rs b/src/test/compile-fail/chalkify/chalk_initial_program.rs new file mode 100644 index 0000000000000..df25bad622b3d --- /dev/null +++ b/src/test/compile-fail/chalkify/chalk_initial_program.rs @@ -0,0 +1,16 @@ +// compile-flags: -Z chalk + +trait Foo { } + +impl Foo for i32 { } + +impl Foo for u32 { } + +fn gimme() { } + +// Note: this also tests that `std::process::Termination` is implemented for `()`. +fn main() { + gimme::(); + gimme::(); + gimme::(); //~ERROR the trait bound `f32: Foo` is not satisfied +} diff --git a/src/test/compile-fail/chalkify/generic_impls.rs b/src/test/compile-fail/chalkify/generic_impls.rs new file mode 100644 index 0000000000000..d70c6f8055ddf --- /dev/null +++ b/src/test/compile-fail/chalkify/generic_impls.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z chalk + +trait Foo { } + +impl Foo for (T, u32) { } + +fn gimme() { } + +fn foo() { + gimme::<(T, u32)>(); + gimme::<(Option, u32)>(); + gimme::<(Option, f32)>(); //~ ERROR +} + +fn main() { + gimme::<(i32, u32)>(); + gimme::<(i32, f32)>(); //~ ERROR +} diff --git a/src/test/compile-fail/chalkify/impl_wf.rs b/src/test/compile-fail/chalkify/impl_wf.rs new file mode 100644 index 0000000000000..96b1b2533712b --- /dev/null +++ b/src/test/compile-fail/chalkify/impl_wf.rs @@ -0,0 +1,38 @@ +// compile-flags: -Z chalk + +trait Foo: Sized { } + +trait Bar { + type Item: Foo; +} + +impl Foo for i32 { } + +impl Foo for str { } +//~^ ERROR the size for values of type `str` cannot be known at compilation time + +// Implicit `T: Sized` bound. +impl Foo for Option { } + +impl Bar for () { + type Item = i32; +} + +impl Bar for Option { + type Item = Option; +} + +impl Bar for f32 { +//~^ ERROR the trait bound `f32: Foo` is not satisfied + type Item = f32; +} + +trait Baz where U: Foo { } + +impl Baz for i32 { } + +impl Baz for f32 { } +//~^ ERROR the trait bound `f32: Foo` is not satisfied + +fn main() { +} diff --git a/src/test/compile-fail/chalkify/type_wf.rs b/src/test/compile-fail/chalkify/type_wf.rs new file mode 100644 index 0000000000000..d1aa975ddc24d --- /dev/null +++ b/src/test/compile-fail/chalkify/type_wf.rs @@ -0,0 +1,24 @@ +// compile-flags: -Z chalk + +trait Foo { } + +struct S { + x: T, +} + +impl Foo for i32 { } +impl Foo for Option { } + +fn main() { + let s = S { + x: 5, + }; + + let s = S { //~ ERROR the trait bound `{float}: Foo` is not satisfied + x: 5.0, + }; + + let s = S { + x: Some(5.0), + }; +} diff --git a/src/test/run-pass/chalkify/inherent_impl.rs b/src/test/run-pass/chalkify/inherent_impl.rs new file mode 100644 index 0000000000000..fbe30f115444e --- /dev/null +++ b/src/test/run-pass/chalkify/inherent_impl.rs @@ -0,0 +1,41 @@ +// compile-flags: -Z chalk + +trait Foo { } + +impl Foo for i32 { } + +struct S { + x: T, +} + +fn only_foo(_x: &T) { } + +impl S { + // Test that we have the correct environment inside an inherent method. + fn dummy_foo(&self) { + only_foo(&self.x) + } +} + +trait Bar { } +impl Bar for u32 { } + +fn only_bar() { } + +impl S { + // Test that the environment of `dummy_bar` adds up with the environment + // of the inherent impl. + fn dummy_bar(&self) { + only_foo(&self.x); + only_bar::(); + } +} + +fn main() { + let s = S { + x: 5, + }; + + s.dummy_foo(); + s.dummy_bar::(); +} diff --git a/src/test/run-pass/chalkify/projection.rs b/src/test/run-pass/chalkify/projection.rs new file mode 100644 index 0000000000000..a598f68d3f987 --- /dev/null +++ b/src/test/run-pass/chalkify/projection.rs @@ -0,0 +1,24 @@ +// compile-flags: -Z chalk + +trait Foo { } + +trait Bar { + type Item: Foo; +} + +impl Foo for i32 { } +impl Bar for i32 { + type Item = i32; +} + +fn only_foo() { } + +fn only_bar() { + // `T` implements `Bar` hence `::Item` must also implement `Bar` + only_foo::() +} + +fn main() { + only_bar::(); + only_foo::<::Item>(); +} diff --git a/src/test/run-pass/chalkify/super_trait.rs b/src/test/run-pass/chalkify/super_trait.rs new file mode 100644 index 0000000000000..441d61ef24893 --- /dev/null +++ b/src/test/run-pass/chalkify/super_trait.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z chalk + +trait Foo { } +trait Bar: Foo { } + +impl Foo for i32 { } +impl Bar for i32 { } + +fn only_foo() { } + +fn only_bar() { + // `T` implements `Bar` hence `T` must also implement `Foo` + only_foo::() +} + +fn main() { + only_bar::() +} diff --git a/src/test/run-pass/chalkify/trait_implied_bound.rs b/src/test/run-pass/chalkify/trait_implied_bound.rs new file mode 100644 index 0000000000000..f82453792ff4c --- /dev/null +++ b/src/test/run-pass/chalkify/trait_implied_bound.rs @@ -0,0 +1,17 @@ +// compile-flags: -Z chalk + +trait Foo { } +trait Bar where U: Foo { } + +impl Foo for i32 { } +impl Bar for i32 { } + +fn only_foo() { } + +fn only_bar>() { + only_foo::() +} + +fn main() { + only_bar::() +} diff --git a/src/test/run-pass/chalkify/type_implied_bound.rs b/src/test/run-pass/chalkify/type_implied_bound.rs new file mode 100644 index 0000000000000..94d976d324271 --- /dev/null +++ b/src/test/run-pass/chalkify/type_implied_bound.rs @@ -0,0 +1,28 @@ +// compile-flags: -Z chalk + +trait Eq { } +trait Hash: Eq { } + +impl Eq for i32 { } +impl Hash for i32 { } + +struct Set { + _x: T, +} + +fn only_eq() { } + +fn take_a_set(_: &Set) { + // `Set` is an input type of `take_a_set`, hence we know that + // `T` must implement `Hash`, and we know in turn that `T` must + // implement `Eq`. + only_eq::() +} + +fn main() { + let set = Set { + _x: 5, + }; + + take_a_set(&set); +} diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs new file mode 100644 index 0000000000000..62a53ec0317b3 --- /dev/null +++ b/src/test/ui/chalkify/type_inference.rs @@ -0,0 +1,26 @@ +// compile-flags: -Z chalk + +trait Foo { } +impl Foo for i32 { } + +trait Bar { } +impl Bar for i32 { } +impl Bar for u32 { } + +fn only_foo(_x: T) { } + +fn only_bar(_x: T) { } + +fn main() { + let x = 5.0; + + // The only type which implements `Foo` is `i32`, so the chalk trait solver + // is expecting a variable of type `i32`. This behavior differs from the + // old-style trait solver. I guess this will change, that's why I'm + // adding that test. + only_foo(x); //~ ERROR mismatched types + + // Here we have two solutions so we get back the behavior of the old-style + // trait solver. + only_bar(x); //~ ERROR the trait bound `{float}: Bar` is not satisfied +} diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr new file mode 100644 index 0000000000000..49ed97d71680b --- /dev/null +++ b/src/test/ui/chalkify/type_inference.stderr @@ -0,0 +1,28 @@ +error[E0308]: mismatched types + --> $DIR/type_inference.rs:21:14 + | +LL | only_foo(x); //~ ERROR mismatched types + | ^ expected i32, found floating-point variable + | + = note: expected type `i32` + found type `{float}` + +error[E0277]: the trait bound `{float}: Bar` is not satisfied + --> $DIR/type_inference.rs:25:5 + | +LL | only_bar(x); //~ ERROR the trait bound `{float}: Bar` is not satisfied + | ^^^^^^^^ the trait `Bar` is not implemented for `{float}` + | + = help: the following implementations were found: + + +note: required by `only_bar` + --> $DIR/type_inference.rs:12:1 + | +LL | fn only_bar(_x: T) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors occurred: E0277, E0308. +For more information about an error, try `rustc --explain E0277`.