diff --git a/src/test/compile-fail/impl-trait/disallowed-2.rs b/src/test/compile-fail/impl-trait/disallowed-2.rs new file mode 100644 index 0000000000000..46b3106ab8d6e --- /dev/null +++ b/src/test/compile-fail/impl-trait/disallowed-2.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(conservative_impl_trait)] + +fn main() { + let _: impl Fn() = || {}; + //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + let _ = || -> impl Fn() { || {} }; + //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +} diff --git a/src/test/compile-fail/impl-trait/disallowed.rs b/src/test/compile-fail/impl-trait/disallowed.rs new file mode 100644 index 0000000000000..09aba5d8c9168 --- /dev/null +++ b/src/test/compile-fail/impl-trait/disallowed.rs @@ -0,0 +1,61 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(conservative_impl_trait)] + +fn arguments(_: impl Fn(), +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + _: Vec) {} +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + +type Factory = impl Fn() -> R; +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + +type GlobalFactory = fn() -> impl FnOnce() -> R; +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + +trait LazyToString { + fn lazy_to_string<'a>(&'a self) -> impl Fn() -> String; + //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +} + +// Note that the following impl doesn't error, because the trait is invalid. +impl LazyToString for String { + fn lazy_to_string<'a>(&'a self) -> impl Fn() -> String { + || self.clone() + } +} + +#[derive(Copy, Clone)] +struct Lazy(T); + +impl std::ops::Add> for Lazy { + type Output = impl Fn() -> Lazy; + //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + + fn add(self, other: Lazy) -> Self::Output { + move || Lazy(self.0 + other.0) + } +} + +impl std::ops::Add +for impl Fn() -> Lazy +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +where F: Fn() -> impl FnOnce() -> i32 +//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +{ + type Output = Self; + + fn add(self, other: F) -> Self::Output { + move || Lazy(self().0 + other()()) + } +} + +fn main() {} diff --git a/src/test/compile-fail/impl-trait/equality.rs b/src/test/compile-fail/impl-trait/equality.rs new file mode 100644 index 0000000000000..59ad1132b3501 --- /dev/null +++ b/src/test/compile-fail/impl-trait/equality.rs @@ -0,0 +1,89 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(conservative_impl_trait, specialization)] + +trait Foo: Copy + ToString {} + +impl Foo for T {} + +fn hide(x: T) -> impl Foo { + x +} + +fn two(x: bool) -> impl Foo { + if x { + return 1_i32; + } + 0_u32 + //~^ ERROR mismatched types + //~| expected i32, found u32 +} + +fn sum_to(n: u32) -> impl Foo { + if n == 0 { + 0 + } else { + n + sum_to(n - 1) + //~^ ERROR the trait bound `u32: std::ops::Add` is not satisfied + } +} + +trait Leak: Sized { + type T; + fn leak(self) -> Self::T; +} +impl Leak for T { + default type T = (); + default fn leak(self) -> Self::T { panic!() } +} +impl Leak for i32 { + type T = i32; + fn leak(self) -> i32 { self } +} + +trait CheckIfSend: Sized { + type T: Default; + fn check(self) -> Self::T { Default::default() } +} +impl CheckIfSend for T { + default type T = (); +} +impl CheckIfSend for T { + type T = bool; +} + +fn main() { + let _: u32 = hide(0_u32); + //~^ ERROR mismatched types + //~| expected type `u32` + //~| found type `impl Foo` + //~| expected u32, found anonymized type + + let _: i32 = Leak::leak(hide(0_i32)); + //~^ ERROR mismatched types + //~| expected type `i32` + //~| found type `::T` + //~| expected i32, found associated type + + let _: bool = CheckIfSend::check(hide(0_i32)); + //~^ ERROR mismatched types + //~| expected type `bool` + //~| found type `::T` + //~| expected bool, found associated type + + let mut x = (hide(0_u32), hide(0_i32)); + x = (x.1, + //~^ ERROR mismatched types + //~| expected u32, found i32 + x.0); + //~^ ERROR mismatched types + //~| expected i32, found u32 +} diff --git a/src/test/compile-fail/impl-trait/feature-gate.rs b/src/test/compile-fail/impl-trait/feature-gate.rs new file mode 100644 index 0000000000000..8239b06f2b4a3 --- /dev/null +++ b/src/test/compile-fail/impl-trait/feature-gate.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo() -> impl Fn() { || {} } +//~^ ERROR `impl Trait` is experimental + +fn main() {} diff --git a/src/test/compile-fail/impl-trait/lifetimes.rs b/src/test/compile-fail/impl-trait/lifetimes.rs new file mode 100644 index 0000000000000..9d9f6bf72974a --- /dev/null +++ b/src/test/compile-fail/impl-trait/lifetimes.rs @@ -0,0 +1,43 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(conservative_impl_trait)] + +// Helper creating a fake borrow, captured by the impl Trait. +fn borrow<'a, T>(_: &'a mut T) -> impl Copy { () } + +fn stack() -> impl Copy { + //~^ ERROR only named lifetimes are allowed in `impl Trait` + let x = 0; + &x +} + +fn late_bound(x: &i32) -> impl Copy { + //~^ ERROR only named lifetimes are allowed in `impl Trait` + x +} + +// FIXME(#34511) Should work but doesn't at the moment, +// region-checking needs an overhault to support this. +fn early_bound<'a>(x: &'a i32) -> impl Copy { + //~^ ERROR only named lifetimes are allowed in `impl Trait` + x +} + +fn ambiguous<'a, 'b>(x: &'a [u32], y: &'b [u32]) -> impl Iterator { + //~^ ERROR only named lifetimes are allowed in `impl Trait` + if x.len() < y.len() { + x.iter().cloned() + } else { + y.iter().cloned() + } +} + +fn main() {} diff --git a/src/test/compile-fail/impl-trait/loan-extend.rs b/src/test/compile-fail/impl-trait/loan-extend.rs new file mode 100644 index 0000000000000..ceaa8f4eed723 --- /dev/null +++ b/src/test/compile-fail/impl-trait/loan-extend.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(conservative_impl_trait)] + +// Helper creating a fake borrow, captured by the impl Trait. +fn borrow<'a, T>(_: &'a mut T) -> impl Copy { () } + +fn main() { + //~^ NOTE reference must be valid for the block + let long; + let mut short = 0; + //~^ NOTE but borrowed value is only valid for the block suffix following statement 1 + long = borrow(&mut short); + //~^ ERROR `short` does not live long enough +} diff --git a/src/test/run-pass/impl-trait/equality.rs b/src/test/run-pass/impl-trait/equality.rs new file mode 100644 index 0000000000000..72b0e588ff483 --- /dev/null +++ b/src/test/run-pass/impl-trait/equality.rs @@ -0,0 +1,43 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(conservative_impl_trait, specialization)] + +trait Foo: std::fmt::Debug + Eq {} + +impl Foo for T {} + +fn hide(x: T) -> impl Foo { + x +} + +trait Leak: Sized { + fn leak(self) -> T; +} +impl Leak for U { + default fn leak(self) -> T { panic!("type mismatch") } +} +impl Leak for T { + fn leak(self) -> T { self } +} + +fn lucky_seven() -> impl Fn(usize) -> u8 { + let a = [1, 2, 3, 4, 5, 6, 7]; + move |i| a[i] +} + +fn main() { + assert_eq!(hide(42), hide(42)); + + assert_eq!(std::mem::size_of_val(&hide([0_u8; 5])), 5); + assert_eq!(std::mem::size_of_val(&lucky_seven()), 7); + + assert_eq!(Leak::::leak(hide(5_i32)), 5_i32); +}