--- /dev/null
+// compile-flags: -Z chalk
+
+trait Foo { }
+
+impl Foo for i32 { }
+
+impl Foo for u32 { }
+
+fn gimme<F: Foo>() { }
+
+// Note: this also tests that `std::process::Termination` is implemented for `()`.
+fn main() {
+ gimme::<i32>();
+ gimme::<u32>();
+ gimme::<f32>(); //~ERROR the trait bound `f32: Foo` is not satisfied
+}
--- /dev/null
+// compile-flags: -Z chalk
+
+trait Foo { }
+
+impl<T> Foo for (T, u32) { }
+
+fn gimme<F: Foo>() { }
+
+fn foo<T>() {
+ gimme::<(T, u32)>();
+ gimme::<(Option<T>, u32)>();
+ gimme::<(Option<T>, f32)>(); //~ ERROR
+}
+
+fn main() {
+ gimme::<(i32, u32)>();
+ gimme::<(i32, f32)>(); //~ ERROR
+}
--- /dev/null
+// 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<T> Foo for Option<T> { }
+
+impl Bar for () {
+ type Item = i32;
+}
+
+impl<T> Bar for Option<T> {
+ type Item = Option<T>;
+}
+
+impl Bar for f32 {
+//~^ ERROR the trait bound `f32: Foo` is not satisfied
+ type Item = f32;
+}
+
+trait Baz<U: ?Sized> where U: Foo { }
+
+impl Baz<i32> for i32 { }
+
+impl Baz<f32> for f32 { }
+//~^ ERROR the trait bound `f32: Foo` is not satisfied
+
+fn main() {
+}
--- /dev/null
+// compile-flags: -Z chalk
+
+trait Foo { }
+
+struct S<T: Foo> {
+ x: T,
+}
+
+impl Foo for i32 { }
+impl<T> Foo for Option<T> { }
+
+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),
+ };
+}
--- /dev/null
+// compile-flags: -Z chalk
+
+trait Foo { }
+
+impl Foo for i32 { }
+
+struct S<T: Foo> {
+ x: T,
+}
+
+fn only_foo<T: Foo>(_x: &T) { }
+
+impl<T> S<T> {
+ // 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<T: Bar>() { }
+
+impl<T> S<T> {
+ // Test that the environment of `dummy_bar` adds up with the environment
+ // of the inherent impl.
+ fn dummy_bar<U: Bar>(&self) {
+ only_foo(&self.x);
+ only_bar::<U>();
+ }
+}
+
+fn main() {
+ let s = S {
+ x: 5,
+ };
+
+ s.dummy_foo();
+ s.dummy_bar::<u32>();
+}
--- /dev/null
+// 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<T: Foo>() { }
+
+fn only_bar<T: Bar>() {
+ // `T` implements `Bar` hence `<T as Bar>::Item` must also implement `Bar`
+ only_foo::<T::Item>()
+}
+
+fn main() {
+ only_bar::<i32>();
+ only_foo::<<i32 as Bar>::Item>();
+}
--- /dev/null
+// compile-flags: -Z chalk
+
+trait Foo { }
+trait Bar: Foo { }
+
+impl Foo for i32 { }
+impl Bar for i32 { }
+
+fn only_foo<T: Foo>() { }
+
+fn only_bar<T: Bar>() {
+ // `T` implements `Bar` hence `T` must also implement `Foo`
+ only_foo::<T>()
+}
+
+fn main() {
+ only_bar::<i32>()
+}
--- /dev/null
+// compile-flags: -Z chalk
+
+trait Foo { }
+trait Bar<U> where U: Foo { }
+
+impl Foo for i32 { }
+impl Bar<i32> for i32 { }
+
+fn only_foo<T: Foo>() { }
+
+fn only_bar<U, T: Bar<U>>() {
+ only_foo::<U>()
+}
+
+fn main() {
+ only_bar::<i32, i32>()
+}
--- /dev/null
+// compile-flags: -Z chalk
+
+trait Eq { }
+trait Hash: Eq { }
+
+impl Eq for i32 { }
+impl Hash for i32 { }
+
+struct Set<T: Hash> {
+ _x: T,
+}
+
+fn only_eq<T: Eq>() { }
+
+fn take_a_set<T>(_: &Set<T>) {
+ // `Set<T>` 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::<T>()
+}
+
+fn main() {
+ let set = Set {
+ _x: 5,
+ };
+
+ take_a_set(&set);
+}
--- /dev/null
+// compile-flags: -Z chalk
+
+trait Foo { }
+impl Foo for i32 { }
+
+trait Bar { }
+impl Bar for i32 { }
+impl Bar for u32 { }
+
+fn only_foo<T: Foo>(_x: T) { }
+
+fn only_bar<T: 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
+}
--- /dev/null
+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:
+ <i32 as Bar>
+ <u32 as Bar>
+note: required by `only_bar`
+ --> $DIR/type_inference.rs:12:1
+ |
+LL | fn only_bar<T: 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`.