From 218caa410aa38c29984be31a5229b9fa717560ee Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:13 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- tests/ui/functions-closures/auxiliary/fn-abi.rs | 2 + .../call-closure-from-overloaded-op.rs | 9 ++++ .../capture-clauses-boxed-closures.rs | 14 ++++++ .../capture-clauses-unboxed-closures.rs | 13 +++++ tests/ui/functions-closures/clone-closure.rs | 18 +++++++ .../closure-bounds-can-capture-chan.rs | 16 +++++++ .../closure-expected-type/README.md | 8 ++++ .../expect-infer-supply-two-infers.rs | 19 ++++++++ .../closure-expected-type/issue-38714.rs | 19 ++++++++ .../supply-just-return-type.rs | 26 ++++++++++ .../closure-expected-type/supply-nothing.rs | 11 +++++ tests/ui/functions-closures/closure-immediate.rs | 13 +++++ tests/ui/functions-closures/closure-inference.rs | 11 +++++ tests/ui/functions-closures/closure-inference2.rs | 9 ++++ tests/ui/functions-closures/closure-reform.rs | 56 ++++++++++++++++++++++ .../closure-returning-closure.rs | 5 ++ .../functions-closures/closure-to-fn-coercion.rs | 35 ++++++++++++++ .../closure_to_fn_coercion-expected-types.rs | 9 ++++ tests/ui/functions-closures/copy-closure.rs | 16 +++++++ tests/ui/functions-closures/fn-abi.rs | 18 +++++++ tests/ui/functions-closures/fn-bare-assign.rs | 17 +++++++ .../functions-closures/fn-bare-coerce-to-block.rs | 10 ++++ tests/ui/functions-closures/fn-bare-item.rs | 8 ++++ tests/ui/functions-closures/fn-bare-size.rs | 8 ++++ tests/ui/functions-closures/fn-bare-spawn.rs | 15 ++++++ tests/ui/functions-closures/fn-coerce-field.rs | 13 +++++ .../fn-help-with-err-generic-is-not-function.rs | 14 ++++++ ...fn-help-with-err-generic-is-not-function.stderr | 20 ++++++++ tests/ui/functions-closures/fn-help-with-err.rs | 24 ++++++++++ .../ui/functions-closures/fn-help-with-err.stderr | 27 +++++++++++ tests/ui/functions-closures/fn-item-type-cast.rs | 22 +++++++++ tests/ui/functions-closures/fn-item-type-coerce.rs | 17 +++++++ .../functions-closures/fn-item-type-zero-sized.rs | 13 +++++ tests/ui/functions-closures/fn-lval.rs | 11 +++++ tests/ui/functions-closures/fn-type-infer.rs | 11 +++++ .../implied-bounds-closure-arg-outlives.rs | 35 ++++++++++++++ .../nullable-pointer-opt-closures.rs | 34 +++++++++++++ .../parallel-codegen-closures.rs | 28 +++++++++++ tests/ui/functions-closures/return-from-closure.rs | 33 +++++++++++++ 39 files changed, 687 insertions(+) create mode 100644 tests/ui/functions-closures/auxiliary/fn-abi.rs create mode 100644 tests/ui/functions-closures/call-closure-from-overloaded-op.rs create mode 100644 tests/ui/functions-closures/capture-clauses-boxed-closures.rs create mode 100644 tests/ui/functions-closures/capture-clauses-unboxed-closures.rs create mode 100644 tests/ui/functions-closures/clone-closure.rs create mode 100644 tests/ui/functions-closures/closure-bounds-can-capture-chan.rs create mode 100644 tests/ui/functions-closures/closure-expected-type/README.md create mode 100644 tests/ui/functions-closures/closure-expected-type/expect-infer-supply-two-infers.rs create mode 100644 tests/ui/functions-closures/closure-expected-type/issue-38714.rs create mode 100644 tests/ui/functions-closures/closure-expected-type/supply-just-return-type.rs create mode 100644 tests/ui/functions-closures/closure-expected-type/supply-nothing.rs create mode 100644 tests/ui/functions-closures/closure-immediate.rs create mode 100644 tests/ui/functions-closures/closure-inference.rs create mode 100644 tests/ui/functions-closures/closure-inference2.rs create mode 100644 tests/ui/functions-closures/closure-reform.rs create mode 100644 tests/ui/functions-closures/closure-returning-closure.rs create mode 100644 tests/ui/functions-closures/closure-to-fn-coercion.rs create mode 100644 tests/ui/functions-closures/closure_to_fn_coercion-expected-types.rs create mode 100644 tests/ui/functions-closures/copy-closure.rs create mode 100644 tests/ui/functions-closures/fn-abi.rs create mode 100644 tests/ui/functions-closures/fn-bare-assign.rs create mode 100644 tests/ui/functions-closures/fn-bare-coerce-to-block.rs create mode 100644 tests/ui/functions-closures/fn-bare-item.rs create mode 100644 tests/ui/functions-closures/fn-bare-size.rs create mode 100644 tests/ui/functions-closures/fn-bare-spawn.rs create mode 100644 tests/ui/functions-closures/fn-coerce-field.rs create mode 100644 tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs create mode 100644 tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr create mode 100644 tests/ui/functions-closures/fn-help-with-err.rs create mode 100644 tests/ui/functions-closures/fn-help-with-err.stderr create mode 100644 tests/ui/functions-closures/fn-item-type-cast.rs create mode 100644 tests/ui/functions-closures/fn-item-type-coerce.rs create mode 100644 tests/ui/functions-closures/fn-item-type-zero-sized.rs create mode 100644 tests/ui/functions-closures/fn-lval.rs create mode 100644 tests/ui/functions-closures/fn-type-infer.rs create mode 100644 tests/ui/functions-closures/implied-bounds-closure-arg-outlives.rs create mode 100644 tests/ui/functions-closures/nullable-pointer-opt-closures.rs create mode 100644 tests/ui/functions-closures/parallel-codegen-closures.rs create mode 100644 tests/ui/functions-closures/return-from-closure.rs (limited to 'tests/ui/functions-closures') diff --git a/tests/ui/functions-closures/auxiliary/fn-abi.rs b/tests/ui/functions-closures/auxiliary/fn-abi.rs new file mode 100644 index 000000000..ace9fbdfd --- /dev/null +++ b/tests/ui/functions-closures/auxiliary/fn-abi.rs @@ -0,0 +1,2 @@ +#[no_mangle] +pub extern "C" fn foo() {} diff --git a/tests/ui/functions-closures/call-closure-from-overloaded-op.rs b/tests/ui/functions-closures/call-closure-from-overloaded-op.rs new file mode 100644 index 000000000..8e1c68fd7 --- /dev/null +++ b/tests/ui/functions-closures/call-closure-from-overloaded-op.rs @@ -0,0 +1,9 @@ +// run-pass + +fn foo() -> isize { 22 } + +pub fn main() { + let mut x: Vec isize> = Vec::new(); + x.push(foo); + assert_eq!((x[0])(), 22); +} diff --git a/tests/ui/functions-closures/capture-clauses-boxed-closures.rs b/tests/ui/functions-closures/capture-clauses-boxed-closures.rs new file mode 100644 index 000000000..bcde50463 --- /dev/null +++ b/tests/ui/functions-closures/capture-clauses-boxed-closures.rs @@ -0,0 +1,14 @@ +// run-pass + +fn each(x: &[T], mut f: F) where F: FnMut(&T) { + for val in x { + f(val) + } +} + +fn main() { + let mut sum = 0_usize; + let elems = [ 1_usize, 2, 3, 4, 5 ]; + each(&elems, |val| sum += *val); + assert_eq!(sum, 15); +} diff --git a/tests/ui/functions-closures/capture-clauses-unboxed-closures.rs b/tests/ui/functions-closures/capture-clauses-unboxed-closures.rs new file mode 100644 index 000000000..206b3d7b6 --- /dev/null +++ b/tests/ui/functions-closures/capture-clauses-unboxed-closures.rs @@ -0,0 +1,13 @@ +// run-pass +fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) { + for val in x { + f(val) + } +} + +fn main() { + let mut sum = 0; + let elems = [ 1, 2, 3, 4, 5 ]; + each(&elems, |val: &usize| sum += *val); + assert_eq!(sum, 15); +} diff --git a/tests/ui/functions-closures/clone-closure.rs b/tests/ui/functions-closures/clone-closure.rs new file mode 100644 index 000000000..1e725d805 --- /dev/null +++ b/tests/ui/functions-closures/clone-closure.rs @@ -0,0 +1,18 @@ +// run-pass +// Check that closures implement `Clone`. + +#[derive(Clone)] +struct S(i32); + +fn main() { + let mut a = S(5); + let mut hello = move || { + a.0 += 1; + println!("Hello {}", a.0); + a.0 + }; + + let mut hello2 = hello.clone(); + assert_eq!(6, hello2()); + assert_eq!(6, hello()); +} diff --git a/tests/ui/functions-closures/closure-bounds-can-capture-chan.rs b/tests/ui/functions-closures/closure-bounds-can-capture-chan.rs new file mode 100644 index 000000000..ccb2e201d --- /dev/null +++ b/tests/ui/functions-closures/closure-bounds-can-capture-chan.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::sync::mpsc::channel; + +fn foo(blk: F) { + blk(); +} + +pub fn main() { + let (tx, rx) = channel(); + foo(move || { + tx.send(()).unwrap(); + }); + rx.recv().unwrap(); +} diff --git a/tests/ui/functions-closures/closure-expected-type/README.md b/tests/ui/functions-closures/closure-expected-type/README.md new file mode 100644 index 000000000..0b749040a --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/README.md @@ -0,0 +1,8 @@ +Some tests targeted at how we deduce the types of closure arguments. +This process is a result of some heuristics aimed at combining the +*expected type* we have with the *actual types* that we get from +inputs. This investigation was kicked off by #38714, which revealed +some pretty deep flaws in the ad-hoc way that we were doing things +before. + +See also `tests/ui/closure-expected-type`. diff --git a/tests/ui/functions-closures/closure-expected-type/expect-infer-supply-two-infers.rs b/tests/ui/functions-closures/closure-expected-type/expect-infer-supply-two-infers.rs new file mode 100644 index 000000000..6d5a9876c --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/expect-infer-supply-two-infers.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +fn with_closure(_: F) + where F: FnOnce(Vec, A) +{ +} + +fn expect_free_supply_free<'x>(x: &'x u32) { + with_closure(|mut x: Vec<_>, y| { + // Shows that the call to `x.push()` is influencing type of `y`... + x.push(22_u32); + + // ...since we now know the type of `y` and can resolve the method call. + let _ = y.wrapping_add(1); + }); +} + +fn main() { } diff --git a/tests/ui/functions-closures/closure-expected-type/issue-38714.rs b/tests/ui/functions-closures/closure-expected-type/issue-38714.rs new file mode 100644 index 000000000..e97785b5c --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/issue-38714.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +struct UsizeRef<'a> { + a: &'a usize +} + +type RefTo = Box Fn(&'r Vec) -> UsizeRef<'r>>; + +fn ref_to<'a>(vec: &'a Vec) -> UsizeRef<'a> { + UsizeRef{ a: &vec[0]} +} + +fn main() { + // Regression test: this was causing ICEs; it should compile. + let a: RefTo = Box::new(|vec: &Vec| { + UsizeRef{ a: &vec[0] } + }); +} diff --git a/tests/ui/functions-closures/closure-expected-type/supply-just-return-type.rs b/tests/ui/functions-closures/closure-expected-type/supply-just-return-type.rs new file mode 100644 index 000000000..e9964531c --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/supply-just-return-type.rs @@ -0,0 +1,26 @@ +// run-pass +fn with_closure(f: F) -> Result + where F: FnOnce(&char) -> Result, +{ + f(&'a') +} + +fn main() { + // Test that supplying the `-> Result` manually here + // (which is needed to constrain `R`) still allows us to figure + // out that the type of `x` is `&'a char` where `'a` is bound in + // the closure (if we didn't, we'd get a type-error because + // `with_closure` requires a bound region). + // + // This pattern was found in the wild. + let z = with_closure(|x| -> Result { Ok(*x) }); + assert_eq!(z.unwrap(), 'a'); + + // It also works with `_`: + let z = with_closure(|x: _| -> Result { Ok(*x) }); + assert_eq!(z.unwrap(), 'a'); + + // It also works with `&_`: + let z = with_closure(|x: &_| -> Result { Ok(*x) }); + assert_eq!(z.unwrap(), 'a'); +} diff --git a/tests/ui/functions-closures/closure-expected-type/supply-nothing.rs b/tests/ui/functions-closures/closure-expected-type/supply-nothing.rs new file mode 100644 index 000000000..8665cfc21 --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/supply-nothing.rs @@ -0,0 +1,11 @@ +// run-pass +fn with_closure(f: F) -> u32 + where F: FnOnce(&u32, &u32) -> u32 +{ + f(&22, &44) +} + +fn main() { + let z = with_closure(|x, y| x + y).wrapping_add(1); + assert_eq!(z, 22 + 44 + 1); +} diff --git a/tests/ui/functions-closures/closure-immediate.rs b/tests/ui/functions-closures/closure-immediate.rs new file mode 100644 index 000000000..428fc6bde --- /dev/null +++ b/tests/ui/functions-closures/closure-immediate.rs @@ -0,0 +1,13 @@ +// run-pass + +// After the work to reoptimize structs, it became possible for immediate logic to fail. +// This test verifies that it actually works. + +fn main() { + let c = |a: u8, b: u16, c: u8| { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + }; + c(1, 2, 3); +} diff --git a/tests/ui/functions-closures/closure-inference.rs b/tests/ui/functions-closures/closure-inference.rs new file mode 100644 index 000000000..1877414f0 --- /dev/null +++ b/tests/ui/functions-closures/closure-inference.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_braces)] + +fn foo(i: isize) -> isize { i + 1 } + +fn apply(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) } + +pub fn main() { + let f = {|i| foo(i)}; + assert_eq!(apply(f, 2), 3); +} diff --git a/tests/ui/functions-closures/closure-inference2.rs b/tests/ui/functions-closures/closure-inference2.rs new file mode 100644 index 000000000..4ce132e86 --- /dev/null +++ b/tests/ui/functions-closures/closure-inference2.rs @@ -0,0 +1,9 @@ +// run-pass +// Test a rather underspecified example: +#![allow(unused_braces)] + +pub fn main() { + let f = {|i| i}; + assert_eq!(f(2), 2); + assert_eq!(f(5), 5); +} diff --git a/tests/ui/functions-closures/closure-reform.rs b/tests/ui/functions-closures/closure-reform.rs new file mode 100644 index 000000000..0bb6159ff --- /dev/null +++ b/tests/ui/functions-closures/closure-reform.rs @@ -0,0 +1,56 @@ +// run-pass +#![allow(unused_variables)] +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +fn call_it(f: F) + where F : FnOnce(String) -> String +{ + println!("{}", f("Fred".to_string())) +} + +fn call_a_thunk(f: F) where F: FnOnce() { + f(); +} + +fn call_this(f: F) where F: FnOnce(&str) + Send { + f("Hello!"); +} + +fn call_bare(f: fn(&str)) { + f("Hello world!") +} + +fn call_bare_again(f: extern "Rust" fn(&str)) { + f("Goodbye world!") +} + +pub fn main() { + // Procs + + let greeting = "Hello ".to_string(); + call_it(|s| { + format!("{}{}", greeting, s) + }); + + let greeting = "Goodbye ".to_string(); + call_it(|s| format!("{}{}", greeting, s)); + + let greeting = "How's life, ".to_string(); + call_it(|s: String| -> String { + format!("{}{}", greeting, s) + }); + + // Closures + + call_a_thunk(|| println!("Hello world!")); + + call_this(|s| println!("{}", s)); + + // External functions + + fn foo(s: &str) {} + call_bare(foo); + + call_bare_again(foo); +} diff --git a/tests/ui/functions-closures/closure-returning-closure.rs b/tests/ui/functions-closures/closure-returning-closure.rs new file mode 100644 index 000000000..17db81687 --- /dev/null +++ b/tests/ui/functions-closures/closure-returning-closure.rs @@ -0,0 +1,5 @@ +// run-pass +fn main() { + let f = |_||x, y| x+y; + assert_eq!(f(())(1, 2), 3); +} diff --git a/tests/ui/functions-closures/closure-to-fn-coercion.rs b/tests/ui/functions-closures/closure-to-fn-coercion.rs new file mode 100644 index 000000000..87ba488b5 --- /dev/null +++ b/tests/ui/functions-closures/closure-to-fn-coercion.rs @@ -0,0 +1,35 @@ +// run-pass +use std::mem; + +const FOO: fn(u8) -> u8 = |v: u8| { v }; + +const BAR: [fn(&mut u32); 5] = [ + |_: &mut u32| {}, + |v: &mut u32| *v += 1, + |v: &mut u32| *v += 2, + |v: &mut u32| *v += 3, + |v: &mut u32| *v += 4, +]; +fn func_specific() -> fn() -> u32 { + || return 42 +} + +fn generic(_: T) -> fn() -> usize { + || mem::size_of::() +} + +fn main() { + // Items + assert_eq!(func_specific()(), 42); + let foo: fn(u8) -> u8 = |v: u8| { v }; + assert_eq!(foo(31), 31); + // Constants + assert_eq!(FOO(31), 31); + let mut a: u32 = 0; + assert_eq!({ BAR[0](&mut a); a }, 0); + assert_eq!({ BAR[1](&mut a); a }, 1); + assert_eq!({ BAR[2](&mut a); a }, 3); + assert_eq!({ BAR[3](&mut a); a }, 6); + assert_eq!({ BAR[4](&mut a); a }, 10); + assert_eq!(generic(0i8)(), 1); +} diff --git a/tests/ui/functions-closures/closure_to_fn_coercion-expected-types.rs b/tests/ui/functions-closures/closure_to_fn_coercion-expected-types.rs new file mode 100644 index 000000000..e7a938395 --- /dev/null +++ b/tests/ui/functions-closures/closure_to_fn_coercion-expected-types.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_variables)] +// Ensure that we deduce expected argument types when a `fn()` type is expected (#41755) + +fn foo(f: fn(Vec) -> usize) { } + +fn main() { + foo(|x| x.len()) +} diff --git a/tests/ui/functions-closures/copy-closure.rs b/tests/ui/functions-closures/copy-closure.rs new file mode 100644 index 000000000..72da02421 --- /dev/null +++ b/tests/ui/functions-closures/copy-closure.rs @@ -0,0 +1,16 @@ +// run-pass +// Check that closures implement `Copy`. + +fn call T>(f: F) -> T { f() } + +fn main() { + let a = 5; + let hello = || { + println!("Hello {}", a); + a + }; + + assert_eq!(5, call(hello.clone())); + assert_eq!(5, call(hello)); + assert_eq!(5, call(hello)); +} diff --git a/tests/ui/functions-closures/fn-abi.rs b/tests/ui/functions-closures/fn-abi.rs new file mode 100644 index 000000000..ac3a4be33 --- /dev/null +++ b/tests/ui/functions-closures/fn-abi.rs @@ -0,0 +1,18 @@ +// run-pass +// Ensure that declarations and types which use `extern fn` both have the same +// ABI (#9309). + +// pretty-expanded FIXME #23616 +// aux-build:fn-abi.rs + +extern crate fn_abi; + +extern "C" { + fn foo(); +} + +pub fn main() { + // Will only type check if the type of _p and the decl of foo use the + // same ABI + let _p: unsafe extern "C" fn() = foo; +} diff --git a/tests/ui/functions-closures/fn-bare-assign.rs b/tests/ui/functions-closures/fn-bare-assign.rs new file mode 100644 index 000000000..f5dab3c84 --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-assign.rs @@ -0,0 +1,17 @@ +// run-pass + +fn f(i: isize, called: &mut bool) { + assert_eq!(i, 10); + *called = true; +} + +fn g(f: fn(isize, v: &mut bool), called: &mut bool) { + f(10, called); +} + +pub fn main() { + let mut called = false; + let h = f; + g(h, &mut called); + assert_eq!(called, true); +} diff --git a/tests/ui/functions-closures/fn-bare-coerce-to-block.rs b/tests/ui/functions-closures/fn-bare-coerce-to-block.rs new file mode 100644 index 000000000..922e016dd --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-coerce-to-block.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn bare() {} + +fn likes_block(f: F) where F: FnOnce() { f() } + +pub fn main() { + likes_block(bare); +} diff --git a/tests/ui/functions-closures/fn-bare-item.rs b/tests/ui/functions-closures/fn-bare-item.rs new file mode 100644 index 000000000..a6e6495a4 --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-item.rs @@ -0,0 +1,8 @@ +// run-pass +fn f() { + println!("This is a bare function"); +} + +pub fn main() { + f(); +} diff --git a/tests/ui/functions-closures/fn-bare-size.rs b/tests/ui/functions-closures/fn-bare-size.rs new file mode 100644 index 000000000..2ba56eaae --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-size.rs @@ -0,0 +1,8 @@ +// run-pass + +use std::mem; + +pub fn main() { + // Bare functions should just be a pointer + assert_eq!(mem::size_of::(), mem::size_of::()); +} diff --git a/tests/ui/functions-closures/fn-bare-spawn.rs b/tests/ui/functions-closures/fn-bare-spawn.rs new file mode 100644 index 000000000..0d46fe220 --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-spawn.rs @@ -0,0 +1,15 @@ +// run-pass +// This is what the signature to spawn should look like with bare functions + + +fn spawn(val: T, f: fn(T)) { + f(val); +} + +fn f(i: isize) { + assert_eq!(i, 100); +} + +pub fn main() { + spawn(100, f); +} diff --git a/tests/ui/functions-closures/fn-coerce-field.rs b/tests/ui/functions-closures/fn-coerce-field.rs new file mode 100644 index 000000000..38bde7b9e --- /dev/null +++ b/tests/ui/functions-closures/fn-coerce-field.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] + +struct r where F: FnOnce() { + field: F, +} + +pub fn main() { + fn f() {} + let _i: r = r {field: f as fn()}; +} diff --git a/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs new file mode 100644 index 000000000..e48ab4aa9 --- /dev/null +++ b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs @@ -0,0 +1,14 @@ +struct Struct(T); +impl Struct +//~^ ERROR cannot find type `T` in this scope +//~| NOTE not found in this scope +//~| HELP you might be missing a type parameter +where + T: Copy, + //~^ ERROR cannot find type `T` in this scope + //~| NOTE not found in this scope +{ + fn method(v: Vec) { v.len(); } +} + +fn main() {} diff --git a/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr new file mode 100644 index 000000000..9d4ea0115 --- /dev/null +++ b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr @@ -0,0 +1,20 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/fn-help-with-err-generic-is-not-function.rs:2:13 + | +LL | impl Struct + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl Struct + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/fn-help-with-err-generic-is-not-function.rs:7:5 + | +LL | T: Copy, + | ^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/functions-closures/fn-help-with-err.rs b/tests/ui/functions-closures/fn-help-with-err.rs new file mode 100644 index 000000000..612fe1b84 --- /dev/null +++ b/tests/ui/functions-closures/fn-help-with-err.rs @@ -0,0 +1,24 @@ +// This test case checks the behavior of typeck::check::method::suggest::is_fn on Ty::Error. + +struct Foo; + +trait Bar { + //~^ NOTE `Bar` defines an item `bar`, perhaps you need to implement it + fn bar(&self) {} +} + +impl Bar for Foo {} + +fn main() { + let arc = std::sync::Arc::new(oops); + //~^ ERROR cannot find value `oops` in this scope + //~| NOTE not found + arc.bar(); + + let arc2 = std::sync::Arc::new(|| Foo); + arc2.bar(); + //~^ ERROR no method named `bar` + //~| NOTE method not found + //~| HELP items from traits can only be used if the trait is implemented and in scope + //~| HELP use parentheses to call this closure +} diff --git a/tests/ui/functions-closures/fn-help-with-err.stderr b/tests/ui/functions-closures/fn-help-with-err.stderr new file mode 100644 index 000000000..83a2b1f58 --- /dev/null +++ b/tests/ui/functions-closures/fn-help-with-err.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find value `oops` in this scope + --> $DIR/fn-help-with-err.rs:13:35 + | +LL | let arc = std::sync::Arc::new(oops); + | ^^^^ not found in this scope + +error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:18:36]>` in the current scope + --> $DIR/fn-help-with-err.rs:19:10 + | +LL | arc2.bar(); + | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:18:36]>` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `bar`, perhaps you need to implement it + --> $DIR/fn-help-with-err.rs:5:1 + | +LL | trait Bar { + | ^^^^^^^^^ +help: use parentheses to call this closure + | +LL | arc2().bar(); + | ++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/functions-closures/fn-item-type-cast.rs b/tests/ui/functions-closures/fn-item-type-cast.rs new file mode 100644 index 000000000..4d50ea97b --- /dev/null +++ b/tests/ui/functions-closures/fn-item-type-cast.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test explicit coercions from a fn item type to a fn pointer type. + + +fn foo(x: isize) -> isize { x * 2 } +fn bar(x: isize) -> isize { x * 4 } +type IntMap = fn(isize) -> isize; + +fn eq(x: T, y: T) { } + +static TEST: Option = Some(foo as IntMap); + +fn main() { + let f = foo as IntMap; + + let f = if true { foo as IntMap } else { bar as IntMap }; + assert_eq!(f(4), 8); + + eq(foo as IntMap, bar as IntMap); +} diff --git a/tests/ui/functions-closures/fn-item-type-coerce.rs b/tests/ui/functions-closures/fn-item-type-coerce.rs new file mode 100644 index 000000000..7a096764e --- /dev/null +++ b/tests/ui/functions-closures/fn-item-type-coerce.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_variables)] +// Test implicit coercions from a fn item type to a fn pointer type. + +// pretty-expanded FIXME #23616 + +fn foo(x: isize) -> isize { x * 2 } +fn bar(x: isize) -> isize { x * 4 } +type IntMap = fn(isize) -> isize; + +fn eq(x: T, y: T) { } + +fn main() { + let f: IntMap = foo; + + eq::(foo, bar); +} diff --git a/tests/ui/functions-closures/fn-item-type-zero-sized.rs b/tests/ui/functions-closures/fn-item-type-zero-sized.rs new file mode 100644 index 000000000..bd9f1ed66 --- /dev/null +++ b/tests/ui/functions-closures/fn-item-type-zero-sized.rs @@ -0,0 +1,13 @@ +// run-pass +// Test that fn item types are zero-sized. + +use std::mem::{size_of, size_of_val}; + +fn main() { + assert_eq!(size_of_val(&main), 0); + + let (a, b) = (size_of::, size_of::); + assert_eq!(size_of_val(&a), 0); + assert_eq!(size_of_val(&b), 0); + assert_eq!((a(), b()), (1, 2)); +} diff --git a/tests/ui/functions-closures/fn-lval.rs b/tests/ui/functions-closures/fn-lval.rs new file mode 100644 index 000000000..01079eea4 --- /dev/null +++ b/tests/ui/functions-closures/fn-lval.rs @@ -0,0 +1,11 @@ +// run-pass + + + +// pretty-expanded FIXME #23616 + +fn foo(_f: fn(isize) -> isize) { } + +fn id(x: isize) -> isize { return x; } + +pub fn main() { foo(id); } diff --git a/tests/ui/functions-closures/fn-type-infer.rs b/tests/ui/functions-closures/fn-type-infer.rs new file mode 100644 index 000000000..fe6567f22 --- /dev/null +++ b/tests/ui/functions-closures/fn-type-infer.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +pub fn main() { + // We should be able to type infer inside of ||s. + let _f = || { + let i = 10; + }; +} diff --git a/tests/ui/functions-closures/implied-bounds-closure-arg-outlives.rs b/tests/ui/functions-closures/implied-bounds-closure-arg-outlives.rs new file mode 100644 index 000000000..4ac07123d --- /dev/null +++ b/tests/ui/functions-closures/implied-bounds-closure-arg-outlives.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that we are able to handle the relationships between free +// regions bound in a closure callback. + +#[derive(Copy, Clone)] +struct MyCx<'short, 'long: 'short> { + short: &'short u32, + long: &'long u32, +} + +impl<'short, 'long> MyCx<'short, 'long> { + fn short(self) -> &'short u32 { self.short } + fn long(self) -> &'long u32 { self.long } + fn set_short(&mut self, v: &'short u32) { self.short = v; } +} + +fn with(op: F) -> R +where + F: for<'short, 'long> FnOnce(MyCx<'short, 'long>) -> R, +{ + op(MyCx { + short: &22, + long: &22, + }) +} + +fn main() { + with(|mut cx| { + // For this to type-check, we need to be able to deduce that + // the lifetime of `l` can be `'short`, even though it has + // input from `'long`. + let l = if true { cx.long() } else { cx.short() }; + cx.set_short(l); + }); +} diff --git a/tests/ui/functions-closures/nullable-pointer-opt-closures.rs b/tests/ui/functions-closures/nullable-pointer-opt-closures.rs new file mode 100644 index 000000000..87dacfba2 --- /dev/null +++ b/tests/ui/functions-closures/nullable-pointer-opt-closures.rs @@ -0,0 +1,34 @@ +// run-pass + +use std::mem; + +pub fn main() { + // By Ref Capture + let a = 10i32; + let b = Some(|| println!("{}", a)); + // When we capture by reference we can use any of the + // captures as the discriminant since they're all + // behind a pointer. + assert_eq!(mem::size_of_val(&b), mem::size_of::()); + + // By Value Capture + let a = Box::new(12i32); + let b = Some(move || println!("{}", a)); + // We captured `a` by value and since it's a `Box` we can use it + // as the discriminant. + assert_eq!(mem::size_of_val(&b), mem::size_of::>()); + + // By Value Capture - Transitive case + let a = "Hello".to_string(); // String -> Vec -> Unique -> NonZero + let b = Some(move || println!("{}", a)); + // We captured `a` by value and since down the chain it contains + // a `NonZero` field, we can use it as the discriminant. + assert_eq!(mem::size_of_val(&b), mem::size_of::()); + + // By Value - No Optimization + let a = 14i32; + let b = Some(move || println!("{}", a)); + // We captured `a` by value but we can't use it as the discriminant + // thus we end up with an extra field for the discriminant + assert_eq!(mem::size_of_val(&b), mem::size_of::<(i32, i32)>()); +} diff --git a/tests/ui/functions-closures/parallel-codegen-closures.rs b/tests/ui/functions-closures/parallel-codegen-closures.rs new file mode 100644 index 000000000..79759daba --- /dev/null +++ b/tests/ui/functions-closures/parallel-codegen-closures.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(stable_features)] + +// Tests parallel codegen - this can fail if the symbol for the anonymous +// closure in `sum` pollutes the second codegen unit from the first. + +// compile-flags: -C codegen_units=2 + +#![feature(iter_arith)] + +mod a { + fn foo() { + let x = ["a", "bob", "c"]; + let len: usize = x.iter().map(|s| s.len()).sum(); + } +} + +mod b { + fn bar() { + let x = ["a", "bob", "c"]; + let len: usize = x.iter().map(|s| s.len()).sum(); + } +} + +fn main() { +} diff --git a/tests/ui/functions-closures/return-from-closure.rs b/tests/ui/functions-closures/return-from-closure.rs new file mode 100644 index 000000000..656a95f12 --- /dev/null +++ b/tests/ui/functions-closures/return-from-closure.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(non_upper_case_globals)] +// just to make sure that `return` is only returning from the closure, +// not the surrounding function. + +static mut calls: usize = 0; + +fn surrounding() { + let return_works = |n: isize| { + unsafe { calls += 1 } + + if n >= 0 { return; } + panic!() + }; + + return_works(10); + return_works(20); + + let return_works_proc = |n: isize| { + unsafe { calls += 1 } + + if n >= 0 { return; } + panic!() + }; + + return_works_proc(10); +} + +pub fn main() { + surrounding(); + + assert_eq!(unsafe {calls}, 3); +} -- cgit v1.2.3