Skip to content

Commit

Permalink
test: add more extensive tests for impl Trait.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Aug 12, 2016
1 parent 08bf9f6 commit 23f0494
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/test/compile-fail/impl-trait/disallowed-2.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
}
61 changes: 61 additions & 0 deletions src/test/compile-fail/impl-trait/disallowed.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<impl Clone>) {}
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

type Factory<R> = impl Fn() -> R;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

type GlobalFactory<R> = 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>(T);

impl std::ops::Add<Lazy<i32>> for Lazy<i32> {
type Output = impl Fn() -> Lazy<i32>;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

fn add(self, other: Lazy<i32>) -> Self::Output {
move || Lazy(self.0 + other.0)
}
}

impl<F> std::ops::Add<F>
for impl Fn() -> Lazy<i32>
//~^ 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() {}
89 changes: 89 additions & 0 deletions src/test/compile-fail/impl-trait/equality.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Copy + ToString> Foo for T {}

fn hide<T: Foo>(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<impl Foo>` is not satisfied
}
}

trait Leak: Sized {
type T;
fn leak(self) -> Self::T;
}
impl<T> 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<T> CheckIfSend for T {
default type T = ();
}
impl<T: Send> 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 `<impl Foo as Leak>::T`
//~| expected i32, found associated type

let _: bool = CheckIfSend::check(hide(0_i32));
//~^ ERROR mismatched types
//~| expected type `bool`
//~| found type `<impl Foo as CheckIfSend>::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
}
14 changes: 14 additions & 0 deletions src/test/compile-fail/impl-trait/feature-gate.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
43 changes: 43 additions & 0 deletions src/test/compile-fail/impl-trait/lifetimes.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Item=u32> {
//~^ ERROR only named lifetimes are allowed in `impl Trait`
if x.len() < y.len() {
x.iter().cloned()
} else {
y.iter().cloned()
}
}

fn main() {}
23 changes: 23 additions & 0 deletions src/test/compile-fail/impl-trait/loan-extend.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
}
43 changes: 43 additions & 0 deletions src/test/run-pass/impl-trait/equality.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: std::fmt::Debug + Eq> Foo for T {}

fn hide<T: Foo>(x: T) -> impl Foo {
x
}

trait Leak<T>: Sized {
fn leak(self) -> T;
}
impl<T, U> Leak<T> for U {
default fn leak(self) -> T { panic!("type mismatch") }
}
impl<T> Leak<T> 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::<i32>::leak(hide(5_i32)), 5_i32);
}

0 comments on commit 23f0494

Please sign in to comment.