From d636a6590ce1429ff011e04bb0b4d393dc382226 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Thu, 24 Jul 2025 17:15:36 +0500 Subject: moved 35 tests to organized locations --- tests/ui/block-result/blocks-without-results.rs | 37 +++++ tests/ui/borrowck/refcell-borrow-comparison.rs | 7 + tests/ui/closures/fnonce-moved-twice.rs | 14 ++ tests/ui/closures/moved-upvar-mut-rebind.rs | 11 ++ tests/ui/collections/hashset-connected-border.rs | 49 ++++++ .../ui/const-generics/vec-macro-in-static-array.rs | 6 + tests/ui/extern/format-message-windows-ffi.rs | 39 +++++ tests/ui/fn/anonymous-parameters-trait.rs | 9 ++ tests/ui/imports/use-in-impl-scope.rs | 14 ++ tests/ui/issues/issue-11709.rs | 37 ----- tests/ui/issues/issue-11740.rs | 26 --- tests/ui/issues/issue-11771.rs | 11 -- tests/ui/issues/issue-11820.rs | 13 -- tests/ui/issues/issue-11844.rs | 8 - tests/ui/issues/issue-11869.rs | 16 -- tests/ui/issues/issue-11958.rs | 11 -- tests/ui/issues/issue-12033.rs | 7 - tests/ui/issues/issue-12041.rs | 13 -- tests/ui/issues/issue-12127.rs | 14 -- tests/ui/issues/issue-12285.rs | 14 -- tests/ui/issues/issue-12567.rs | 13 -- tests/ui/issues/issue-12677.rs | 9 -- tests/ui/issues/issue-12729.rs | 14 -- tests/ui/issues/issue-12744.rs | 5 - tests/ui/issues/issue-12860.rs | 49 ------ tests/ui/issues/issue-12863.rs | 8 - tests/ui/issues/issue-12909.rs | 19 --- tests/ui/issues/issue-12920.rs | 8 - tests/ui/issues/issue-13027.rs | 178 --------------------- tests/ui/issues/issue-13058.rs | 27 ---- tests/ui/issues/issue-13105.rs | 9 -- tests/ui/issues/issue-13167.rs | 24 --- tests/ui/issues/issue-13202.rs | 7 - tests/ui/issues/issue-13204.rs | 25 --- tests/ui/issues/issue-13214.rs | 22 --- tests/ui/issues/issue-13259-windows-tcb-trash.rs | 39 ----- tests/ui/issues/issue-13264.rs | 74 --------- tests/ui/issues/issue-13323.rs | 58 ------- tests/ui/issues/issue-13359.rs | 15 -- tests/ui/issues/issue-13405.rs | 19 --- tests/ui/issues/issue-13407.rs | 9 -- tests/ui/issues/issue-13434.rs | 21 --- tests/ui/issues/issue-13446.rs | 6 - tests/ui/issues/issue-13466.rs | 22 --- tests/ui/iterators/bytes-iterator-clone.rs | 9 ++ tests/ui/iterators/phf-map-entries-iterator.rs | 24 +++ .../ui/lifetimes/iterator-trait-lifetime-error.rs | 27 ++++ .../lifetimes/struct-lifetime-field-assignment.rs | 19 +++ tests/ui/match/function-in-pattern-error.rs | 8 + tests/ui/match/guard-literal-range-shadow.rs | 178 +++++++++++++++++++++ tests/ui/match/option-result-mismatch.rs | 8 + .../ui/match/option-result-type-param-mismatch.rs | 22 +++ tests/ui/match/slice-move-out-error.rs | 13 ++ tests/ui/match/string-literal-match-patterns.rs | 16 ++ tests/ui/match/struct-reference-patterns.rs | 14 ++ tests/ui/panics/explicit-panic-unreachable.rs | 8 + tests/ui/panics/unwrap-or-panic-input.rs | 7 + tests/ui/privacy/private-unit-struct-assignment.rs | 9 ++ tests/ui/statics/enum-with-static-str-variant.rs | 22 +++ tests/ui/threads/moved-value-in-thread-loop.rs | 13 ++ tests/ui/traits/any-trait-object-debug.rs | 5 + tests/ui/traits/default-method-lifetime-params.rs | 25 +++ tests/ui/traits/deref-chain-method-calls.rs | 74 +++++++++ tests/ui/traits/fnonce-repro-trait-impl.rs | 21 +++ tests/ui/traits/matcher-trait-equality.rs | 58 +++++++ tests/ui/traits/reference-clone-noclone.rs | 13 ++ .../type-inference/isize-usize-mismatch-error.rs | 15 ++ tests/ui/type-inference/type-collect-inference.rs | 19 +++ tests/ui/type-inference/unit-type-add-error.rs | 11 ++ tests/ui/unsafe/unsafe-transmute-in-find.rs | 26 +++ 70 files changed, 850 insertions(+), 850 deletions(-) create mode 100644 tests/ui/block-result/blocks-without-results.rs create mode 100644 tests/ui/borrowck/refcell-borrow-comparison.rs create mode 100644 tests/ui/closures/fnonce-moved-twice.rs create mode 100644 tests/ui/closures/moved-upvar-mut-rebind.rs create mode 100644 tests/ui/collections/hashset-connected-border.rs create mode 100644 tests/ui/const-generics/vec-macro-in-static-array.rs create mode 100644 tests/ui/extern/format-message-windows-ffi.rs create mode 100644 tests/ui/fn/anonymous-parameters-trait.rs create mode 100644 tests/ui/imports/use-in-impl-scope.rs delete mode 100644 tests/ui/issues/issue-11709.rs delete mode 100644 tests/ui/issues/issue-11740.rs delete mode 100644 tests/ui/issues/issue-11771.rs delete mode 100644 tests/ui/issues/issue-11820.rs delete mode 100644 tests/ui/issues/issue-11844.rs delete mode 100644 tests/ui/issues/issue-11869.rs delete mode 100644 tests/ui/issues/issue-11958.rs delete mode 100644 tests/ui/issues/issue-12033.rs delete mode 100644 tests/ui/issues/issue-12041.rs delete mode 100644 tests/ui/issues/issue-12127.rs delete mode 100644 tests/ui/issues/issue-12285.rs delete mode 100644 tests/ui/issues/issue-12567.rs delete mode 100644 tests/ui/issues/issue-12677.rs delete mode 100644 tests/ui/issues/issue-12729.rs delete mode 100644 tests/ui/issues/issue-12744.rs delete mode 100644 tests/ui/issues/issue-12860.rs delete mode 100644 tests/ui/issues/issue-12863.rs delete mode 100644 tests/ui/issues/issue-12909.rs delete mode 100644 tests/ui/issues/issue-12920.rs delete mode 100644 tests/ui/issues/issue-13027.rs delete mode 100644 tests/ui/issues/issue-13058.rs delete mode 100644 tests/ui/issues/issue-13105.rs delete mode 100644 tests/ui/issues/issue-13167.rs delete mode 100644 tests/ui/issues/issue-13202.rs delete mode 100644 tests/ui/issues/issue-13204.rs delete mode 100644 tests/ui/issues/issue-13214.rs delete mode 100644 tests/ui/issues/issue-13259-windows-tcb-trash.rs delete mode 100644 tests/ui/issues/issue-13264.rs delete mode 100644 tests/ui/issues/issue-13323.rs delete mode 100644 tests/ui/issues/issue-13359.rs delete mode 100644 tests/ui/issues/issue-13405.rs delete mode 100644 tests/ui/issues/issue-13407.rs delete mode 100644 tests/ui/issues/issue-13434.rs delete mode 100644 tests/ui/issues/issue-13446.rs delete mode 100644 tests/ui/issues/issue-13466.rs create mode 100644 tests/ui/iterators/bytes-iterator-clone.rs create mode 100644 tests/ui/iterators/phf-map-entries-iterator.rs create mode 100644 tests/ui/lifetimes/iterator-trait-lifetime-error.rs create mode 100644 tests/ui/lifetimes/struct-lifetime-field-assignment.rs create mode 100644 tests/ui/match/function-in-pattern-error.rs create mode 100644 tests/ui/match/guard-literal-range-shadow.rs create mode 100644 tests/ui/match/option-result-mismatch.rs create mode 100644 tests/ui/match/option-result-type-param-mismatch.rs create mode 100644 tests/ui/match/slice-move-out-error.rs create mode 100644 tests/ui/match/string-literal-match-patterns.rs create mode 100644 tests/ui/match/struct-reference-patterns.rs create mode 100644 tests/ui/panics/explicit-panic-unreachable.rs create mode 100644 tests/ui/panics/unwrap-or-panic-input.rs create mode 100644 tests/ui/privacy/private-unit-struct-assignment.rs create mode 100644 tests/ui/statics/enum-with-static-str-variant.rs create mode 100644 tests/ui/threads/moved-value-in-thread-loop.rs create mode 100644 tests/ui/traits/any-trait-object-debug.rs create mode 100644 tests/ui/traits/default-method-lifetime-params.rs create mode 100644 tests/ui/traits/deref-chain-method-calls.rs create mode 100644 tests/ui/traits/fnonce-repro-trait-impl.rs create mode 100644 tests/ui/traits/matcher-trait-equality.rs create mode 100644 tests/ui/traits/reference-clone-noclone.rs create mode 100644 tests/ui/type-inference/isize-usize-mismatch-error.rs create mode 100644 tests/ui/type-inference/type-collect-inference.rs create mode 100644 tests/ui/type-inference/unit-type-add-error.rs create mode 100644 tests/ui/unsafe/unsafe-transmute-in-find.rs (limited to 'tests/ui') diff --git a/tests/ui/block-result/blocks-without-results.rs b/tests/ui/block-result/blocks-without-results.rs new file mode 100644 index 00000000000..8a11074eca8 --- /dev/null +++ b/tests/ui/block-result/blocks-without-results.rs @@ -0,0 +1,37 @@ +//@ run-pass +#![allow(dead_code)] + +// Don't panic on blocks without results +// There are several tests in this run-pass that raised +// when this bug was opened. The cases where the compiler +// panics before the fix have a comment. + +struct S {x:()} + +fn test(slot: &mut Option Box>>) -> () { + let a = slot.take(); + let _a: () = match a { + // `{let .. a(); }` would break + Some(mut a) => { let _a = a(); }, + None => (), + }; +} + +fn not(b: bool) -> bool { + if b { + !b + } else { + // `panic!(...)` would break + panic!("Break the compiler"); + } +} + +pub fn main() { + // {} would break + let _r: () = {}; + let mut slot = None; + // `{ test(...); }` would break + let _s : S = S{ x: { test(&mut slot); } }; + + let _b = not(true); +} diff --git a/tests/ui/borrowck/refcell-borrow-comparison.rs b/tests/ui/borrowck/refcell-borrow-comparison.rs new file mode 100644 index 00000000000..0bf6490bafe --- /dev/null +++ b/tests/ui/borrowck/refcell-borrow-comparison.rs @@ -0,0 +1,7 @@ +//@ run-pass +use std::cell::RefCell; + +fn main() { + let x = RefCell::new(0); + if *x.borrow() == 0 {} else {} +} diff --git a/tests/ui/closures/fnonce-moved-twice.rs b/tests/ui/closures/fnonce-moved-twice.rs new file mode 100644 index 00000000000..199d542e816 --- /dev/null +++ b/tests/ui/closures/fnonce-moved-twice.rs @@ -0,0 +1,14 @@ +#![feature(unboxed_closures, tuple_trait)] + +fn to_fn_once>(f: F) -> F { f } +fn do_it(x: &isize) { } + +fn main() { + let x: Box<_> = Box::new(22); + let f = to_fn_once(move|| do_it(&*x)); + to_fn_once(move|| { + f(); + f(); + //~^ ERROR: use of moved value: `f` + })() +} diff --git a/tests/ui/closures/moved-upvar-mut-rebind.rs b/tests/ui/closures/moved-upvar-mut-rebind.rs new file mode 100644 index 00000000000..9185c5158af --- /dev/null +++ b/tests/ui/closures/moved-upvar-mut-rebind.rs @@ -0,0 +1,11 @@ +//@ run-pass + +// We shouldn't need to rebind a moved upvar as mut if it's already +// marked as mut + +pub fn main() { + let mut x = 1; + let _thunk = Box::new(move|| { x = 2; }); + //~^ WARN value assigned to `x` is never read + //~| WARN unused variable: `x` +} diff --git a/tests/ui/collections/hashset-connected-border.rs b/tests/ui/collections/hashset-connected-border.rs new file mode 100644 index 00000000000..255f6670793 --- /dev/null +++ b/tests/ui/collections/hashset-connected-border.rs @@ -0,0 +1,49 @@ +//@ run-pass +use std::collections::HashSet; + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +struct XYZ { + x: isize, + y: isize, + z: isize +} + +fn main() { + let mut connected = HashSet::new(); + let mut border = HashSet::new(); + + let middle = XYZ{x: 0, y: 0, z: 0}; + border.insert(middle); + + while !border.is_empty() && connected.len() < 10000 { + let choice = *(border.iter().next().unwrap()); + border.remove(&choice); + connected.insert(choice); + + let cxp = XYZ{x: choice.x + 1, y: choice.y, z: choice.z}; + let cxm = XYZ{x: choice.x - 1, y: choice.y, z: choice.z}; + let cyp = XYZ{x: choice.x, y: choice.y + 1, z: choice.z}; + let cym = XYZ{x: choice.x, y: choice.y - 1, z: choice.z}; + let czp = XYZ{x: choice.x, y: choice.y, z: choice.z + 1}; + let czm = XYZ{x: choice.x, y: choice.y, z: choice.z - 1}; + + if !connected.contains(&cxp) { + border.insert(cxp); + } + if !connected.contains(&cxm){ + border.insert(cxm); + } + if !connected.contains(&cyp){ + border.insert(cyp); + } + if !connected.contains(&cym) { + border.insert(cym); + } + if !connected.contains(&czp){ + border.insert(czp); + } + if !connected.contains(&czm) { + border.insert(czm); + } + } +} diff --git a/tests/ui/const-generics/vec-macro-in-static-array.rs b/tests/ui/const-generics/vec-macro-in-static-array.rs new file mode 100644 index 00000000000..9f1fc42774f --- /dev/null +++ b/tests/ui/const-generics/vec-macro-in-static-array.rs @@ -0,0 +1,6 @@ +// Used to cause ICE + +static VEC: [u32; 256] = vec![]; +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/extern/format-message-windows-ffi.rs b/tests/ui/extern/format-message-windows-ffi.rs new file mode 100644 index 00000000000..381e3f15259 --- /dev/null +++ b/tests/ui/extern/format-message-windows-ffi.rs @@ -0,0 +1,39 @@ +//@ run-pass + +#[cfg(windows)] +mod imp { + type LPVOID = *mut u8; + type DWORD = u32; + type LPWSTR = *mut u16; + + extern "system" { + fn FormatMessageW(flags: DWORD, + lpSrc: LPVOID, + msgId: DWORD, + langId: DWORD, + buf: LPWSTR, + nsize: DWORD, + args: *const u8) + -> DWORD; + } + + pub fn test() { + let mut buf: [u16; 50] = [0; 50]; + let ret = unsafe { + FormatMessageW(0x1000, core::ptr::null_mut(), 1, 0x400, + buf.as_mut_ptr(), buf.len() as u32, core::ptr::null()) + }; + // On some 32-bit Windowses (Win7-8 at least) this will panic with segmented + // stacks taking control of pvArbitrary + assert!(ret != 0); + } +} + +#[cfg(not(windows))] +mod imp { + pub fn test() { } +} + +fn main() { + imp::test() +} diff --git a/tests/ui/fn/anonymous-parameters-trait.rs b/tests/ui/fn/anonymous-parameters-trait.rs new file mode 100644 index 00000000000..d119aa9c788 --- /dev/null +++ b/tests/ui/fn/anonymous-parameters-trait.rs @@ -0,0 +1,9 @@ +//@ edition: 2015 +//@ check-pass + +trait Foo { + #[allow(anonymous_parameters)] + fn quux(u8) {} +} + +fn main() {} diff --git a/tests/ui/imports/use-in-impl-scope.rs b/tests/ui/imports/use-in-impl-scope.rs new file mode 100644 index 00000000000..4d45846bc60 --- /dev/null +++ b/tests/ui/imports/use-in-impl-scope.rs @@ -0,0 +1,14 @@ +//@ edition: 2015 +//@ check-pass +#![allow(dead_code)] + +pub struct Foo; + +mod bar { + use Foo; + + impl Foo { + fn baz(&self) {} + } +} +fn main() {} diff --git a/tests/ui/issues/issue-11709.rs b/tests/ui/issues/issue-11709.rs deleted file mode 100644 index 8a11074eca8..00000000000 --- a/tests/ui/issues/issue-11709.rs +++ /dev/null @@ -1,37 +0,0 @@ -//@ run-pass -#![allow(dead_code)] - -// Don't panic on blocks without results -// There are several tests in this run-pass that raised -// when this bug was opened. The cases where the compiler -// panics before the fix have a comment. - -struct S {x:()} - -fn test(slot: &mut Option Box>>) -> () { - let a = slot.take(); - let _a: () = match a { - // `{let .. a(); }` would break - Some(mut a) => { let _a = a(); }, - None => (), - }; -} - -fn not(b: bool) -> bool { - if b { - !b - } else { - // `panic!(...)` would break - panic!("Break the compiler"); - } -} - -pub fn main() { - // {} would break - let _r: () = {}; - let mut slot = None; - // `{ test(...); }` would break - let _s : S = S{ x: { test(&mut slot); } }; - - let _b = not(true); -} diff --git a/tests/ui/issues/issue-11740.rs b/tests/ui/issues/issue-11740.rs deleted file mode 100644 index c6099c2a0c0..00000000000 --- a/tests/ui/issues/issue-11740.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ check-pass - -struct Attr { - name: String, - value: String, -} - -struct Element { - attrs: Vec>, -} - -impl Element { - pub unsafe fn get_attr<'a>(&'a self, name: &str) { - self.attrs - .iter() - .find(|attr| { - let attr: &&Box = std::mem::transmute(attr); - true - }); - } -} - -fn main() { - let element = Element { attrs: Vec::new() }; - unsafe { let () = element.get_attr("foo"); }; -} diff --git a/tests/ui/issues/issue-11771.rs b/tests/ui/issues/issue-11771.rs deleted file mode 100644 index c69cd1e79e3..00000000000 --- a/tests/ui/issues/issue-11771.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - let x = (); - 1 + - x //~^ ERROR E0277 - ; - - let x: () = (); - 1 + - x //~^ ERROR E0277 - ; -} diff --git a/tests/ui/issues/issue-11820.rs b/tests/ui/issues/issue-11820.rs deleted file mode 100644 index ada844f8ee1..00000000000 --- a/tests/ui/issues/issue-11820.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ run-pass - -#![allow(noop_method_call)] - -struct NoClone; - -fn main() { - let rnc = &NoClone; - let rsnc = &Some(NoClone); - - let _: &NoClone = rnc.clone(); - let _: &Option = rsnc.clone(); -} diff --git a/tests/ui/issues/issue-11844.rs b/tests/ui/issues/issue-11844.rs deleted file mode 100644 index f974a470296..00000000000 --- a/tests/ui/issues/issue-11844.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn main() { - let a = Some(Box::new(1)); - match a { - Ok(a) => //~ ERROR: mismatched types - println!("{}",a), - None => panic!() - } -} diff --git a/tests/ui/issues/issue-11869.rs b/tests/ui/issues/issue-11869.rs deleted file mode 100644 index dd752227bbe..00000000000 --- a/tests/ui/issues/issue-11869.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ check-pass -#![allow(dead_code)] - -struct A { - a: String -} - -fn borrow<'a>(binding: &'a A) -> &'a str { - match &*binding.a { - "in" => "in_", - "ref" => "ref_", - ident => ident - } -} - -fn main() {} diff --git a/tests/ui/issues/issue-11958.rs b/tests/ui/issues/issue-11958.rs deleted file mode 100644 index 9185c5158af..00000000000 --- a/tests/ui/issues/issue-11958.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass - -// We shouldn't need to rebind a moved upvar as mut if it's already -// marked as mut - -pub fn main() { - let mut x = 1; - let _thunk = Box::new(move|| { x = 2; }); - //~^ WARN value assigned to `x` is never read - //~| WARN unused variable: `x` -} diff --git a/tests/ui/issues/issue-12033.rs b/tests/ui/issues/issue-12033.rs deleted file mode 100644 index 0bf6490bafe..00000000000 --- a/tests/ui/issues/issue-12033.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -use std::cell::RefCell; - -fn main() { - let x = RefCell::new(0); - if *x.borrow() == 0 {} else {} -} diff --git a/tests/ui/issues/issue-12041.rs b/tests/ui/issues/issue-12041.rs deleted file mode 100644 index 091e8fe8b2a..00000000000 --- a/tests/ui/issues/issue-12041.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::sync::mpsc::channel; -use std::thread; - -fn main() { - let (tx, rx) = channel(); - let _t = thread::spawn(move|| -> () { - loop { - let tx = tx; - //~^ ERROR: use of moved value: `tx` - tx.send(1); - } - }); -} diff --git a/tests/ui/issues/issue-12127.rs b/tests/ui/issues/issue-12127.rs deleted file mode 100644 index 199d542e816..00000000000 --- a/tests/ui/issues/issue-12127.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(unboxed_closures, tuple_trait)] - -fn to_fn_once>(f: F) -> F { f } -fn do_it(x: &isize) { } - -fn main() { - let x: Box<_> = Box::new(22); - let f = to_fn_once(move|| do_it(&*x)); - to_fn_once(move|| { - f(); - f(); - //~^ ERROR: use of moved value: `f` - })() -} diff --git a/tests/ui/issues/issue-12285.rs b/tests/ui/issues/issue-12285.rs deleted file mode 100644 index fe199147128..00000000000 --- a/tests/ui/issues/issue-12285.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass - -struct S; - -fn main() { - match Some(&S) { - Some(&S) => {}, - _x => unreachable!() - } - match Some(&S) { - Some(&S) => {}, - None => unreachable!() - } -} diff --git a/tests/ui/issues/issue-12567.rs b/tests/ui/issues/issue-12567.rs deleted file mode 100644 index 1b2a37de475..00000000000 --- a/tests/ui/issues/issue-12567.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) { - match (l1, l2) { - //~^ ERROR: cannot move out of type `[T]`, a non-copy slice - //~| ERROR: cannot move out of type `[T]`, a non-copy slice - (&[], &[]) => println!("both empty"), - (&[], &[hd, ..]) | (&[hd, ..], &[]) - => println!("one empty"), - (&[hd1, ..], &[hd2, ..]) - => println!("both nonempty"), - } -} - -fn main() {} diff --git a/tests/ui/issues/issue-12677.rs b/tests/ui/issues/issue-12677.rs deleted file mode 100644 index dbc2dbc8527..00000000000 --- a/tests/ui/issues/issue-12677.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass - -fn main() { - let s = "Hello"; - let first = s.bytes(); - let second = first.clone(); - - assert_eq!(first.collect::>(), second.collect::>()) -} diff --git a/tests/ui/issues/issue-12729.rs b/tests/ui/issues/issue-12729.rs deleted file mode 100644 index 4d45846bc60..00000000000 --- a/tests/ui/issues/issue-12729.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ edition: 2015 -//@ check-pass -#![allow(dead_code)] - -pub struct Foo; - -mod bar { - use Foo; - - impl Foo { - fn baz(&self) {} - } -} -fn main() {} diff --git a/tests/ui/issues/issue-12744.rs b/tests/ui/issues/issue-12744.rs deleted file mode 100644 index eaf92d413d5..00000000000 --- a/tests/ui/issues/issue-12744.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-pass -fn main() { - fn test() -> Box { Box::new(1) } - println!("{:?}", test()) -} diff --git a/tests/ui/issues/issue-12860.rs b/tests/ui/issues/issue-12860.rs deleted file mode 100644 index 255f6670793..00000000000 --- a/tests/ui/issues/issue-12860.rs +++ /dev/null @@ -1,49 +0,0 @@ -//@ run-pass -use std::collections::HashSet; - -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -struct XYZ { - x: isize, - y: isize, - z: isize -} - -fn main() { - let mut connected = HashSet::new(); - let mut border = HashSet::new(); - - let middle = XYZ{x: 0, y: 0, z: 0}; - border.insert(middle); - - while !border.is_empty() && connected.len() < 10000 { - let choice = *(border.iter().next().unwrap()); - border.remove(&choice); - connected.insert(choice); - - let cxp = XYZ{x: choice.x + 1, y: choice.y, z: choice.z}; - let cxm = XYZ{x: choice.x - 1, y: choice.y, z: choice.z}; - let cyp = XYZ{x: choice.x, y: choice.y + 1, z: choice.z}; - let cym = XYZ{x: choice.x, y: choice.y - 1, z: choice.z}; - let czp = XYZ{x: choice.x, y: choice.y, z: choice.z + 1}; - let czm = XYZ{x: choice.x, y: choice.y, z: choice.z - 1}; - - if !connected.contains(&cxp) { - border.insert(cxp); - } - if !connected.contains(&cxm){ - border.insert(cxm); - } - if !connected.contains(&cyp){ - border.insert(cyp); - } - if !connected.contains(&cym) { - border.insert(cym); - } - if !connected.contains(&czp){ - border.insert(czp); - } - if !connected.contains(&czm) { - border.insert(czm); - } - } -} diff --git a/tests/ui/issues/issue-12863.rs b/tests/ui/issues/issue-12863.rs deleted file mode 100644 index 1ac1c3d818e..00000000000 --- a/tests/ui/issues/issue-12863.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod foo { pub fn bar() {} } - -fn main() { - match () { - foo::bar => {} - //~^ ERROR expected unit struct, unit variant or constant, found function `foo::bar` - } -} diff --git a/tests/ui/issues/issue-12909.rs b/tests/ui/issues/issue-12909.rs deleted file mode 100644 index f2c33806aae..00000000000 --- a/tests/ui/issues/issue-12909.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ run-pass -#![allow(unused_variables)] - -use std::collections::HashMap; - -fn copy(&x: &T) -> T { - x -} - -fn main() { - let arr = [(1, 1), (2, 2), (3, 3)]; - - let v1: Vec<&_> = arr.iter().collect(); - let v2: Vec<_> = arr.iter().map(copy).collect(); - - let m1: HashMap<_, _> = arr.iter().map(copy).collect(); - let m2: HashMap = arr.iter().map(copy).collect(); - let m3: HashMap<_, usize> = arr.iter().map(copy).collect(); -} diff --git a/tests/ui/issues/issue-12920.rs b/tests/ui/issues/issue-12920.rs deleted file mode 100644 index f3b1b643c45..00000000000 --- a/tests/ui/issues/issue-12920.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-fail -//@ error-pattern:explicit panic -//@ needs-subprocess - -pub fn main() { - panic!(); - println!("{}", 1); -} diff --git a/tests/ui/issues/issue-13027.rs b/tests/ui/issues/issue-13027.rs deleted file mode 100644 index fbd1d75067b..00000000000 --- a/tests/ui/issues/issue-13027.rs +++ /dev/null @@ -1,178 +0,0 @@ -//@ run-pass - -// Tests that match expression handles overlapped literal and range -// properly in the presence of guard function. - -fn val() -> usize { 1 } - -static CONST: usize = 1; - -pub fn main() { - lit_shadow_range(); - range_shadow_lit(); - range_shadow_range(); - multi_pats_shadow_lit(); - multi_pats_shadow_range(); - lit_shadow_multi_pats(); - range_shadow_multi_pats(); - misc(); -} - -fn lit_shadow_range() { - assert_eq!(2, match 1 { - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); - - let x = 0; - assert_eq!(2, match x+1 { - 0 => 0, - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); - - assert_eq!(2, match val() { - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); - - assert_eq!(2, match CONST { - 0 => 0, - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); - - // value is out of the range of second arm, should match wildcard pattern - assert_eq!(3, match 3 { - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); -} - -fn range_shadow_lit() { - assert_eq!(2, match 1 { - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); - - let x = 0; - assert_eq!(2, match x+1 { - 0 => 0, - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); - - assert_eq!(2, match val() { - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); - - assert_eq!(2, match CONST { - 0 => 0, - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); - - // ditto - assert_eq!(3, match 3 { - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); -} - -fn range_shadow_range() { - assert_eq!(2, match 1 { - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); - - let x = 0; - assert_eq!(2, match x+1 { - 100 => 0, - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); - - assert_eq!(2, match val() { - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); - - assert_eq!(2, match CONST { - 100 => 0, - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); - - // ditto - assert_eq!(3, match 5 { - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); -} - -fn multi_pats_shadow_lit() { - assert_eq!(2, match 1 { - 100 => 0, - 0 | 1..=10 if false => 1, - 1 => 2, - _ => 3, - }); -} - -fn multi_pats_shadow_range() { - assert_eq!(2, match 1 { - 100 => 0, - 0 | 1..=10 if false => 1, - 1..=3 => 2, - _ => 3, - }); -} - -fn lit_shadow_multi_pats() { - assert_eq!(2, match 1 { - 100 => 0, - 1 if false => 1, - 0 | 1..=10 => 2, - _ => 3, - }); -} - -fn range_shadow_multi_pats() { - assert_eq!(2, match 1 { - 100 => 0, - 1..=3 if false => 1, - 0 | 1..=10 => 2, - _ => 3, - }); -} - -fn misc() { - enum Foo { - Bar(#[allow(dead_code)] usize, bool) - } - // This test basically mimics how trace_macros! macro is implemented, - // which is a rare combination of vector patterns, multiple wild-card - // patterns and guard functions. - let r = match [Foo::Bar(0, false)] { - [Foo::Bar(_, pred)] if pred => 1, - [Foo::Bar(_, pred)] if !pred => 2, - _ => 0, - }; - assert_eq!(2, r); -} diff --git a/tests/ui/issues/issue-13058.rs b/tests/ui/issues/issue-13058.rs deleted file mode 100644 index a5806feb720..00000000000 --- a/tests/ui/issues/issue-13058.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::ops::Range; - -trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } - -impl<'r> Itble<'r, usize, Range> for (usize, usize) { - fn iter(&'r self) -> Range { - let &(min, max) = self; - min..max - } -} - -fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool -{ - let cont_iter = cont.iter(); -//~^ ERROR explicit lifetime required in the type of `cont` [E0621] - let result = cont_iter.fold(Some(0), |state, val| { - state.map_or(None, |mask| { - let bit = 1 << val; - if mask & bit == 0 {Some(mask|bit)} else {None} - }) - }); - result.is_some() -} - -fn main() { - check(&(3, 5)); -} diff --git a/tests/ui/issues/issue-13105.rs b/tests/ui/issues/issue-13105.rs deleted file mode 100644 index d119aa9c788..00000000000 --- a/tests/ui/issues/issue-13105.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ edition: 2015 -//@ check-pass - -trait Foo { - #[allow(anonymous_parameters)] - fn quux(u8) {} -} - -fn main() {} diff --git a/tests/ui/issues/issue-13167.rs b/tests/ui/issues/issue-13167.rs deleted file mode 100644 index 5f733e85948..00000000000 --- a/tests/ui/issues/issue-13167.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ check-pass -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver - -use std::slice; - -pub struct PhfMapEntries<'a, T: 'a> { - iter: slice::Iter<'a, (&'static str, T)>, -} - -impl<'a, T> Iterator for PhfMapEntries<'a, T> { - type Item = (&'static str, &'a T); - - fn next(&mut self) -> Option<(&'static str, &'a T)> { - self.iter.by_ref().map(|&(key, ref value)| (key, value)).next() - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -fn main() {} diff --git a/tests/ui/issues/issue-13202.rs b/tests/ui/issues/issue-13202.rs deleted file mode 100644 index 99ffba3fba5..00000000000 --- a/tests/ui/issues/issue-13202.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-fail -//@ error-pattern:bad input -//@ needs-subprocess - -fn main() { - Some("foo").unwrap_or(panic!("bad input")).to_string(); -} diff --git a/tests/ui/issues/issue-13204.rs b/tests/ui/issues/issue-13204.rs deleted file mode 100644 index 01362f6fe61..00000000000 --- a/tests/ui/issues/issue-13204.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ run-pass -#![allow(unused_mut)] -// Test that when instantiating trait default methods, typeck handles -// lifetime parameters defined on the method bound correctly. - - -pub trait Foo { - fn bar<'a, I: Iterator>(&self, it: I) -> usize { - let mut xs = it.filter(|_| true); - xs.count() - } -} - -pub struct Baz; - -impl Foo for Baz { - // When instantiating `Foo::bar` for `Baz` here, typeck used to - // ICE due to the lifetime parameter of `bar`. -} - -fn main() { - let x = Baz; - let y = vec![(), (), ()]; - assert_eq!(x.bar(y.iter()), 3); -} diff --git a/tests/ui/issues/issue-13214.rs b/tests/ui/issues/issue-13214.rs deleted file mode 100644 index 8140ec943a0..00000000000 --- a/tests/ui/issues/issue-13214.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ build-pass -#![allow(dead_code)] -// defining static with struct that contains enum -// with &'static str variant used to cause ICE - - -pub enum Foo { - Bar, - Baz(&'static str), -} - -pub static TEST: Test = Test { - foo: Foo::Bar, - c: 'a' -}; - -pub struct Test { - foo: Foo, - c: char, -} - -fn main() {} diff --git a/tests/ui/issues/issue-13259-windows-tcb-trash.rs b/tests/ui/issues/issue-13259-windows-tcb-trash.rs deleted file mode 100644 index 381e3f15259..00000000000 --- a/tests/ui/issues/issue-13259-windows-tcb-trash.rs +++ /dev/null @@ -1,39 +0,0 @@ -//@ run-pass - -#[cfg(windows)] -mod imp { - type LPVOID = *mut u8; - type DWORD = u32; - type LPWSTR = *mut u16; - - extern "system" { - fn FormatMessageW(flags: DWORD, - lpSrc: LPVOID, - msgId: DWORD, - langId: DWORD, - buf: LPWSTR, - nsize: DWORD, - args: *const u8) - -> DWORD; - } - - pub fn test() { - let mut buf: [u16; 50] = [0; 50]; - let ret = unsafe { - FormatMessageW(0x1000, core::ptr::null_mut(), 1, 0x400, - buf.as_mut_ptr(), buf.len() as u32, core::ptr::null()) - }; - // On some 32-bit Windowses (Win7-8 at least) this will panic with segmented - // stacks taking control of pvArbitrary - assert!(ret != 0); - } -} - -#[cfg(not(windows))] -mod imp { - pub fn test() { } -} - -fn main() { - imp::test() -} diff --git a/tests/ui/issues/issue-13264.rs b/tests/ui/issues/issue-13264.rs deleted file mode 100644 index bf4ec388c4f..00000000000 --- a/tests/ui/issues/issue-13264.rs +++ /dev/null @@ -1,74 +0,0 @@ -//@ run-pass -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -use std::ops::Deref; - -struct Root { - jsref: JSRef -} - -impl Deref for Root { - type Target = JSRef; - - fn deref<'a>(&'a self) -> &'a JSRef { - &self.jsref - } -} - -#[derive(Copy, Clone)] -struct JSRef { - node: *const Node -} - -impl Deref for JSRef { - type Target = Node; - - fn deref<'a>(&'a self) -> &'a Node { - self.get() - } -} - -trait INode { - fn RemoveChild(&self); -} - -impl INode for JSRef { - fn RemoveChild(&self) { - self.get().RemoveChild(0) - } -} - -impl JSRef { - fn AddChild(&self) { - self.get().AddChild(0); - } - - fn get<'a>(&'a self) -> &'a Node { - unsafe { - &*self.node - } - } -} - -struct Node; - -impl Node { - fn RemoveChild(&self, _a: usize) { - } - - fn AddChild(&self, _a: usize) { - } -} - -fn main() { - let n = Node; - let jsref = JSRef { node: &n }; - let root = Root { jsref: jsref }; - - root.AddChild(); - jsref.AddChild(); - - root.RemoveChild(); - jsref.RemoveChild(); -} diff --git a/tests/ui/issues/issue-13323.rs b/tests/ui/issues/issue-13323.rs deleted file mode 100644 index 8f334404f9a..00000000000 --- a/tests/ui/issues/issue-13323.rs +++ /dev/null @@ -1,58 +0,0 @@ -//@ run-pass - -struct StrWrap { - s: String -} - -impl StrWrap { - fn new(s: &str) -> StrWrap { - StrWrap { s: s.to_string() } - } - - fn get_s<'a>(&'a self) -> &'a str { - &self.s - } -} - -struct MyStruct { - s: StrWrap -} - -impl MyStruct { - fn new(s: &str) -> MyStruct { - MyStruct { s: StrWrap::new(s) } - } - - fn get_str_wrap<'a>(&'a self) -> &'a StrWrap { - &self.s - } -} - -trait Matcher { - fn matches(&self, actual: T) -> bool; -} - -fn assert_that>(actual: T, matcher: &U) { - assert!(matcher.matches(actual)); -} - -struct EqualTo { - expected: T -} - -impl Matcher for EqualTo { - fn matches(&self, actual: T) -> bool { - self.expected.eq(&actual) - } -} - -fn equal_to(expected: T) -> Box> { - Box::new(EqualTo { expected: expected }) -} - -pub fn main() { - let my_struct = MyStruct::new("zomg"); - let s = my_struct.get_str_wrap(); - - assert_that(s.get_s(), &*equal_to("zomg")); -} diff --git a/tests/ui/issues/issue-13359.rs b/tests/ui/issues/issue-13359.rs deleted file mode 100644 index 5d31d7f861c..00000000000 --- a/tests/ui/issues/issue-13359.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ dont-require-annotations: NOTE - -fn foo(_s: i16) { } - -fn bar(_s: u32) { } - -fn main() { - foo(1*(1 as isize)); - //~^ ERROR mismatched types - //~| NOTE expected `i16`, found `isize` - - bar(1*(1 as usize)); - //~^ ERROR mismatched types - //~| NOTE expected `u32`, found `usize` -} diff --git a/tests/ui/issues/issue-13405.rs b/tests/ui/issues/issue-13405.rs deleted file mode 100644 index 80b298d2f37..00000000000 --- a/tests/ui/issues/issue-13405.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ check-pass -#![allow(dead_code)] -#![allow(unused_variables)] - -struct Foo<'a> { - i: &'a bool, - j: Option<&'a isize>, -} - -impl<'a> Foo<'a> { - fn bar(&mut self, j: &isize) { - let child = Foo { - i: self.i, - j: Some(j) - }; - } -} - -fn main() {} diff --git a/tests/ui/issues/issue-13407.rs b/tests/ui/issues/issue-13407.rs deleted file mode 100644 index 7794be37b85..00000000000 --- a/tests/ui/issues/issue-13407.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod A { - struct C; -} - -fn main() { - A::C = 1; - //~^ ERROR: mismatched types - //~| ERROR: unit struct `C` is private -} diff --git a/tests/ui/issues/issue-13434.rs b/tests/ui/issues/issue-13434.rs deleted file mode 100644 index caf7b632393..00000000000 --- a/tests/ui/issues/issue-13434.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ run-pass -#[derive(Debug)] -struct MyStruct; - -trait Repro { - fn repro(self, s: MyStruct) -> String; -} - -impl Repro for F where F: FnOnce(MyStruct) -> String { - fn repro(self, s: MyStruct) -> String { - self(s) - } -} - -fn do_stuff(r: R) -> String { - r.repro(MyStruct) -} - -pub fn main() { - assert_eq!("MyStruct".to_string(), do_stuff(|s: MyStruct| format!("{:?}", s))); -} diff --git a/tests/ui/issues/issue-13446.rs b/tests/ui/issues/issue-13446.rs deleted file mode 100644 index 9f1fc42774f..00000000000 --- a/tests/ui/issues/issue-13446.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Used to cause ICE - -static VEC: [u32; 256] = vec![]; -//~^ ERROR mismatched types - -fn main() {} diff --git a/tests/ui/issues/issue-13466.rs b/tests/ui/issues/issue-13466.rs deleted file mode 100644 index 78ce4c1d2f6..00000000000 --- a/tests/ui/issues/issue-13466.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Regression test for #13466 - -//@ dont-require-annotations: NOTE - -pub fn main() { - // The expected arm type `Option` has one type parameter, while - // the actual arm `Result` has two. typeck should not be - // tricked into looking up a non-existing second type parameter. - let _x: usize = match Some(1) { - Ok(u) => u, - //~^ ERROR mismatched types - //~| NOTE expected enum `Option<{integer}>` - //~| NOTE found enum `Result<_, _>` - //~| NOTE expected `Option<{integer}>`, found `Result<_, _>` - - Err(e) => panic!(e) - //~^ ERROR mismatched types - //~| NOTE expected enum `Option<{integer}>` - //~| NOTE found enum `Result<_, _>` - //~| NOTE expected `Option<{integer}>`, found `Result<_, _>` - }; -} diff --git a/tests/ui/iterators/bytes-iterator-clone.rs b/tests/ui/iterators/bytes-iterator-clone.rs new file mode 100644 index 00000000000..dbc2dbc8527 --- /dev/null +++ b/tests/ui/iterators/bytes-iterator-clone.rs @@ -0,0 +1,9 @@ +//@ run-pass + +fn main() { + let s = "Hello"; + let first = s.bytes(); + let second = first.clone(); + + assert_eq!(first.collect::>(), second.collect::>()) +} diff --git a/tests/ui/iterators/phf-map-entries-iterator.rs b/tests/ui/iterators/phf-map-entries-iterator.rs new file mode 100644 index 00000000000..5f733e85948 --- /dev/null +++ b/tests/ui/iterators/phf-map-entries-iterator.rs @@ -0,0 +1,24 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +use std::slice; + +pub struct PhfMapEntries<'a, T: 'a> { + iter: slice::Iter<'a, (&'static str, T)>, +} + +impl<'a, T> Iterator for PhfMapEntries<'a, T> { + type Item = (&'static str, &'a T); + + fn next(&mut self) -> Option<(&'static str, &'a T)> { + self.iter.by_ref().map(|&(key, ref value)| (key, value)).next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/iterator-trait-lifetime-error.rs b/tests/ui/lifetimes/iterator-trait-lifetime-error.rs new file mode 100644 index 00000000000..a5806feb720 --- /dev/null +++ b/tests/ui/lifetimes/iterator-trait-lifetime-error.rs @@ -0,0 +1,27 @@ +use std::ops::Range; + +trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } + +impl<'r> Itble<'r, usize, Range> for (usize, usize) { + fn iter(&'r self) -> Range { + let &(min, max) = self; + min..max + } +} + +fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool +{ + let cont_iter = cont.iter(); +//~^ ERROR explicit lifetime required in the type of `cont` [E0621] + let result = cont_iter.fold(Some(0), |state, val| { + state.map_or(None, |mask| { + let bit = 1 << val; + if mask & bit == 0 {Some(mask|bit)} else {None} + }) + }); + result.is_some() +} + +fn main() { + check(&(3, 5)); +} diff --git a/tests/ui/lifetimes/struct-lifetime-field-assignment.rs b/tests/ui/lifetimes/struct-lifetime-field-assignment.rs new file mode 100644 index 00000000000..80b298d2f37 --- /dev/null +++ b/tests/ui/lifetimes/struct-lifetime-field-assignment.rs @@ -0,0 +1,19 @@ +//@ check-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Foo<'a> { + i: &'a bool, + j: Option<&'a isize>, +} + +impl<'a> Foo<'a> { + fn bar(&mut self, j: &isize) { + let child = Foo { + i: self.i, + j: Some(j) + }; + } +} + +fn main() {} diff --git a/tests/ui/match/function-in-pattern-error.rs b/tests/ui/match/function-in-pattern-error.rs new file mode 100644 index 00000000000..1ac1c3d818e --- /dev/null +++ b/tests/ui/match/function-in-pattern-error.rs @@ -0,0 +1,8 @@ +mod foo { pub fn bar() {} } + +fn main() { + match () { + foo::bar => {} + //~^ ERROR expected unit struct, unit variant or constant, found function `foo::bar` + } +} diff --git a/tests/ui/match/guard-literal-range-shadow.rs b/tests/ui/match/guard-literal-range-shadow.rs new file mode 100644 index 00000000000..fbd1d75067b --- /dev/null +++ b/tests/ui/match/guard-literal-range-shadow.rs @@ -0,0 +1,178 @@ +//@ run-pass + +// Tests that match expression handles overlapped literal and range +// properly in the presence of guard function. + +fn val() -> usize { 1 } + +static CONST: usize = 1; + +pub fn main() { + lit_shadow_range(); + range_shadow_lit(); + range_shadow_range(); + multi_pats_shadow_lit(); + multi_pats_shadow_range(); + lit_shadow_multi_pats(); + range_shadow_multi_pats(); + misc(); +} + +fn lit_shadow_range() { + assert_eq!(2, match 1 { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + let x = 0; + assert_eq!(2, match x+1 { + 0 => 0, + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + assert_eq!(2, match val() { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + assert_eq!(2, match CONST { + 0 => 0, + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + // value is out of the range of second arm, should match wildcard pattern + assert_eq!(3, match 3 { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); +} + +fn range_shadow_lit() { + assert_eq!(2, match 1 { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + let x = 0; + assert_eq!(2, match x+1 { + 0 => 0, + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + assert_eq!(2, match val() { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + assert_eq!(2, match CONST { + 0 => 0, + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + // ditto + assert_eq!(3, match 3 { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); +} + +fn range_shadow_range() { + assert_eq!(2, match 1 { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + let x = 0; + assert_eq!(2, match x+1 { + 100 => 0, + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + assert_eq!(2, match val() { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + assert_eq!(2, match CONST { + 100 => 0, + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + // ditto + assert_eq!(3, match 5 { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); +} + +fn multi_pats_shadow_lit() { + assert_eq!(2, match 1 { + 100 => 0, + 0 | 1..=10 if false => 1, + 1 => 2, + _ => 3, + }); +} + +fn multi_pats_shadow_range() { + assert_eq!(2, match 1 { + 100 => 0, + 0 | 1..=10 if false => 1, + 1..=3 => 2, + _ => 3, + }); +} + +fn lit_shadow_multi_pats() { + assert_eq!(2, match 1 { + 100 => 0, + 1 if false => 1, + 0 | 1..=10 => 2, + _ => 3, + }); +} + +fn range_shadow_multi_pats() { + assert_eq!(2, match 1 { + 100 => 0, + 1..=3 if false => 1, + 0 | 1..=10 => 2, + _ => 3, + }); +} + +fn misc() { + enum Foo { + Bar(#[allow(dead_code)] usize, bool) + } + // This test basically mimics how trace_macros! macro is implemented, + // which is a rare combination of vector patterns, multiple wild-card + // patterns and guard functions. + let r = match [Foo::Bar(0, false)] { + [Foo::Bar(_, pred)] if pred => 1, + [Foo::Bar(_, pred)] if !pred => 2, + _ => 0, + }; + assert_eq!(2, r); +} diff --git a/tests/ui/match/option-result-mismatch.rs b/tests/ui/match/option-result-mismatch.rs new file mode 100644 index 00000000000..f974a470296 --- /dev/null +++ b/tests/ui/match/option-result-mismatch.rs @@ -0,0 +1,8 @@ +fn main() { + let a = Some(Box::new(1)); + match a { + Ok(a) => //~ ERROR: mismatched types + println!("{}",a), + None => panic!() + } +} diff --git a/tests/ui/match/option-result-type-param-mismatch.rs b/tests/ui/match/option-result-type-param-mismatch.rs new file mode 100644 index 00000000000..78ce4c1d2f6 --- /dev/null +++ b/tests/ui/match/option-result-type-param-mismatch.rs @@ -0,0 +1,22 @@ +// Regression test for #13466 + +//@ dont-require-annotations: NOTE + +pub fn main() { + // The expected arm type `Option` has one type parameter, while + // the actual arm `Result` has two. typeck should not be + // tricked into looking up a non-existing second type parameter. + let _x: usize = match Some(1) { + Ok(u) => u, + //~^ ERROR mismatched types + //~| NOTE expected enum `Option<{integer}>` + //~| NOTE found enum `Result<_, _>` + //~| NOTE expected `Option<{integer}>`, found `Result<_, _>` + + Err(e) => panic!(e) + //~^ ERROR mismatched types + //~| NOTE expected enum `Option<{integer}>` + //~| NOTE found enum `Result<_, _>` + //~| NOTE expected `Option<{integer}>`, found `Result<_, _>` + }; +} diff --git a/tests/ui/match/slice-move-out-error.rs b/tests/ui/match/slice-move-out-error.rs new file mode 100644 index 00000000000..1b2a37de475 --- /dev/null +++ b/tests/ui/match/slice-move-out-error.rs @@ -0,0 +1,13 @@ +fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) { + match (l1, l2) { + //~^ ERROR: cannot move out of type `[T]`, a non-copy slice + //~| ERROR: cannot move out of type `[T]`, a non-copy slice + (&[], &[]) => println!("both empty"), + (&[], &[hd, ..]) | (&[hd, ..], &[]) + => println!("one empty"), + (&[hd1, ..], &[hd2, ..]) + => println!("both nonempty"), + } +} + +fn main() {} diff --git a/tests/ui/match/string-literal-match-patterns.rs b/tests/ui/match/string-literal-match-patterns.rs new file mode 100644 index 00000000000..dd752227bbe --- /dev/null +++ b/tests/ui/match/string-literal-match-patterns.rs @@ -0,0 +1,16 @@ +//@ check-pass +#![allow(dead_code)] + +struct A { + a: String +} + +fn borrow<'a>(binding: &'a A) -> &'a str { + match &*binding.a { + "in" => "in_", + "ref" => "ref_", + ident => ident + } +} + +fn main() {} diff --git a/tests/ui/match/struct-reference-patterns.rs b/tests/ui/match/struct-reference-patterns.rs new file mode 100644 index 00000000000..fe199147128 --- /dev/null +++ b/tests/ui/match/struct-reference-patterns.rs @@ -0,0 +1,14 @@ +//@ run-pass + +struct S; + +fn main() { + match Some(&S) { + Some(&S) => {}, + _x => unreachable!() + } + match Some(&S) { + Some(&S) => {}, + None => unreachable!() + } +} diff --git a/tests/ui/panics/explicit-panic-unreachable.rs b/tests/ui/panics/explicit-panic-unreachable.rs new file mode 100644 index 00000000000..f3b1b643c45 --- /dev/null +++ b/tests/ui/panics/explicit-panic-unreachable.rs @@ -0,0 +1,8 @@ +//@ run-fail +//@ error-pattern:explicit panic +//@ needs-subprocess + +pub fn main() { + panic!(); + println!("{}", 1); +} diff --git a/tests/ui/panics/unwrap-or-panic-input.rs b/tests/ui/panics/unwrap-or-panic-input.rs new file mode 100644 index 00000000000..99ffba3fba5 --- /dev/null +++ b/tests/ui/panics/unwrap-or-panic-input.rs @@ -0,0 +1,7 @@ +//@ run-fail +//@ error-pattern:bad input +//@ needs-subprocess + +fn main() { + Some("foo").unwrap_or(panic!("bad input")).to_string(); +} diff --git a/tests/ui/privacy/private-unit-struct-assignment.rs b/tests/ui/privacy/private-unit-struct-assignment.rs new file mode 100644 index 00000000000..7794be37b85 --- /dev/null +++ b/tests/ui/privacy/private-unit-struct-assignment.rs @@ -0,0 +1,9 @@ +mod A { + struct C; +} + +fn main() { + A::C = 1; + //~^ ERROR: mismatched types + //~| ERROR: unit struct `C` is private +} diff --git a/tests/ui/statics/enum-with-static-str-variant.rs b/tests/ui/statics/enum-with-static-str-variant.rs new file mode 100644 index 00000000000..8140ec943a0 --- /dev/null +++ b/tests/ui/statics/enum-with-static-str-variant.rs @@ -0,0 +1,22 @@ +//@ build-pass +#![allow(dead_code)] +// defining static with struct that contains enum +// with &'static str variant used to cause ICE + + +pub enum Foo { + Bar, + Baz(&'static str), +} + +pub static TEST: Test = Test { + foo: Foo::Bar, + c: 'a' +}; + +pub struct Test { + foo: Foo, + c: char, +} + +fn main() {} diff --git a/tests/ui/threads/moved-value-in-thread-loop.rs b/tests/ui/threads/moved-value-in-thread-loop.rs new file mode 100644 index 00000000000..091e8fe8b2a --- /dev/null +++ b/tests/ui/threads/moved-value-in-thread-loop.rs @@ -0,0 +1,13 @@ +use std::sync::mpsc::channel; +use std::thread; + +fn main() { + let (tx, rx) = channel(); + let _t = thread::spawn(move|| -> () { + loop { + let tx = tx; + //~^ ERROR: use of moved value: `tx` + tx.send(1); + } + }); +} diff --git a/tests/ui/traits/any-trait-object-debug.rs b/tests/ui/traits/any-trait-object-debug.rs new file mode 100644 index 00000000000..eaf92d413d5 --- /dev/null +++ b/tests/ui/traits/any-trait-object-debug.rs @@ -0,0 +1,5 @@ +//@ run-pass +fn main() { + fn test() -> Box { Box::new(1) } + println!("{:?}", test()) +} diff --git a/tests/ui/traits/default-method-lifetime-params.rs b/tests/ui/traits/default-method-lifetime-params.rs new file mode 100644 index 00000000000..01362f6fe61 --- /dev/null +++ b/tests/ui/traits/default-method-lifetime-params.rs @@ -0,0 +1,25 @@ +//@ run-pass +#![allow(unused_mut)] +// Test that when instantiating trait default methods, typeck handles +// lifetime parameters defined on the method bound correctly. + + +pub trait Foo { + fn bar<'a, I: Iterator>(&self, it: I) -> usize { + let mut xs = it.filter(|_| true); + xs.count() + } +} + +pub struct Baz; + +impl Foo for Baz { + // When instantiating `Foo::bar` for `Baz` here, typeck used to + // ICE due to the lifetime parameter of `bar`. +} + +fn main() { + let x = Baz; + let y = vec![(), (), ()]; + assert_eq!(x.bar(y.iter()), 3); +} diff --git a/tests/ui/traits/deref-chain-method-calls.rs b/tests/ui/traits/deref-chain-method-calls.rs new file mode 100644 index 00000000000..bf4ec388c4f --- /dev/null +++ b/tests/ui/traits/deref-chain-method-calls.rs @@ -0,0 +1,74 @@ +//@ run-pass +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use std::ops::Deref; + +struct Root { + jsref: JSRef +} + +impl Deref for Root { + type Target = JSRef; + + fn deref<'a>(&'a self) -> &'a JSRef { + &self.jsref + } +} + +#[derive(Copy, Clone)] +struct JSRef { + node: *const Node +} + +impl Deref for JSRef { + type Target = Node; + + fn deref<'a>(&'a self) -> &'a Node { + self.get() + } +} + +trait INode { + fn RemoveChild(&self); +} + +impl INode for JSRef { + fn RemoveChild(&self) { + self.get().RemoveChild(0) + } +} + +impl JSRef { + fn AddChild(&self) { + self.get().AddChild(0); + } + + fn get<'a>(&'a self) -> &'a Node { + unsafe { + &*self.node + } + } +} + +struct Node; + +impl Node { + fn RemoveChild(&self, _a: usize) { + } + + fn AddChild(&self, _a: usize) { + } +} + +fn main() { + let n = Node; + let jsref = JSRef { node: &n }; + let root = Root { jsref: jsref }; + + root.AddChild(); + jsref.AddChild(); + + root.RemoveChild(); + jsref.RemoveChild(); +} diff --git a/tests/ui/traits/fnonce-repro-trait-impl.rs b/tests/ui/traits/fnonce-repro-trait-impl.rs new file mode 100644 index 00000000000..caf7b632393 --- /dev/null +++ b/tests/ui/traits/fnonce-repro-trait-impl.rs @@ -0,0 +1,21 @@ +//@ run-pass +#[derive(Debug)] +struct MyStruct; + +trait Repro { + fn repro(self, s: MyStruct) -> String; +} + +impl Repro for F where F: FnOnce(MyStruct) -> String { + fn repro(self, s: MyStruct) -> String { + self(s) + } +} + +fn do_stuff(r: R) -> String { + r.repro(MyStruct) +} + +pub fn main() { + assert_eq!("MyStruct".to_string(), do_stuff(|s: MyStruct| format!("{:?}", s))); +} diff --git a/tests/ui/traits/matcher-trait-equality.rs b/tests/ui/traits/matcher-trait-equality.rs new file mode 100644 index 00000000000..8f334404f9a --- /dev/null +++ b/tests/ui/traits/matcher-trait-equality.rs @@ -0,0 +1,58 @@ +//@ run-pass + +struct StrWrap { + s: String +} + +impl StrWrap { + fn new(s: &str) -> StrWrap { + StrWrap { s: s.to_string() } + } + + fn get_s<'a>(&'a self) -> &'a str { + &self.s + } +} + +struct MyStruct { + s: StrWrap +} + +impl MyStruct { + fn new(s: &str) -> MyStruct { + MyStruct { s: StrWrap::new(s) } + } + + fn get_str_wrap<'a>(&'a self) -> &'a StrWrap { + &self.s + } +} + +trait Matcher { + fn matches(&self, actual: T) -> bool; +} + +fn assert_that>(actual: T, matcher: &U) { + assert!(matcher.matches(actual)); +} + +struct EqualTo { + expected: T +} + +impl Matcher for EqualTo { + fn matches(&self, actual: T) -> bool { + self.expected.eq(&actual) + } +} + +fn equal_to(expected: T) -> Box> { + Box::new(EqualTo { expected: expected }) +} + +pub fn main() { + let my_struct = MyStruct::new("zomg"); + let s = my_struct.get_str_wrap(); + + assert_that(s.get_s(), &*equal_to("zomg")); +} diff --git a/tests/ui/traits/reference-clone-noclone.rs b/tests/ui/traits/reference-clone-noclone.rs new file mode 100644 index 00000000000..ada844f8ee1 --- /dev/null +++ b/tests/ui/traits/reference-clone-noclone.rs @@ -0,0 +1,13 @@ +//@ run-pass + +#![allow(noop_method_call)] + +struct NoClone; + +fn main() { + let rnc = &NoClone; + let rsnc = &Some(NoClone); + + let _: &NoClone = rnc.clone(); + let _: &Option = rsnc.clone(); +} diff --git a/tests/ui/type-inference/isize-usize-mismatch-error.rs b/tests/ui/type-inference/isize-usize-mismatch-error.rs new file mode 100644 index 00000000000..5d31d7f861c --- /dev/null +++ b/tests/ui/type-inference/isize-usize-mismatch-error.rs @@ -0,0 +1,15 @@ +//@ dont-require-annotations: NOTE + +fn foo(_s: i16) { } + +fn bar(_s: u32) { } + +fn main() { + foo(1*(1 as isize)); + //~^ ERROR mismatched types + //~| NOTE expected `i16`, found `isize` + + bar(1*(1 as usize)); + //~^ ERROR mismatched types + //~| NOTE expected `u32`, found `usize` +} diff --git a/tests/ui/type-inference/type-collect-inference.rs b/tests/ui/type-inference/type-collect-inference.rs new file mode 100644 index 00000000000..f2c33806aae --- /dev/null +++ b/tests/ui/type-inference/type-collect-inference.rs @@ -0,0 +1,19 @@ +//@ run-pass +#![allow(unused_variables)] + +use std::collections::HashMap; + +fn copy(&x: &T) -> T { + x +} + +fn main() { + let arr = [(1, 1), (2, 2), (3, 3)]; + + let v1: Vec<&_> = arr.iter().collect(); + let v2: Vec<_> = arr.iter().map(copy).collect(); + + let m1: HashMap<_, _> = arr.iter().map(copy).collect(); + let m2: HashMap = arr.iter().map(copy).collect(); + let m3: HashMap<_, usize> = arr.iter().map(copy).collect(); +} diff --git a/tests/ui/type-inference/unit-type-add-error.rs b/tests/ui/type-inference/unit-type-add-error.rs new file mode 100644 index 00000000000..c69cd1e79e3 --- /dev/null +++ b/tests/ui/type-inference/unit-type-add-error.rs @@ -0,0 +1,11 @@ +fn main() { + let x = (); + 1 + + x //~^ ERROR E0277 + ; + + let x: () = (); + 1 + + x //~^ ERROR E0277 + ; +} diff --git a/tests/ui/unsafe/unsafe-transmute-in-find.rs b/tests/ui/unsafe/unsafe-transmute-in-find.rs new file mode 100644 index 00000000000..c6099c2a0c0 --- /dev/null +++ b/tests/ui/unsafe/unsafe-transmute-in-find.rs @@ -0,0 +1,26 @@ +//@ check-pass + +struct Attr { + name: String, + value: String, +} + +struct Element { + attrs: Vec>, +} + +impl Element { + pub unsafe fn get_attr<'a>(&'a self, name: &str) { + self.attrs + .iter() + .find(|attr| { + let attr: &&Box = std::mem::transmute(attr); + true + }); + } +} + +fn main() { + let element = Element { attrs: Vec::new() }; + unsafe { let () = element.get_attr("foo"); }; +} -- cgit 1.4.1-3-g733a5 From a1f5a6d781d65949fe08c149a695d4cd926cc755 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 26 Jul 2025 00:47:33 +0000 Subject: Perform check_private_in_public by module. --- compiler/rustc_interface/src/passes.rs | 4 +- compiler/rustc_middle/src/query/mod.rs | 7 ++- compiler/rustc_privacy/src/lib.rs | 4 +- tests/ui/privacy/private-in-public-warn.stderr | 72 +++++++++++++------------- tests/ui/privacy/projections.stderr | 26 +++++----- 5 files changed, 59 insertions(+), 54 deletions(-) (limited to 'tests/ui') diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index fb6897c7d89..aaabf7df42d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1147,7 +1147,9 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { parallel!( { - tcx.ensure_ok().check_private_in_public(()); + tcx.par_hir_for_each_module(|module| { + tcx.ensure_ok().check_private_in_public(module) + }) }, { tcx.par_hir_for_each_module(|module| { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 587349d4cf4..7a625f4fee7 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1390,8 +1390,11 @@ rustc_queries! { eval_always desc { "checking effective visibilities" } } - query check_private_in_public(_: ()) { - desc { "checking for private elements in public interfaces" } + query check_private_in_public(module_def_id: LocalModDefId) { + desc { |tcx| + "checking for private elements in public interfaces for {}", + describe_as_module(module_def_id, tcx) + } } query reachable_set(_: ()) -> &'tcx LocalDefIdSet { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 6fd2b7fc12f..1a062c63a6f 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1854,12 +1854,12 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { tcx.arena.alloc(visitor.effective_visibilities) } -fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { +fn check_private_in_public(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let effective_visibilities = tcx.effective_visibilities(()); // Check for private types in public interfaces. let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities }; - let crate_items = tcx.hir_crate_items(()); + let crate_items = tcx.hir_module_items(module_def_id); for id in crate_items.free_items() { checker.check_item(id); } diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr index 86f6be85a07..edcffaf6b70 100644 --- a/tests/ui/privacy/private-in-public-warn.stderr +++ b/tests/ui/privacy/private-in-public-warn.stderr @@ -93,6 +93,42 @@ LL | struct Priv; LL | type Alias = Priv; | ^^^^^^^^^^ can't leak private type +error: type `types::Priv` is more private than the item `types::ES` + --> $DIR/private-in-public-warn.rs:27:9 + | +LL | pub static ES: Priv; + | ^^^^^^^^^^^^^^^^^^^ static `types::ES` is reachable at visibility `pub(crate)` + | +note: but type `types::Priv` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:9:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + +error: type `types::Priv` is more private than the item `types::ef1` + --> $DIR/private-in-public-warn.rs:28:9 + | +LL | pub fn ef1(arg: Priv); + | ^^^^^^^^^^^^^^^^^^^^^^ function `types::ef1` is reachable at visibility `pub(crate)` + | +note: but type `types::Priv` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:9:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + +error: type `types::Priv` is more private than the item `types::ef2` + --> $DIR/private-in-public-warn.rs:29:9 + | +LL | pub fn ef2() -> Priv; + | ^^^^^^^^^^^^^^^^^^^^^ function `types::ef2` is reachable at visibility `pub(crate)` + | +note: but type `types::Priv` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:9:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + error: trait `traits::PrivTr` is more private than the item `traits::Alias` --> $DIR/private-in-public-warn.rs:42:5 | @@ -359,42 +395,6 @@ note: but type `Priv2` is only usable at visibility `pub(self)` LL | struct Priv2; | ^^^^^^^^^^^^ -error: type `types::Priv` is more private than the item `types::ES` - --> $DIR/private-in-public-warn.rs:27:9 - | -LL | pub static ES: Priv; - | ^^^^^^^^^^^^^^^^^^^ static `types::ES` is reachable at visibility `pub(crate)` - | -note: but type `types::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:9:5 - | -LL | struct Priv; - | ^^^^^^^^^^^ - -error: type `types::Priv` is more private than the item `types::ef1` - --> $DIR/private-in-public-warn.rs:28:9 - | -LL | pub fn ef1(arg: Priv); - | ^^^^^^^^^^^^^^^^^^^^^^ function `types::ef1` is reachable at visibility `pub(crate)` - | -note: but type `types::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:9:5 - | -LL | struct Priv; - | ^^^^^^^^^^^ - -error: type `types::Priv` is more private than the item `types::ef2` - --> $DIR/private-in-public-warn.rs:29:9 - | -LL | pub fn ef2() -> Priv; - | ^^^^^^^^^^^^^^^^^^^^^ function `types::ef2` is reachable at visibility `pub(crate)` - | -note: but type `types::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:9:5 - | -LL | struct Priv; - | ^^^^^^^^^^^ - warning: bounds on generic parameters in type aliases are not enforced --> $DIR/private-in-public-warn.rs:42:23 | diff --git a/tests/ui/privacy/projections.stderr b/tests/ui/privacy/projections.stderr index 010d77998e3..addb6a075a2 100644 --- a/tests/ui/privacy/projections.stderr +++ b/tests/ui/privacy/projections.stderr @@ -1,16 +1,3 @@ -warning: type `Priv` is more private than the item `Leak` - --> $DIR/projections.rs:3:5 - | -LL | pub type Leak = Priv; - | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` - | -note: but type `Priv` is only usable at visibility `pub(self)` - --> $DIR/projections.rs:2:5 - | -LL | struct Priv; - | ^^^^^^^^^^^ - = note: `#[warn(private_interfaces)]` on by default - error[E0446]: private type `Priv` in public interface --> $DIR/projections.rs:24:5 | @@ -29,6 +16,19 @@ LL | struct Priv; LL | type A = T::A; | ^^^^^^^^^^^^^^^^ can't leak private type +warning: type `Priv` is more private than the item `Leak` + --> $DIR/projections.rs:3:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/projections.rs:2:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + error: type `Priv` is private --> $DIR/projections.rs:14:15 | -- cgit 1.4.1-3-g733a5 From ee0118f8a1dbfcad06b8c09644553a3fc3e070d4 Mon Sep 17 00:00:00 2001 From: David Tenty Date: Wed, 30 Jul 2025 16:45:17 -0400 Subject: [test][AIX] ignore extern_weak linkage test The AIX linkage model doesn't support ELF style extern_weak semantic, so just skip this test, like other platforms that don't have it. --- tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/ui') diff --git a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs index 8c194ec50df..ad7b0674478 100644 --- a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs +++ b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs @@ -4,6 +4,7 @@ //@ ignore-emscripten no weak symbol support //@ ignore-apple no extern_weak linkage +//@ ignore-aix no extern_weak linkage //@ aux-build:lib.rs -- cgit 1.4.1-3-g733a5 From 7b667e7811f4a4b496f38d25c5e824f13638cdbb Mon Sep 17 00:00:00 2001 From: xizheyin Date: Thu, 31 Jul 2025 00:44:22 +0800 Subject: Extend `is_case_difference` to handle digit-letter confusables Signed-off-by: xizheyin --- compiler/rustc_errors/src/emitter.rs | 135 ++++++++++++++++----- compiler/rustc_errors/src/lib.rs | 11 +- .../clippy/tests/ui/match_str_case_mismatch.stderr | 2 +- tests/ui/error-codes/E0423.stderr | 2 +- tests/ui/lint/lint-non-uppercase-usages.stderr | 2 +- tests/ui/parser/item-kw-case-mismatch.stderr | 6 +- tests/ui/parser/kw-in-trait-bounds.stderr | 8 +- tests/ui/parser/misspelled-keywords/hrdt.stderr | 2 +- .../parser/misspelled-keywords/impl-return.stderr | 2 +- tests/ui/parser/misspelled-keywords/static.stderr | 2 +- tests/ui/parser/misspelled-keywords/struct.stderr | 2 +- .../recover/recover-fn-trait-from-fn-kw.stderr | 4 +- .../parser/typod-const-in-const-param-def.stderr | 8 +- .../suggestions/assoc-ct-for-assoc-method.stderr | 2 +- tests/ui/suggestions/bool_typo_err_suggest.stderr | 2 +- .../ui/suggestions/case-difference-suggestions.rs | 57 +++++++++ .../suggestions/case-difference-suggestions.stderr | 99 +++++++++++++++ tests/ui/suggestions/incorrect-variant-literal.svg | 2 +- 18 files changed, 290 insertions(+), 58 deletions(-) create mode 100644 tests/ui/suggestions/case-difference-suggestions.rs create mode 100644 tests/ui/suggestions/case-difference-suggestions.stderr (limited to 'tests/ui') diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 46a4a186824..55a42d0426e 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -262,19 +262,11 @@ pub trait Emitter { format!("help: {msg}") } else { // Show the default suggestion text with the substitution - format!( - "help: {}{}: `{}`", - msg, - if self - .source_map() - .is_some_and(|sm| is_case_difference(sm, snippet, part.span,)) - { - " (notice the capitalization)" - } else { - "" - }, - snippet, - ) + let confusion_type = self + .source_map() + .map(|sm| detect_confusion_type(sm, snippet, part.span)) + .unwrap_or(ConfusionType::None); + format!("help: {}{}: `{}`", msg, confusion_type.label_text(), snippet,) }; primary_span.push_span_label(part.span, msg); @@ -2028,12 +2020,12 @@ impl HumanEmitter { buffer.append(0, ": ", Style::HeaderMsg); let mut msg = vec![(suggestion.msg.to_owned(), Style::NoStyle)]; - if suggestions - .iter() - .take(MAX_SUGGESTIONS) - .any(|(_, _, _, only_capitalization)| *only_capitalization) + if let Some(confusion_type) = + suggestions.iter().take(MAX_SUGGESTIONS).find_map(|(_, _, _, confusion_type)| { + if confusion_type.has_confusion() { Some(*confusion_type) } else { None } + }) { - msg.push((" (notice the capitalization difference)".into(), Style::NoStyle)); + msg.push((confusion_type.label_text().into(), Style::NoStyle)); } self.msgs_to_buffer( &mut buffer, @@ -3528,24 +3520,107 @@ pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool { } /// Whether the original and suggested code are visually similar enough to warrant extra wording. -pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { - // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode. +pub fn detect_confusion_type(sm: &SourceMap, suggested: &str, sp: Span) -> ConfusionType { let found = match sm.span_to_snippet(sp) { Ok(snippet) => snippet, Err(e) => { warn!(error = ?e, "Invalid span {:?}", sp); - return false; + return ConfusionType::None; } }; - let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z']; - // All the chars that differ in capitalization are confusable (above): - let confusable = iter::zip(found.chars(), suggested.chars()) - .filter(|(f, s)| f != s) - .all(|(f, s)| ascii_confusables.contains(&f) || ascii_confusables.contains(&s)); - confusable && found.to_lowercase() == suggested.to_lowercase() - // FIXME: We sometimes suggest the same thing we already have, which is a - // bug, but be defensive against that here. - && found != suggested + + let mut has_case_confusion = false; + let mut has_digit_letter_confusion = false; + + if found.len() == suggested.len() { + let mut has_case_diff = false; + let mut has_digit_letter_confusable = false; + let mut has_other_diff = false; + + let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z']; + + let digit_letter_confusables = [('0', 'O'), ('1', 'l'), ('5', 'S'), ('8', 'B'), ('9', 'g')]; + + for (f, s) in iter::zip(found.chars(), suggested.chars()) { + if f != s { + if f.to_lowercase().to_string() == s.to_lowercase().to_string() { + // Check for case differences (any character that differs only in case) + if ascii_confusables.contains(&f) || ascii_confusables.contains(&s) { + has_case_diff = true; + } else { + has_other_diff = true; + } + } else if digit_letter_confusables.contains(&(f, s)) + || digit_letter_confusables.contains(&(s, f)) + { + // Check for digit-letter confusables (like 0 vs O, 1 vs l, etc.) + has_digit_letter_confusable = true; + } else { + has_other_diff = true; + } + } + } + + // If we have case differences and no other differences + if has_case_diff && !has_other_diff && found != suggested { + has_case_confusion = true; + } + if has_digit_letter_confusable && !has_other_diff && found != suggested { + has_digit_letter_confusion = true; + } + } + + match (has_case_confusion, has_digit_letter_confusion) { + (true, true) => ConfusionType::Both, + (true, false) => ConfusionType::Case, + (false, true) => ConfusionType::DigitLetter, + (false, false) => ConfusionType::None, + } +} + +/// Represents the type of confusion detected between original and suggested code. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ConfusionType { + /// No confusion detected + None, + /// Only case differences (e.g., "hello" vs "Hello") + Case, + /// Only digit-letter confusion (e.g., "0" vs "O", "1" vs "l") + DigitLetter, + /// Both case and digit-letter confusion + Both, +} + +impl ConfusionType { + /// Returns the appropriate label text for this confusion type. + pub fn label_text(&self) -> &'static str { + match self { + ConfusionType::None => "", + ConfusionType::Case => " (notice the capitalization)", + ConfusionType::DigitLetter => " (notice the digit/letter confusion)", + ConfusionType::Both => " (notice the capitalization and digit/letter confusion)", + } + } + + /// Combines two confusion types. If either is `Both`, the result is `Both`. + /// If one is `Case` and the other is `DigitLetter`, the result is `Both`. + /// Otherwise, returns the non-`None` type, or `None` if both are `None`. + pub fn combine(self, other: ConfusionType) -> ConfusionType { + match (self, other) { + (ConfusionType::None, other) => other, + (this, ConfusionType::None) => this, + (ConfusionType::Both, _) | (_, ConfusionType::Both) => ConfusionType::Both, + (ConfusionType::Case, ConfusionType::DigitLetter) + | (ConfusionType::DigitLetter, ConfusionType::Case) => ConfusionType::Both, + (ConfusionType::Case, ConfusionType::Case) => ConfusionType::Case, + (ConfusionType::DigitLetter, ConfusionType::DigitLetter) => ConfusionType::DigitLetter, + } + } + + /// Returns true if this confusion type represents any kind of confusion. + pub fn has_confusion(&self) -> bool { + *self != ConfusionType::None + } } pub(crate) fn should_show_source_code( diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 381d780077d..2534cddf105 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -50,7 +50,7 @@ pub use diagnostic_impls::{ IndicateAnonymousLifetime, SingleLabelManySpans, }; pub use emitter::ColorConfig; -use emitter::{DynEmitter, Emitter, is_case_difference, is_different}; +use emitter::{ConfusionType, DynEmitter, Emitter, detect_confusion_type, is_different}; use rustc_data_structures::AtomicRef; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::StableHasher; @@ -308,7 +308,7 @@ impl CodeSuggestion { pub(crate) fn splice_lines( &self, sm: &SourceMap, - ) -> Vec<(String, Vec, Vec>, bool)> { + ) -> Vec<(String, Vec, Vec>, ConfusionType)> { // For the `Vec>` value, the first level of the vector // corresponds to the output snippet's lines, while the second level corresponds to the // substrings within that line that should be highlighted. @@ -414,14 +414,15 @@ impl CodeSuggestion { // We need to keep track of the difference between the existing code and the added // or deleted code in order to point at the correct column *after* substitution. let mut acc = 0; - let mut only_capitalization = false; + let mut confusion_type = ConfusionType::None; for part in &mut substitution.parts { // If this is a replacement of, e.g. `"a"` into `"ab"`, adjust the // suggestion and snippet to look as if we just suggested to add // `"b"`, which is typically much easier for the user to understand. part.trim_trivial_replacements(sm); - only_capitalization |= is_case_difference(sm, &part.snippet, part.span); + let part_confusion = detect_confusion_type(sm, &part.snippet, part.span); + confusion_type = confusion_type.combine(part_confusion); let cur_lo = sm.lookup_char_pos(part.span.lo()); if prev_hi.line == cur_lo.line { let mut count = @@ -511,7 +512,7 @@ impl CodeSuggestion { if highlights.iter().all(|parts| parts.is_empty()) { None } else { - Some((buf, substitution.parts, highlights, only_capitalization)) + Some((buf, substitution.parts, highlights, confusion_type)) } }) .collect() diff --git a/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr b/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr index 8068edfff94..c2b58b952aa 100644 --- a/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr +++ b/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr @@ -18,7 +18,7 @@ error: this `match` arm has a differing case than its expression LL | "~!@#$%^&*()-_=+Foo" => {}, | ^^^^^^^^^^^^^^^^^^^^ | -help: consider changing the case of this arm to respect `to_ascii_lowercase` (notice the capitalization difference) +help: consider changing the case of this arm to respect `to_ascii_lowercase` (notice the capitalization) | LL - "~!@#$%^&*()-_=+Foo" => {}, LL + "~!@#$%^&*()-_=+foo" => {}, diff --git a/tests/ui/error-codes/E0423.stderr b/tests/ui/error-codes/E0423.stderr index e50b8bd820c..b699e53fb48 100644 --- a/tests/ui/error-codes/E0423.stderr +++ b/tests/ui/error-codes/E0423.stderr @@ -54,7 +54,7 @@ help: use struct literal syntax instead LL - let f = Foo(); LL + let f = Foo { a: val }; | -help: a function with a similar name exists (notice the capitalization difference) +help: a function with a similar name exists (notice the capitalization) | LL - let f = Foo(); LL + let f = foo(); diff --git a/tests/ui/lint/lint-non-uppercase-usages.stderr b/tests/ui/lint/lint-non-uppercase-usages.stderr index 7c7e573a88e..b34be31216d 100644 --- a/tests/ui/lint/lint-non-uppercase-usages.stderr +++ b/tests/ui/lint/lint-non-uppercase-usages.stderr @@ -29,7 +29,7 @@ warning: const parameter `foo` should have an upper case name LL | fn foo() { | ^^^ | -help: convert the identifier to upper case (notice the capitalization difference) +help: convert the identifier to upper case (notice the capitalization) | LL - fn foo() { LL + fn foo() { diff --git a/tests/ui/parser/item-kw-case-mismatch.stderr b/tests/ui/parser/item-kw-case-mismatch.stderr index df39eb10fdb..d2a1eb7f2f5 100644 --- a/tests/ui/parser/item-kw-case-mismatch.stderr +++ b/tests/ui/parser/item-kw-case-mismatch.stderr @@ -4,7 +4,7 @@ error: keyword `use` is written in the wrong case LL | Use std::ptr::read; | ^^^ | -help: write it in the correct case (notice the capitalization difference) +help: write it in the correct case (notice the capitalization) | LL - Use std::ptr::read; LL + use std::ptr::read; @@ -28,7 +28,7 @@ error: keyword `fn` is written in the wrong case LL | async Fn _a() {} | ^^ | -help: write it in the correct case (notice the capitalization difference) +help: write it in the correct case (notice the capitalization) | LL - async Fn _a() {} LL + async fn _a() {} @@ -40,7 +40,7 @@ error: keyword `fn` is written in the wrong case LL | Fn _b() {} | ^^ | -help: write it in the correct case (notice the capitalization difference) +help: write it in the correct case (notice the capitalization) | LL - Fn _b() {} LL + fn _b() {} diff --git a/tests/ui/parser/kw-in-trait-bounds.stderr b/tests/ui/parser/kw-in-trait-bounds.stderr index 1892d0b6226..5a4adf3e37b 100644 --- a/tests/ui/parser/kw-in-trait-bounds.stderr +++ b/tests/ui/parser/kw-in-trait-bounds.stderr @@ -4,7 +4,7 @@ error: expected identifier, found keyword `fn` LL | fn _f(_: impl fn(), _: &dyn fn()) | ^^ | -help: use `Fn` to refer to the trait (notice the capitalization difference) +help: use `Fn` to refer to the trait (notice the capitalization) | LL - fn _f(_: impl fn(), _: &dyn fn()) LL + fn _f(_: impl fn(), _: &dyn fn()) @@ -16,7 +16,7 @@ error: expected identifier, found keyword `fn` LL | fn _f(_: impl fn(), _: &dyn fn()) | ^^ | -help: use `Fn` to refer to the trait (notice the capitalization difference) +help: use `Fn` to refer to the trait (notice the capitalization) | LL - fn _f(_: impl fn(), _: &dyn fn()) LL + fn _f(_: impl Fn(), _: &dyn fn()) @@ -28,7 +28,7 @@ error: expected identifier, found keyword `fn` LL | fn _f(_: impl fn(), _: &dyn fn()) | ^^ | -help: use `Fn` to refer to the trait (notice the capitalization difference) +help: use `Fn` to refer to the trait (notice the capitalization) | LL - fn _f(_: impl fn(), _: &dyn fn()) LL + fn _f(_: impl fn(), _: &dyn Fn()) @@ -40,7 +40,7 @@ error: expected identifier, found keyword `fn` LL | G: fn(), | ^^ | -help: use `Fn` to refer to the trait (notice the capitalization difference) +help: use `Fn` to refer to the trait (notice the capitalization) | LL - G: fn(), LL + G: Fn(), diff --git a/tests/ui/parser/misspelled-keywords/hrdt.stderr b/tests/ui/parser/misspelled-keywords/hrdt.stderr index e5fc1a50382..497bd613bf4 100644 --- a/tests/ui/parser/misspelled-keywords/hrdt.stderr +++ b/tests/ui/parser/misspelled-keywords/hrdt.stderr @@ -4,7 +4,7 @@ error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found keyword LL | Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, | ^^^ expected one of 7 possible tokens | -help: write keyword `where` in lowercase (notice the capitalization difference) +help: write keyword `where` in lowercase (notice the capitalization) | LL - Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, LL + where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, diff --git a/tests/ui/parser/misspelled-keywords/impl-return.stderr b/tests/ui/parser/misspelled-keywords/impl-return.stderr index ff5391461a9..d49d962d7e9 100644 --- a/tests/ui/parser/misspelled-keywords/impl-return.stderr +++ b/tests/ui/parser/misspelled-keywords/impl-return.stderr @@ -4,7 +4,7 @@ error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Display LL | fn code() -> Impl Display {} | ^^^^^^^ expected one of 7 possible tokens | -help: write keyword `impl` in lowercase (notice the capitalization difference) +help: write keyword `impl` in lowercase (notice the capitalization) | LL - fn code() -> Impl Display {} LL + fn code() -> impl Display {} diff --git a/tests/ui/parser/misspelled-keywords/static.stderr b/tests/ui/parser/misspelled-keywords/static.stderr index e559f2be109..0df40bcdc33 100644 --- a/tests/ui/parser/misspelled-keywords/static.stderr +++ b/tests/ui/parser/misspelled-keywords/static.stderr @@ -4,7 +4,7 @@ error: expected one of `!` or `::`, found `a` LL | Static a = 0; | ^ expected one of `!` or `::` | -help: write keyword `static` in lowercase (notice the capitalization difference) +help: write keyword `static` in lowercase (notice the capitalization) | LL - Static a = 0; LL + static a = 0; diff --git a/tests/ui/parser/misspelled-keywords/struct.stderr b/tests/ui/parser/misspelled-keywords/struct.stderr index edbec3b9456..af8614ef14b 100644 --- a/tests/ui/parser/misspelled-keywords/struct.stderr +++ b/tests/ui/parser/misspelled-keywords/struct.stderr @@ -4,7 +4,7 @@ error: expected one of `!` or `::`, found `Foor` LL | Struct Foor { | ^^^^ expected one of `!` or `::` | -help: write keyword `struct` in lowercase (notice the capitalization difference) +help: write keyword `struct` in lowercase (notice the capitalization) | LL - Struct Foor { LL + struct Foor { diff --git a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr index 4e1fcaf4936..bd809e77a8f 100644 --- a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr +++ b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr @@ -4,7 +4,7 @@ error: expected identifier, found keyword `fn` LL | fn foo(_: impl fn() -> i32) {} | ^^ | -help: use `Fn` to refer to the trait (notice the capitalization difference) +help: use `Fn` to refer to the trait (notice the capitalization) | LL - fn foo(_: impl fn() -> i32) {} LL + fn foo(_: impl Fn() -> i32) {} @@ -16,7 +16,7 @@ error: expected identifier, found keyword `fn` LL | fn foo2(_: T) {} | ^^ | -help: use `Fn` to refer to the trait (notice the capitalization difference) +help: use `Fn` to refer to the trait (notice the capitalization) | LL - fn foo2(_: T) {} LL + fn foo2(_: T) {} diff --git a/tests/ui/parser/typod-const-in-const-param-def.stderr b/tests/ui/parser/typod-const-in-const-param-def.stderr index bf7168a0157..cc1600fe5cb 100644 --- a/tests/ui/parser/typod-const-in-const-param-def.stderr +++ b/tests/ui/parser/typod-const-in-const-param-def.stderr @@ -4,7 +4,7 @@ error: `const` keyword was mistyped as `Const` LL | pub fn foo() {} | ^^^^^ | -help: use the `const` keyword (notice the capitalization difference) +help: use the `const` keyword (notice the capitalization) | LL - pub fn foo() {} LL + pub fn foo() {} @@ -16,7 +16,7 @@ error: `const` keyword was mistyped as `Const` LL | pub fn baz() {} | ^^^^^ | -help: use the `const` keyword (notice the capitalization difference) +help: use the `const` keyword (notice the capitalization) | LL - pub fn baz() {} LL + pub fn baz() {} @@ -28,7 +28,7 @@ error: `const` keyword was mistyped as `Const` LL | pub fn qux() {} | ^^^^^ | -help: use the `const` keyword (notice the capitalization difference) +help: use the `const` keyword (notice the capitalization) | LL - pub fn qux() {} LL + pub fn qux() {} @@ -40,7 +40,7 @@ error: `const` keyword was mistyped as `Const` LL | pub fn quux() {} | ^^^^^ | -help: use the `const` keyword (notice the capitalization difference) +help: use the `const` keyword (notice the capitalization) | LL - pub fn quux() {} LL + pub fn quux() {} diff --git a/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr index 6d6fd983038..47efe69cfc2 100644 --- a/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr +++ b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr @@ -8,7 +8,7 @@ LL | let x: i32 = MyS::foo; | = note: expected type `i32` found fn item `fn() -> MyS {MyS::foo}` -help: try referring to the associated const `FOO` instead (notice the capitalization difference) +help: try referring to the associated const `FOO` instead (notice the capitalization) | LL - let x: i32 = MyS::foo; LL + let x: i32 = MyS::FOO; diff --git a/tests/ui/suggestions/bool_typo_err_suggest.stderr b/tests/ui/suggestions/bool_typo_err_suggest.stderr index faf799d0fda..d46ce1ad8a9 100644 --- a/tests/ui/suggestions/bool_typo_err_suggest.stderr +++ b/tests/ui/suggestions/bool_typo_err_suggest.stderr @@ -16,7 +16,7 @@ error[E0425]: cannot find value `False` in this scope LL | let y = False; | ^^^^^ not found in this scope | -help: you may want to use a bool value instead (notice the capitalization difference) +help: you may want to use a bool value instead (notice the capitalization) | LL - let y = False; LL + let y = false; diff --git a/tests/ui/suggestions/case-difference-suggestions.rs b/tests/ui/suggestions/case-difference-suggestions.rs new file mode 100644 index 00000000000..d554b6e9367 --- /dev/null +++ b/tests/ui/suggestions/case-difference-suggestions.rs @@ -0,0 +1,57 @@ +fn main() { + + // Simple case difference, no hit + let hello = "hello"; + println!("{}", Hello); //~ ERROR cannot find value `Hello` in this scope + + // Multiple case differences, hit + let myVariable = 10; + println!("{}", myvariable); //~ ERROR cannot find value `myvariable` in this scope + + // Case difference with special characters, hit + let user_name = "john"; + println!("{}", User_Name); //~ ERROR cannot find value `User_Name` in this scope + + // All uppercase vs all lowercase, hit + let FOO = 42; + println!("{}", foo); //~ ERROR cannot find value `foo` in this scope + + + // 0 vs O + let FFO0 = 100; + println!("{}", FFOO); //~ ERROR cannot find value `FFOO` in this scope + + let l1st = vec![1, 2, 3]; + println!("{}", list); //~ ERROR cannot find value `list` in this scope + + let S5 = "test"; + println!("{}", SS); //~ ERROR cannot find value `SS` in this scope + + let aS5 = "test"; + println!("{}", a55); //~ ERROR cannot find value `a55` in this scope + + let B8 = 8; + println!("{}", BB); //~ ERROR cannot find value `BB` in this scope + + let g9 = 9; + println!("{}", gg); //~ ERROR cannot find value `gg` in this scope + + let o1d = "old"; + println!("{}", old); //~ ERROR cannot find value `old` in this scope + + let new1 = "new"; + println!("{}", newl); //~ ERROR cannot find value `newl` in this scope + + let apple = "apple"; + println!("{}", app1e); //~ ERROR cannot find value `app1e` in this scope + + let a = 1; + println!("{}", A); //~ ERROR cannot find value `A` in this scope + + let worldlu = "world"; + println!("{}", world1U); //~ ERROR cannot find value `world1U` in this scope + + let myV4rlable = 42; + println!("{}", myv4r1able); //~ ERROR cannot find value `myv4r1able` in this scope + +} diff --git a/tests/ui/suggestions/case-difference-suggestions.stderr b/tests/ui/suggestions/case-difference-suggestions.stderr new file mode 100644 index 00000000000..c3d2410a6eb --- /dev/null +++ b/tests/ui/suggestions/case-difference-suggestions.stderr @@ -0,0 +1,99 @@ +error[E0425]: cannot find value `Hello` in this scope + --> $DIR/case-difference-suggestions.rs:5:20 + | +LL | println!("{}", Hello); + | ^^^^^ help: a local variable with a similar name exists: `hello` + +error[E0425]: cannot find value `myvariable` in this scope + --> $DIR/case-difference-suggestions.rs:9:20 + | +LL | println!("{}", myvariable); + | ^^^^^^^^^^ help: a local variable with a similar name exists (notice the capitalization): `myVariable` + +error[E0425]: cannot find value `User_Name` in this scope + --> $DIR/case-difference-suggestions.rs:13:20 + | +LL | println!("{}", User_Name); + | ^^^^^^^^^ help: a local variable with a similar name exists: `user_name` + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/case-difference-suggestions.rs:17:20 + | +LL | println!("{}", foo); + | ^^^ help: a local variable with a similar name exists (notice the capitalization): `FOO` + +error[E0425]: cannot find value `FFOO` in this scope + --> $DIR/case-difference-suggestions.rs:22:20 + | +LL | println!("{}", FFOO); + | ^^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `FFO0` + +error[E0425]: cannot find value `list` in this scope + --> $DIR/case-difference-suggestions.rs:25:20 + | +LL | println!("{}", list); + | ^^^^ help: a local variable with a similar name exists: `l1st` + +error[E0425]: cannot find value `SS` in this scope + --> $DIR/case-difference-suggestions.rs:28:20 + | +LL | println!("{}", SS); + | ^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `S5` + +error[E0425]: cannot find value `a55` in this scope + --> $DIR/case-difference-suggestions.rs:31:20 + | +LL | println!("{}", a55); + | ^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `aS5` + +error[E0425]: cannot find value `BB` in this scope + --> $DIR/case-difference-suggestions.rs:34:20 + | +LL | println!("{}", BB); + | ^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `B8` + +error[E0425]: cannot find value `gg` in this scope + --> $DIR/case-difference-suggestions.rs:37:20 + | +LL | println!("{}", gg); + | ^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `g9` + +error[E0425]: cannot find value `old` in this scope + --> $DIR/case-difference-suggestions.rs:40:20 + | +LL | println!("{}", old); + | ^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `o1d` + +error[E0425]: cannot find value `newl` in this scope + --> $DIR/case-difference-suggestions.rs:43:20 + | +LL | println!("{}", newl); + | ^^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `new1` + +error[E0425]: cannot find value `app1e` in this scope + --> $DIR/case-difference-suggestions.rs:46:20 + | +LL | println!("{}", app1e); + | ^^^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `apple` + +error[E0425]: cannot find value `A` in this scope + --> $DIR/case-difference-suggestions.rs:49:20 + | +LL | println!("{}", A); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `world1U` in this scope + --> $DIR/case-difference-suggestions.rs:52:20 + | +LL | println!("{}", world1U); + | ^^^^^^^ help: a local variable with a similar name exists (notice the capitalization and digit/letter confusion): `worldlu` + +error[E0425]: cannot find value `myv4r1able` in this scope + --> $DIR/case-difference-suggestions.rs:55:20 + | +LL | println!("{}", myv4r1able); + | ^^^^^^^^^^ help: a local variable with a similar name exists (notice the capitalization and digit/letter confusion): `myV4rlable` + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/incorrect-variant-literal.svg b/tests/ui/suggestions/incorrect-variant-literal.svg index 279fd30f216..2cab1f4b60f 100644 --- a/tests/ui/suggestions/incorrect-variant-literal.svg +++ b/tests/ui/suggestions/incorrect-variant-literal.svg @@ -455,7 +455,7 @@ | - help: there is a variant with a similar name (notice the capitalization difference) + help: there is a variant with a similar name (notice the capitalization) | -- cgit 1.4.1-3-g733a5 From a78f92be9bd29b8d4d31ca97d2f5ba0bf818df08 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 31 Jul 2025 14:36:22 +0200 Subject: add tests --- tests/ui/traits/next-solver/cycles/rayon-hang-1.rs | 32 ++++++++++++++ tests/ui/traits/next-solver/cycles/rayon-hang-2.rs | 49 ++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/ui/traits/next-solver/cycles/rayon-hang-1.rs create mode 100644 tests/ui/traits/next-solver/cycles/rayon-hang-2.rs (limited to 'tests/ui') diff --git a/tests/ui/traits/next-solver/cycles/rayon-hang-1.rs b/tests/ui/traits/next-solver/cycles/rayon-hang-1.rs new file mode 100644 index 00000000000..61e1f1b200f --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/rayon-hang-1.rs @@ -0,0 +1,32 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// A regression test for trait-system-refactor-initiative#109. + +trait ParallelIterator: Sized { + type Item; +} +trait IntoParallelIterator { + type Iter: ParallelIterator; + type Item; +} +impl IntoParallelIterator for T { + type Iter = T; + type Item = T::Item; +} + +macro_rules! multizip_impls { + ($($T:ident),+) => { + fn foo<$( $T, )+>() where + $( + $T: IntoParallelIterator, + $T::Iter: ParallelIterator, + )+ + ($( $T, )+): IntoParallelIterator, + {} + } +} + +multizip_impls! { A, B, C, D, E, F, G, H, I, J, K, L } + +fn main() {} diff --git a/tests/ui/traits/next-solver/cycles/rayon-hang-2.rs b/tests/ui/traits/next-solver/cycles/rayon-hang-2.rs new file mode 100644 index 00000000000..bb5d8335dd6 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/rayon-hang-2.rs @@ -0,0 +1,49 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// A regression test for trait-system-refactor-initiative#109. +// Unlike `rayon-hang-1.rs` the cycles in this test are not +// unproductive, which causes the `AliasRelate` goal when trying +// to apply where-clauses to only error in the second iteration. +// +// This makes the exponential blowup to be significantly harder +// to avoid. + +trait ParallelIterator: Sized { + type Item; +} + +trait IntoParallelIteratorIndir { + type Iter: ParallelIterator; + type Item; +} +impl IntoParallelIteratorIndir for I +where + Box: IntoParallelIterator, +{ + type Iter = as IntoParallelIterator>::Iter; + type Item = as IntoParallelIterator>::Item; +} +trait IntoParallelIterator { + type Iter: ParallelIterator; + type Item; +} +impl IntoParallelIterator for T { + type Iter = T; + type Item = T::Item; +} + +macro_rules! multizip_impls { + ($($T:ident),+) => { + fn foo<'a, $( $T, )+>() where + $( + $T: IntoParallelIteratorIndir, + $T::Iter: ParallelIterator, + )+ + {} + } +} + +multizip_impls! { A, B, C, D, E, F, G, H, I, J, K, L } + +fn main() {} -- cgit 1.4.1-3-g733a5 From a4a5bf5a71bd0c3fb52a28f81d88ce1755b3bc30 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Thu, 24 Jul 2025 17:22:54 +0500 Subject: comments --- .../deref-chain-method-calls-13264.rs | 76 +++++++++ .../block-result/blocks-without-results-11709.rs | 39 +++++ tests/ui/block-result/blocks-without-results.rs | 37 ----- .../borrowck/moved-value-in-thread-loop-12041.rs | 15 ++ .../moved-value-in-thread-loop-12041.stderr | 11 ++ .../ui/borrowck/refcell-borrow-comparison-12033.rs | 9 ++ tests/ui/borrowck/refcell-borrow-comparison.rs | 7 - .../string-literal-match-patterns-11869.rs | 18 +++ tests/ui/closures/fnonce-moved-twice-12127.rs | 16 ++ tests/ui/closures/fnonce-moved-twice-12127.stderr | 18 +++ tests/ui/closures/fnonce-moved-twice.rs | 14 -- tests/ui/closures/moved-upvar-mut-rebind-11958.rs | 13 ++ .../closures/moved-upvar-mut-rebind-11958.stderr | 20 +++ tests/ui/closures/moved-upvar-mut-rebind.rs | 11 -- tests/ui/coercion/any-trait-object-debug-12744.rs | 7 + .../collections/hashset-connected-border-12860.rs | 51 ++++++ tests/ui/collections/hashset-connected-border.rs | 49 ------ .../ui/const-generics/vec-macro-in-static-array.rs | 2 + .../vec-macro-in-static-array.stderr | 13 ++ tests/ui/extern/format-message-windows-ffi.rs | 39 ----- tests/ui/extern/windows-tcb-trash-13259.rs | 49 ++++++ tests/ui/fn/anonymous-parameters-trait-13105.rs | 11 ++ tests/ui/fn/anonymous-parameters-trait.rs | 9 -- tests/ui/imports/use-in-impl-scope.rs | 14 -- tests/ui/issues/issue-11771.stderr | 39 ----- tests/ui/issues/issue-11844.stderr | 14 -- tests/ui/issues/issue-11958.stderr | 20 --- tests/ui/issues/issue-12041.stderr | 11 -- tests/ui/issues/issue-12127.stderr | 18 --- tests/ui/issues/issue-12567.stderr | 51 ------ tests/ui/issues/issue-12863.stderr | 9 -- tests/ui/issues/issue-13058.stderr | 14 -- tests/ui/issues/issue-13359.stderr | 39 ----- tests/ui/issues/issue-13407.stderr | 27 ---- tests/ui/issues/issue-13446.stderr | 13 -- tests/ui/issues/issue-13466.stderr | 26 --- tests/ui/iterators/bytes-iterator-clone-12677.rs | 11 ++ tests/ui/iterators/bytes-iterator-clone.rs | 9 -- tests/ui/iterators/phf-map-entries-iterator.rs | 24 --- .../iterator-trait-lifetime-error-13058.rs | 29 ++++ .../iterator-trait-lifetime-error-13058.stderr | 14 ++ .../ui/lifetimes/iterator-trait-lifetime-error.rs | 27 ---- .../lifetime-inference-destructuring-arg.rs | 26 +++ tests/ui/lifetimes/matcher-trait-equality-13323.rs | 60 +++++++ .../struct-lifetime-field-assignment-13405.rs | 21 +++ .../lifetimes/struct-lifetime-field-assignment.rs | 19 --- .../ui/lifetimes/unsafe-transmute-in-find-11740.rs | 28 ++++ tests/ui/match/function-in-pattern-error.rs | 8 - tests/ui/match/guard-literal-range-shadow.rs | 178 -------------------- tests/ui/match/option-result-mismatch-11844.rs | 10 ++ tests/ui/match/option-result-mismatch-11844.stderr | 14 ++ tests/ui/match/option-result-mismatch.rs | 8 - .../option-result-type-param-mismatch-13466.rs | 24 +++ .../option-result-type-param-mismatch-13466.stderr | 26 +++ .../ui/match/option-result-type-param-mismatch.rs | 22 --- .../ui/match/overeager-sub-match-pruning-13027.rs | 180 +++++++++++++++++++++ tests/ui/match/slice-move-out-error-12567.rs | 15 ++ tests/ui/match/slice-move-out-error-12567.stderr | 51 ++++++ tests/ui/match/slice-move-out-error.rs | 13 -- tests/ui/match/string-literal-match-patterns.rs | 16 -- tests/ui/match/struct-reference-patterns-12285.rs | 16 ++ tests/ui/match/struct-reference-patterns.rs | 14 -- tests/ui/panics/explicit-panic-unreachable.rs | 8 - tests/ui/panics/unwrap-or-panic-input.rs | 7 - tests/ui/parser/encode-symbol-ice-12920.rs | 10 ++ tests/ui/privacy/private-unit-struct-assignment.rs | 2 + .../privacy/private-unit-struct-assignment.stderr | 27 ++++ tests/ui/privacy/use-in-impl-scope-12729.rs | 16 ++ tests/ui/resolve/reference-clone-nonclone-11820.rs | 15 ++ .../statics/enum-with-static-str-variant-13214.rs | 24 +++ tests/ui/statics/enum-with-static-str-variant.rs | 22 --- tests/ui/threads/moved-value-in-thread-loop.rs | 13 -- tests/ui/traits/any-trait-object-debug.rs | 5 - .../traits/default-method-lifetime-params-13204.rs | 27 ++++ tests/ui/traits/default-method-lifetime-params.rs | 25 --- tests/ui/traits/deref-chain-method-calls.rs | 74 --------- tests/ui/traits/fnonce-repro-trait-impl-13434.rs | 23 +++ tests/ui/traits/fnonce-repro-trait-impl.rs | 21 --- tests/ui/traits/matcher-trait-equality.rs | 58 ------- tests/ui/traits/reference-clone-noclone.rs | 13 -- .../type-inference/isize-usize-mismatch-error.rs | 15 -- tests/ui/type-inference/partial-type-hint-12909.rs | 21 +++ tests/ui/type-inference/type-collect-inference.rs | 19 --- tests/ui/type-inference/unit-type-add-error.rs | 11 -- tests/ui/typeck/function-in-pattern-error-12863.rs | 10 ++ .../typeck/function-in-pattern-error-12863.stderr | 9 ++ tests/ui/typeck/isize-usize-mismatch-error.rs | 17 ++ tests/ui/typeck/isize-usize-mismatch-error.stderr | 39 +++++ tests/ui/typeck/unit-type-add-error-11771.rs | 13 ++ tests/ui/typeck/unit-type-add-error-11771.stderr | 39 +++++ tests/ui/typeck/unwrap-or-panic-input-13202.rs | 9 ++ tests/ui/unsafe/unsafe-transmute-in-find.rs | 26 --- 92 files changed, 1194 insertions(+), 1116 deletions(-) create mode 100644 tests/ui/autoref-autoderef/deref-chain-method-calls-13264.rs create mode 100644 tests/ui/block-result/blocks-without-results-11709.rs delete mode 100644 tests/ui/block-result/blocks-without-results.rs create mode 100644 tests/ui/borrowck/moved-value-in-thread-loop-12041.rs create mode 100644 tests/ui/borrowck/moved-value-in-thread-loop-12041.stderr create mode 100644 tests/ui/borrowck/refcell-borrow-comparison-12033.rs delete mode 100644 tests/ui/borrowck/refcell-borrow-comparison.rs create mode 100644 tests/ui/borrowck/string-literal-match-patterns-11869.rs create mode 100644 tests/ui/closures/fnonce-moved-twice-12127.rs create mode 100644 tests/ui/closures/fnonce-moved-twice-12127.stderr delete mode 100644 tests/ui/closures/fnonce-moved-twice.rs create mode 100644 tests/ui/closures/moved-upvar-mut-rebind-11958.rs create mode 100644 tests/ui/closures/moved-upvar-mut-rebind-11958.stderr delete mode 100644 tests/ui/closures/moved-upvar-mut-rebind.rs create mode 100644 tests/ui/coercion/any-trait-object-debug-12744.rs create mode 100644 tests/ui/collections/hashset-connected-border-12860.rs delete mode 100644 tests/ui/collections/hashset-connected-border.rs create mode 100644 tests/ui/const-generics/vec-macro-in-static-array.stderr delete mode 100644 tests/ui/extern/format-message-windows-ffi.rs create mode 100644 tests/ui/extern/windows-tcb-trash-13259.rs create mode 100644 tests/ui/fn/anonymous-parameters-trait-13105.rs delete mode 100644 tests/ui/fn/anonymous-parameters-trait.rs delete mode 100644 tests/ui/imports/use-in-impl-scope.rs delete mode 100644 tests/ui/issues/issue-11771.stderr delete mode 100644 tests/ui/issues/issue-11844.stderr delete mode 100644 tests/ui/issues/issue-11958.stderr delete mode 100644 tests/ui/issues/issue-12041.stderr delete mode 100644 tests/ui/issues/issue-12127.stderr delete mode 100644 tests/ui/issues/issue-12567.stderr delete mode 100644 tests/ui/issues/issue-12863.stderr delete mode 100644 tests/ui/issues/issue-13058.stderr delete mode 100644 tests/ui/issues/issue-13359.stderr delete mode 100644 tests/ui/issues/issue-13407.stderr delete mode 100644 tests/ui/issues/issue-13446.stderr delete mode 100644 tests/ui/issues/issue-13466.stderr create mode 100644 tests/ui/iterators/bytes-iterator-clone-12677.rs delete mode 100644 tests/ui/iterators/bytes-iterator-clone.rs delete mode 100644 tests/ui/iterators/phf-map-entries-iterator.rs create mode 100644 tests/ui/lifetimes/iterator-trait-lifetime-error-13058.rs create mode 100644 tests/ui/lifetimes/iterator-trait-lifetime-error-13058.stderr delete mode 100644 tests/ui/lifetimes/iterator-trait-lifetime-error.rs create mode 100644 tests/ui/lifetimes/lifetime-inference-destructuring-arg.rs create mode 100644 tests/ui/lifetimes/matcher-trait-equality-13323.rs create mode 100644 tests/ui/lifetimes/struct-lifetime-field-assignment-13405.rs delete mode 100644 tests/ui/lifetimes/struct-lifetime-field-assignment.rs create mode 100644 tests/ui/lifetimes/unsafe-transmute-in-find-11740.rs delete mode 100644 tests/ui/match/function-in-pattern-error.rs delete mode 100644 tests/ui/match/guard-literal-range-shadow.rs create mode 100644 tests/ui/match/option-result-mismatch-11844.rs create mode 100644 tests/ui/match/option-result-mismatch-11844.stderr delete mode 100644 tests/ui/match/option-result-mismatch.rs create mode 100644 tests/ui/match/option-result-type-param-mismatch-13466.rs create mode 100644 tests/ui/match/option-result-type-param-mismatch-13466.stderr delete mode 100644 tests/ui/match/option-result-type-param-mismatch.rs create mode 100644 tests/ui/match/overeager-sub-match-pruning-13027.rs create mode 100644 tests/ui/match/slice-move-out-error-12567.rs create mode 100644 tests/ui/match/slice-move-out-error-12567.stderr delete mode 100644 tests/ui/match/slice-move-out-error.rs delete mode 100644 tests/ui/match/string-literal-match-patterns.rs create mode 100644 tests/ui/match/struct-reference-patterns-12285.rs delete mode 100644 tests/ui/match/struct-reference-patterns.rs delete mode 100644 tests/ui/panics/explicit-panic-unreachable.rs delete mode 100644 tests/ui/panics/unwrap-or-panic-input.rs create mode 100644 tests/ui/parser/encode-symbol-ice-12920.rs create mode 100644 tests/ui/privacy/private-unit-struct-assignment.stderr create mode 100644 tests/ui/privacy/use-in-impl-scope-12729.rs create mode 100644 tests/ui/resolve/reference-clone-nonclone-11820.rs create mode 100644 tests/ui/statics/enum-with-static-str-variant-13214.rs delete mode 100644 tests/ui/statics/enum-with-static-str-variant.rs delete mode 100644 tests/ui/threads/moved-value-in-thread-loop.rs delete mode 100644 tests/ui/traits/any-trait-object-debug.rs create mode 100644 tests/ui/traits/default-method-lifetime-params-13204.rs delete mode 100644 tests/ui/traits/default-method-lifetime-params.rs delete mode 100644 tests/ui/traits/deref-chain-method-calls.rs create mode 100644 tests/ui/traits/fnonce-repro-trait-impl-13434.rs delete mode 100644 tests/ui/traits/fnonce-repro-trait-impl.rs delete mode 100644 tests/ui/traits/matcher-trait-equality.rs delete mode 100644 tests/ui/traits/reference-clone-noclone.rs delete mode 100644 tests/ui/type-inference/isize-usize-mismatch-error.rs create mode 100644 tests/ui/type-inference/partial-type-hint-12909.rs delete mode 100644 tests/ui/type-inference/type-collect-inference.rs delete mode 100644 tests/ui/type-inference/unit-type-add-error.rs create mode 100644 tests/ui/typeck/function-in-pattern-error-12863.rs create mode 100644 tests/ui/typeck/function-in-pattern-error-12863.stderr create mode 100644 tests/ui/typeck/isize-usize-mismatch-error.rs create mode 100644 tests/ui/typeck/isize-usize-mismatch-error.stderr create mode 100644 tests/ui/typeck/unit-type-add-error-11771.rs create mode 100644 tests/ui/typeck/unit-type-add-error-11771.stderr create mode 100644 tests/ui/typeck/unwrap-or-panic-input-13202.rs delete mode 100644 tests/ui/unsafe/unsafe-transmute-in-find.rs (limited to 'tests/ui') diff --git a/tests/ui/autoref-autoderef/deref-chain-method-calls-13264.rs b/tests/ui/autoref-autoderef/deref-chain-method-calls-13264.rs new file mode 100644 index 00000000000..f471c1c7eef --- /dev/null +++ b/tests/ui/autoref-autoderef/deref-chain-method-calls-13264.rs @@ -0,0 +1,76 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13264 + +//@ run-pass +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use std::ops::Deref; + +struct Root { + jsref: JSRef +} + +impl Deref for Root { + type Target = JSRef; + + fn deref<'a>(&'a self) -> &'a JSRef { + &self.jsref + } +} + +#[derive(Copy, Clone)] +struct JSRef { + node: *const Node +} + +impl Deref for JSRef { + type Target = Node; + + fn deref<'a>(&'a self) -> &'a Node { + self.get() + } +} + +trait INode { + fn RemoveChild(&self); +} + +impl INode for JSRef { + fn RemoveChild(&self) { + self.get().RemoveChild(0) + } +} + +impl JSRef { + fn AddChild(&self) { + self.get().AddChild(0); + } + + fn get<'a>(&'a self) -> &'a Node { + unsafe { + &*self.node + } + } +} + +struct Node; + +impl Node { + fn RemoveChild(&self, _a: usize) { + } + + fn AddChild(&self, _a: usize) { + } +} + +fn main() { + let n = Node; + let jsref = JSRef { node: &n }; + let root = Root { jsref: jsref }; + + root.AddChild(); + jsref.AddChild(); + + root.RemoveChild(); + jsref.RemoveChild(); +} diff --git a/tests/ui/block-result/blocks-without-results-11709.rs b/tests/ui/block-result/blocks-without-results-11709.rs new file mode 100644 index 00000000000..97ea6f9e19e --- /dev/null +++ b/tests/ui/block-result/blocks-without-results-11709.rs @@ -0,0 +1,39 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/11709 + +//@ run-pass +#![allow(dead_code)] + +// Don't panic on blocks without results +// There are several tests in this run-pass that raised +// when this bug was opened. The cases where the compiler +// panics before the fix have a comment. + +struct S {x:()} + +fn test(slot: &mut Option Box>>) -> () { + let a = slot.take(); + let _a: () = match a { + // `{let .. a(); }` would break + Some(mut a) => { let _a = a(); }, + None => (), + }; +} + +fn not(b: bool) -> bool { + if b { + !b + } else { + // `panic!(...)` would break + panic!("Break the compiler"); + } +} + +pub fn main() { + // {} would break + let _r: () = {}; + let mut slot = None; + // `{ test(...); }` would break + let _s : S = S{ x: { test(&mut slot); } }; + + let _b = not(true); +} diff --git a/tests/ui/block-result/blocks-without-results.rs b/tests/ui/block-result/blocks-without-results.rs deleted file mode 100644 index 8a11074eca8..00000000000 --- a/tests/ui/block-result/blocks-without-results.rs +++ /dev/null @@ -1,37 +0,0 @@ -//@ run-pass -#![allow(dead_code)] - -// Don't panic on blocks without results -// There are several tests in this run-pass that raised -// when this bug was opened. The cases where the compiler -// panics before the fix have a comment. - -struct S {x:()} - -fn test(slot: &mut Option Box>>) -> () { - let a = slot.take(); - let _a: () = match a { - // `{let .. a(); }` would break - Some(mut a) => { let _a = a(); }, - None => (), - }; -} - -fn not(b: bool) -> bool { - if b { - !b - } else { - // `panic!(...)` would break - panic!("Break the compiler"); - } -} - -pub fn main() { - // {} would break - let _r: () = {}; - let mut slot = None; - // `{ test(...); }` would break - let _s : S = S{ x: { test(&mut slot); } }; - - let _b = not(true); -} diff --git a/tests/ui/borrowck/moved-value-in-thread-loop-12041.rs b/tests/ui/borrowck/moved-value-in-thread-loop-12041.rs new file mode 100644 index 00000000000..98f9cdbdef7 --- /dev/null +++ b/tests/ui/borrowck/moved-value-in-thread-loop-12041.rs @@ -0,0 +1,15 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12041 + +use std::sync::mpsc::channel; +use std::thread; + +fn main() { + let (tx, rx) = channel(); + let _t = thread::spawn(move|| -> () { + loop { + let tx = tx; + //~^ ERROR: use of moved value: `tx` + tx.send(1); + } + }); +} diff --git a/tests/ui/borrowck/moved-value-in-thread-loop-12041.stderr b/tests/ui/borrowck/moved-value-in-thread-loop-12041.stderr new file mode 100644 index 00000000000..627dd193dad --- /dev/null +++ b/tests/ui/borrowck/moved-value-in-thread-loop-12041.stderr @@ -0,0 +1,11 @@ +error[E0382]: use of moved value: `tx` + --> $DIR/moved-value-in-thread-loop-12041.rs:10:22 + | +LL | let tx = tx; + | ^^ value moved here, in previous iteration of loop + | + = note: move occurs because `tx` has type `std::sync::mpsc::Sender`, which does not implement the `Copy` trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/refcell-borrow-comparison-12033.rs b/tests/ui/borrowck/refcell-borrow-comparison-12033.rs new file mode 100644 index 00000000000..de22cedd5b9 --- /dev/null +++ b/tests/ui/borrowck/refcell-borrow-comparison-12033.rs @@ -0,0 +1,9 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12033 + +//@ run-pass +use std::cell::RefCell; + +fn main() { + let x = RefCell::new(0); + if *x.borrow() == 0 {} else {} +} diff --git a/tests/ui/borrowck/refcell-borrow-comparison.rs b/tests/ui/borrowck/refcell-borrow-comparison.rs deleted file mode 100644 index 0bf6490bafe..00000000000 --- a/tests/ui/borrowck/refcell-borrow-comparison.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -use std::cell::RefCell; - -fn main() { - let x = RefCell::new(0); - if *x.borrow() == 0 {} else {} -} diff --git a/tests/ui/borrowck/string-literal-match-patterns-11869.rs b/tests/ui/borrowck/string-literal-match-patterns-11869.rs new file mode 100644 index 00000000000..4c159e457cf --- /dev/null +++ b/tests/ui/borrowck/string-literal-match-patterns-11869.rs @@ -0,0 +1,18 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/11869 + +//@ check-pass +#![allow(dead_code)] + +struct A { + a: String +} + +fn borrow<'a>(binding: &'a A) -> &'a str { + match &*binding.a { + "in" => "in_", + "ref" => "ref_", + ident => ident + } +} + +fn main() {} diff --git a/tests/ui/closures/fnonce-moved-twice-12127.rs b/tests/ui/closures/fnonce-moved-twice-12127.rs new file mode 100644 index 00000000000..369ddcafaab --- /dev/null +++ b/tests/ui/closures/fnonce-moved-twice-12127.rs @@ -0,0 +1,16 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12127 + +#![feature(unboxed_closures, tuple_trait)] + +fn to_fn_once>(f: F) -> F { f } +fn do_it(x: &isize) { } + +fn main() { + let x: Box<_> = Box::new(22); + let f = to_fn_once(move|| do_it(&*x)); + to_fn_once(move|| { + f(); + f(); + //~^ ERROR: use of moved value: `f` + })() +} diff --git a/tests/ui/closures/fnonce-moved-twice-12127.stderr b/tests/ui/closures/fnonce-moved-twice-12127.stderr new file mode 100644 index 00000000000..c2e12827527 --- /dev/null +++ b/tests/ui/closures/fnonce-moved-twice-12127.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `f` + --> $DIR/fnonce-moved-twice-12127.rs:13:9 + | +LL | f(); + | --- `f` moved due to this call +LL | f(); + | ^ value used here after move + | +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/fnonce-moved-twice-12127.rs:12:9 + | +LL | f(); + | ^ + = note: move occurs because `f` has type `{closure@$DIR/fnonce-moved-twice-12127.rs:10:24: 10:30}`, which does not implement the `Copy` trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/fnonce-moved-twice.rs b/tests/ui/closures/fnonce-moved-twice.rs deleted file mode 100644 index 199d542e816..00000000000 --- a/tests/ui/closures/fnonce-moved-twice.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(unboxed_closures, tuple_trait)] - -fn to_fn_once>(f: F) -> F { f } -fn do_it(x: &isize) { } - -fn main() { - let x: Box<_> = Box::new(22); - let f = to_fn_once(move|| do_it(&*x)); - to_fn_once(move|| { - f(); - f(); - //~^ ERROR: use of moved value: `f` - })() -} diff --git a/tests/ui/closures/moved-upvar-mut-rebind-11958.rs b/tests/ui/closures/moved-upvar-mut-rebind-11958.rs new file mode 100644 index 00000000000..701dc1a2cef --- /dev/null +++ b/tests/ui/closures/moved-upvar-mut-rebind-11958.rs @@ -0,0 +1,13 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/11958 + +//@ run-pass + +// We shouldn't need to rebind a moved upvar as mut if it's already +// marked as mut + +pub fn main() { + let mut x = 1; + let _thunk = Box::new(move|| { x = 2; }); + //~^ WARN value assigned to `x` is never read + //~| WARN unused variable: `x` +} diff --git a/tests/ui/closures/moved-upvar-mut-rebind-11958.stderr b/tests/ui/closures/moved-upvar-mut-rebind-11958.stderr new file mode 100644 index 00000000000..b12bbcad925 --- /dev/null +++ b/tests/ui/closures/moved-upvar-mut-rebind-11958.stderr @@ -0,0 +1,20 @@ +warning: value assigned to `x` is never read + --> $DIR/moved-upvar-mut-rebind-11958.rs:10:36 + | +LL | let _thunk = Box::new(move|| { x = 2; }); + | ^ + | + = help: maybe it is overwritten before being read? + = note: `#[warn(unused_assignments)]` on by default + +warning: unused variable: `x` + --> $DIR/moved-upvar-mut-rebind-11958.rs:10:36 + | +LL | let _thunk = Box::new(move|| { x = 2; }); + | ^ + | + = help: did you mean to capture by reference instead? + = note: `#[warn(unused_variables)]` on by default + +warning: 2 warnings emitted + diff --git a/tests/ui/closures/moved-upvar-mut-rebind.rs b/tests/ui/closures/moved-upvar-mut-rebind.rs deleted file mode 100644 index 9185c5158af..00000000000 --- a/tests/ui/closures/moved-upvar-mut-rebind.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass - -// We shouldn't need to rebind a moved upvar as mut if it's already -// marked as mut - -pub fn main() { - let mut x = 1; - let _thunk = Box::new(move|| { x = 2; }); - //~^ WARN value assigned to `x` is never read - //~| WARN unused variable: `x` -} diff --git a/tests/ui/coercion/any-trait-object-debug-12744.rs b/tests/ui/coercion/any-trait-object-debug-12744.rs new file mode 100644 index 00000000000..4d981c077ee --- /dev/null +++ b/tests/ui/coercion/any-trait-object-debug-12744.rs @@ -0,0 +1,7 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12744 + +//@ run-pass +fn main() { + fn test() -> Box { Box::new(1) } + println!("{:?}", test()) +} diff --git a/tests/ui/collections/hashset-connected-border-12860.rs b/tests/ui/collections/hashset-connected-border-12860.rs new file mode 100644 index 00000000000..40185bef7c8 --- /dev/null +++ b/tests/ui/collections/hashset-connected-border-12860.rs @@ -0,0 +1,51 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12860 + +//@ run-pass +use std::collections::HashSet; + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +struct XYZ { + x: isize, + y: isize, + z: isize +} + +fn main() { + let mut connected = HashSet::new(); + let mut border = HashSet::new(); + + let middle = XYZ{x: 0, y: 0, z: 0}; + border.insert(middle); + + while !border.is_empty() && connected.len() < 10000 { + let choice = *(border.iter().next().unwrap()); + border.remove(&choice); + connected.insert(choice); + + let cxp = XYZ{x: choice.x + 1, y: choice.y, z: choice.z}; + let cxm = XYZ{x: choice.x - 1, y: choice.y, z: choice.z}; + let cyp = XYZ{x: choice.x, y: choice.y + 1, z: choice.z}; + let cym = XYZ{x: choice.x, y: choice.y - 1, z: choice.z}; + let czp = XYZ{x: choice.x, y: choice.y, z: choice.z + 1}; + let czm = XYZ{x: choice.x, y: choice.y, z: choice.z - 1}; + + if !connected.contains(&cxp) { + border.insert(cxp); + } + if !connected.contains(&cxm){ + border.insert(cxm); + } + if !connected.contains(&cyp){ + border.insert(cyp); + } + if !connected.contains(&cym) { + border.insert(cym); + } + if !connected.contains(&czp){ + border.insert(czp); + } + if !connected.contains(&czm) { + border.insert(czm); + } + } +} diff --git a/tests/ui/collections/hashset-connected-border.rs b/tests/ui/collections/hashset-connected-border.rs deleted file mode 100644 index 255f6670793..00000000000 --- a/tests/ui/collections/hashset-connected-border.rs +++ /dev/null @@ -1,49 +0,0 @@ -//@ run-pass -use std::collections::HashSet; - -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -struct XYZ { - x: isize, - y: isize, - z: isize -} - -fn main() { - let mut connected = HashSet::new(); - let mut border = HashSet::new(); - - let middle = XYZ{x: 0, y: 0, z: 0}; - border.insert(middle); - - while !border.is_empty() && connected.len() < 10000 { - let choice = *(border.iter().next().unwrap()); - border.remove(&choice); - connected.insert(choice); - - let cxp = XYZ{x: choice.x + 1, y: choice.y, z: choice.z}; - let cxm = XYZ{x: choice.x - 1, y: choice.y, z: choice.z}; - let cyp = XYZ{x: choice.x, y: choice.y + 1, z: choice.z}; - let cym = XYZ{x: choice.x, y: choice.y - 1, z: choice.z}; - let czp = XYZ{x: choice.x, y: choice.y, z: choice.z + 1}; - let czm = XYZ{x: choice.x, y: choice.y, z: choice.z - 1}; - - if !connected.contains(&cxp) { - border.insert(cxp); - } - if !connected.contains(&cxm){ - border.insert(cxm); - } - if !connected.contains(&cyp){ - border.insert(cyp); - } - if !connected.contains(&cym) { - border.insert(cym); - } - if !connected.contains(&czp){ - border.insert(czp); - } - if !connected.contains(&czm) { - border.insert(czm); - } - } -} diff --git a/tests/ui/const-generics/vec-macro-in-static-array.rs b/tests/ui/const-generics/vec-macro-in-static-array.rs index 9f1fc42774f..7a81836e255 100644 --- a/tests/ui/const-generics/vec-macro-in-static-array.rs +++ b/tests/ui/const-generics/vec-macro-in-static-array.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13446 + // Used to cause ICE static VEC: [u32; 256] = vec![]; diff --git a/tests/ui/const-generics/vec-macro-in-static-array.stderr b/tests/ui/const-generics/vec-macro-in-static-array.stderr new file mode 100644 index 00000000000..de21f2274f3 --- /dev/null +++ b/tests/ui/const-generics/vec-macro-in-static-array.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/vec-macro-in-static-array.rs:5:26 + | +LL | static VEC: [u32; 256] = vec![]; + | ^^^^^^ expected `[u32; 256]`, found `Vec<_>` + | + = note: expected array `[u32; 256]` + found struct `Vec<_>` + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/extern/format-message-windows-ffi.rs b/tests/ui/extern/format-message-windows-ffi.rs deleted file mode 100644 index 381e3f15259..00000000000 --- a/tests/ui/extern/format-message-windows-ffi.rs +++ /dev/null @@ -1,39 +0,0 @@ -//@ run-pass - -#[cfg(windows)] -mod imp { - type LPVOID = *mut u8; - type DWORD = u32; - type LPWSTR = *mut u16; - - extern "system" { - fn FormatMessageW(flags: DWORD, - lpSrc: LPVOID, - msgId: DWORD, - langId: DWORD, - buf: LPWSTR, - nsize: DWORD, - args: *const u8) - -> DWORD; - } - - pub fn test() { - let mut buf: [u16; 50] = [0; 50]; - let ret = unsafe { - FormatMessageW(0x1000, core::ptr::null_mut(), 1, 0x400, - buf.as_mut_ptr(), buf.len() as u32, core::ptr::null()) - }; - // On some 32-bit Windowses (Win7-8 at least) this will panic with segmented - // stacks taking control of pvArbitrary - assert!(ret != 0); - } -} - -#[cfg(not(windows))] -mod imp { - pub fn test() { } -} - -fn main() { - imp::test() -} diff --git a/tests/ui/extern/windows-tcb-trash-13259.rs b/tests/ui/extern/windows-tcb-trash-13259.rs new file mode 100644 index 00000000000..0852e31251a --- /dev/null +++ b/tests/ui/extern/windows-tcb-trash-13259.rs @@ -0,0 +1,49 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13259 + +//@ run-pass + +#[cfg(windows)] +mod imp { + type LPVOID = *mut u8; + type DWORD = u32; + type LPWSTR = *mut u16; + + extern "system" { + fn FormatMessageW( + flags: DWORD, + lpSrc: LPVOID, + msgId: DWORD, + langId: DWORD, + buf: LPWSTR, + nsize: DWORD, + args: *const u8, + ) -> DWORD; + } + + pub fn test() { + let mut buf: [u16; 50] = [0; 50]; + let ret = unsafe { + FormatMessageW( + 0x1000, + core::ptr::null_mut(), + 1, + 0x400, + buf.as_mut_ptr(), + buf.len() as u32, + core::ptr::null(), + ) + }; + // On some 32-bit Windowses (Win7-8 at least) this will panic with segmented + // stacks taking control of pvArbitrary + assert!(ret != 0); + } +} + +#[cfg(not(windows))] +mod imp { + pub fn test() {} +} + +fn main() { + imp::test() +} diff --git a/tests/ui/fn/anonymous-parameters-trait-13105.rs b/tests/ui/fn/anonymous-parameters-trait-13105.rs new file mode 100644 index 00000000000..171dab15fe7 --- /dev/null +++ b/tests/ui/fn/anonymous-parameters-trait-13105.rs @@ -0,0 +1,11 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13105 + +//@ edition: 2015 +//@ check-pass + +trait Foo { + #[allow(anonymous_parameters)] + fn quux(u8) {} +} + +fn main() {} diff --git a/tests/ui/fn/anonymous-parameters-trait.rs b/tests/ui/fn/anonymous-parameters-trait.rs deleted file mode 100644 index d119aa9c788..00000000000 --- a/tests/ui/fn/anonymous-parameters-trait.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ edition: 2015 -//@ check-pass - -trait Foo { - #[allow(anonymous_parameters)] - fn quux(u8) {} -} - -fn main() {} diff --git a/tests/ui/imports/use-in-impl-scope.rs b/tests/ui/imports/use-in-impl-scope.rs deleted file mode 100644 index 4d45846bc60..00000000000 --- a/tests/ui/imports/use-in-impl-scope.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ edition: 2015 -//@ check-pass -#![allow(dead_code)] - -pub struct Foo; - -mod bar { - use Foo; - - impl Foo { - fn baz(&self) {} - } -} -fn main() {} diff --git a/tests/ui/issues/issue-11771.stderr b/tests/ui/issues/issue-11771.stderr deleted file mode 100644 index 5603dc18b63..00000000000 --- a/tests/ui/issues/issue-11771.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0277]: cannot add `()` to `{integer}` - --> $DIR/issue-11771.rs:3:7 - | -LL | 1 + - | ^ no implementation for `{integer} + ()` - | - = help: the trait `Add<()>` is not implemented for `{integer}` - = help: the following other types implement trait `Add`: - `&f128` implements `Add` - `&f128` implements `Add` - `&f16` implements `Add` - `&f16` implements `Add` - `&f32` implements `Add` - `&f32` implements `Add` - `&f64` implements `Add` - `&f64` implements `Add` - and 56 others - -error[E0277]: cannot add `()` to `{integer}` - --> $DIR/issue-11771.rs:8:7 - | -LL | 1 + - | ^ no implementation for `{integer} + ()` - | - = help: the trait `Add<()>` is not implemented for `{integer}` - = help: the following other types implement trait `Add`: - `&f128` implements `Add` - `&f128` implements `Add` - `&f16` implements `Add` - `&f16` implements `Add` - `&f32` implements `Add` - `&f32` implements `Add` - `&f64` implements `Add` - `&f64` implements `Add` - and 56 others - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-11844.stderr b/tests/ui/issues/issue-11844.stderr deleted file mode 100644 index 9ff66eaef49..00000000000 --- a/tests/ui/issues/issue-11844.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-11844.rs:4:9 - | -LL | match a { - | - this expression has type `Option>` -LL | Ok(a) => - | ^^^^^ expected `Option>`, found `Result<_, _>` - | - = note: expected enum `Option>` - found enum `Result<_, _>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-11958.stderr b/tests/ui/issues/issue-11958.stderr deleted file mode 100644 index 5dca4c2f01d..00000000000 --- a/tests/ui/issues/issue-11958.stderr +++ /dev/null @@ -1,20 +0,0 @@ -warning: value assigned to `x` is never read - --> $DIR/issue-11958.rs:8:36 - | -LL | let _thunk = Box::new(move|| { x = 2; }); - | ^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: unused variable: `x` - --> $DIR/issue-11958.rs:8:36 - | -LL | let _thunk = Box::new(move|| { x = 2; }); - | ^ - | - = help: did you mean to capture by reference instead? - = note: `#[warn(unused_variables)]` on by default - -warning: 2 warnings emitted - diff --git a/tests/ui/issues/issue-12041.stderr b/tests/ui/issues/issue-12041.stderr deleted file mode 100644 index f2c10b83383..00000000000 --- a/tests/ui/issues/issue-12041.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0382]: use of moved value: `tx` - --> $DIR/issue-12041.rs:8:22 - | -LL | let tx = tx; - | ^^ value moved here, in previous iteration of loop - | - = note: move occurs because `tx` has type `std::sync::mpsc::Sender`, which does not implement the `Copy` trait - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-12127.stderr b/tests/ui/issues/issue-12127.stderr deleted file mode 100644 index 2a6233547ee..00000000000 --- a/tests/ui/issues/issue-12127.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0382]: use of moved value: `f` - --> $DIR/issue-12127.rs:11:9 - | -LL | f(); - | --- `f` moved due to this call -LL | f(); - | ^ value used here after move - | -note: this value implements `FnOnce`, which causes it to be moved when called - --> $DIR/issue-12127.rs:10:9 - | -LL | f(); - | ^ - = note: move occurs because `f` has type `{closure@$DIR/issue-12127.rs:8:24: 8:30}`, which does not implement the `Copy` trait - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-12567.stderr b/tests/ui/issues/issue-12567.stderr deleted file mode 100644 index 0b19299ece3..00000000000 --- a/tests/ui/issues/issue-12567.stderr +++ /dev/null @@ -1,51 +0,0 @@ -error[E0508]: cannot move out of type `[T]`, a non-copy slice - --> $DIR/issue-12567.rs:2:11 - | -LL | match (l1, l2) { - | ^^^^^^^^ cannot move out of here -... -LL | (&[], &[hd, ..]) | (&[hd, ..], &[]) - | -- data moved here -LL | => println!("one empty"), -LL | (&[hd1, ..], &[hd2, ..]) - | --- ...and here - | - = note: move occurs because these variables have types that don't implement the `Copy` trait -help: consider removing the borrow - | -LL - (&[], &[hd, ..]) | (&[hd, ..], &[]) -LL + (&[], [hd, ..]) | (&[hd, ..], &[]) - | -help: consider removing the borrow - | -LL - (&[hd1, ..], &[hd2, ..]) -LL + (&[hd1, ..], [hd2, ..]) - | - -error[E0508]: cannot move out of type `[T]`, a non-copy slice - --> $DIR/issue-12567.rs:2:11 - | -LL | match (l1, l2) { - | ^^^^^^^^ cannot move out of here -... -LL | (&[], &[hd, ..]) | (&[hd, ..], &[]) - | -- data moved here -LL | => println!("one empty"), -LL | (&[hd1, ..], &[hd2, ..]) - | --- ...and here - | - = note: move occurs because these variables have types that don't implement the `Copy` trait -help: consider removing the borrow - | -LL - (&[], &[hd, ..]) | (&[hd, ..], &[]) -LL + (&[], [hd, ..]) | (&[hd, ..], &[]) - | -help: consider removing the borrow - | -LL - (&[hd1, ..], &[hd2, ..]) -LL + ([hd1, ..], &[hd2, ..]) - | - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/issues/issue-12863.stderr b/tests/ui/issues/issue-12863.stderr deleted file mode 100644 index 95d4a704e72..00000000000 --- a/tests/ui/issues/issue-12863.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0532]: expected unit struct, unit variant or constant, found function `foo::bar` - --> $DIR/issue-12863.rs:5:9 - | -LL | foo::bar => {} - | ^^^^^^^^ not a unit struct, unit variant or constant - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-13058.stderr b/tests/ui/issues/issue-13058.stderr deleted file mode 100644 index 4f4108fa182..00000000000 --- a/tests/ui/issues/issue-13058.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0621]: explicit lifetime required in the type of `cont` - --> $DIR/issue-13058.rs:14:21 - | -LL | let cont_iter = cont.iter(); - | ^^^^^^^^^^^ lifetime `'r` required - | -help: add explicit lifetime `'r` to the type of `cont` - | -LL | fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &'r T) -> bool - | ++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-13359.stderr b/tests/ui/issues/issue-13359.stderr deleted file mode 100644 index 91f5de8e8f3..00000000000 --- a/tests/ui/issues/issue-13359.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-13359.rs:8:9 - | -LL | foo(1*(1 as isize)); - | --- ^^^^^^^^^^^^^^ expected `i16`, found `isize` - | | - | arguments to this function are incorrect - | -note: function defined here - --> $DIR/issue-13359.rs:3:4 - | -LL | fn foo(_s: i16) { } - | ^^^ ------- -help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit - | -LL | foo((1*(1 as isize)).try_into().unwrap()); - | + +++++++++++++++++++++ - -error[E0308]: mismatched types - --> $DIR/issue-13359.rs:12:9 - | -LL | bar(1*(1 as usize)); - | --- ^^^^^^^^^^^^^^ expected `u32`, found `usize` - | | - | arguments to this function are incorrect - | -note: function defined here - --> $DIR/issue-13359.rs:5:4 - | -LL | fn bar(_s: u32) { } - | ^^^ ------- -help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit - | -LL | bar((1*(1 as usize)).try_into().unwrap()); - | + +++++++++++++++++++++ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13407.stderr b/tests/ui/issues/issue-13407.stderr deleted file mode 100644 index ac2eb6581fe..00000000000 --- a/tests/ui/issues/issue-13407.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0603]: unit struct `C` is private - --> $DIR/issue-13407.rs:6:8 - | -LL | A::C = 1; - | ^ private unit struct - | -note: the unit struct `C` is defined here - --> $DIR/issue-13407.rs:2:5 - | -LL | struct C; - | ^^^^^^^^^ - -error[E0308]: mismatched types - --> $DIR/issue-13407.rs:6:5 - | -LL | struct C; - | -------- unit struct defined here -... -LL | A::C = 1; - | ^^^^ - this expression has type `{integer}` - | | - | expected integer, found `C` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0308, E0603. -For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13446.stderr b/tests/ui/issues/issue-13446.stderr deleted file mode 100644 index 28c459e6e62..00000000000 --- a/tests/ui/issues/issue-13446.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-13446.rs:3:26 - | -LL | static VEC: [u32; 256] = vec![]; - | ^^^^^^ expected `[u32; 256]`, found `Vec<_>` - | - = note: expected array `[u32; 256]` - found struct `Vec<_>` - = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13466.stderr b/tests/ui/issues/issue-13466.stderr deleted file mode 100644 index 68a555a1626..00000000000 --- a/tests/ui/issues/issue-13466.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-13466.rs:10:9 - | -LL | let _x: usize = match Some(1) { - | ------- this expression has type `Option<{integer}>` -LL | Ok(u) => u, - | ^^^^^ expected `Option<{integer}>`, found `Result<_, _>` - | - = note: expected enum `Option<{integer}>` - found enum `Result<_, _>` - -error[E0308]: mismatched types - --> $DIR/issue-13466.rs:16:9 - | -LL | let _x: usize = match Some(1) { - | ------- this expression has type `Option<{integer}>` -... -LL | Err(e) => panic!(e) - | ^^^^^^ expected `Option<{integer}>`, found `Result<_, _>` - | - = note: expected enum `Option<{integer}>` - found enum `Result<_, _>` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/iterators/bytes-iterator-clone-12677.rs b/tests/ui/iterators/bytes-iterator-clone-12677.rs new file mode 100644 index 00000000000..cfbb85a3ecb --- /dev/null +++ b/tests/ui/iterators/bytes-iterator-clone-12677.rs @@ -0,0 +1,11 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12677 + +//@ run-pass + +fn main() { + let s = "Hello"; + let first = s.bytes(); + let second = first.clone(); + + assert_eq!(first.collect::>(), second.collect::>()) +} diff --git a/tests/ui/iterators/bytes-iterator-clone.rs b/tests/ui/iterators/bytes-iterator-clone.rs deleted file mode 100644 index dbc2dbc8527..00000000000 --- a/tests/ui/iterators/bytes-iterator-clone.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass - -fn main() { - let s = "Hello"; - let first = s.bytes(); - let second = first.clone(); - - assert_eq!(first.collect::>(), second.collect::>()) -} diff --git a/tests/ui/iterators/phf-map-entries-iterator.rs b/tests/ui/iterators/phf-map-entries-iterator.rs deleted file mode 100644 index 5f733e85948..00000000000 --- a/tests/ui/iterators/phf-map-entries-iterator.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ check-pass -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver - -use std::slice; - -pub struct PhfMapEntries<'a, T: 'a> { - iter: slice::Iter<'a, (&'static str, T)>, -} - -impl<'a, T> Iterator for PhfMapEntries<'a, T> { - type Item = (&'static str, &'a T); - - fn next(&mut self) -> Option<(&'static str, &'a T)> { - self.iter.by_ref().map(|&(key, ref value)| (key, value)).next() - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -fn main() {} diff --git a/tests/ui/lifetimes/iterator-trait-lifetime-error-13058.rs b/tests/ui/lifetimes/iterator-trait-lifetime-error-13058.rs new file mode 100644 index 00000000000..6cfe440b43d --- /dev/null +++ b/tests/ui/lifetimes/iterator-trait-lifetime-error-13058.rs @@ -0,0 +1,29 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13058 + +use std::ops::Range; + +trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } + +impl<'r> Itble<'r, usize, Range> for (usize, usize) { + fn iter(&'r self) -> Range { + let &(min, max) = self; + min..max + } +} + +fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool +{ + let cont_iter = cont.iter(); +//~^ ERROR explicit lifetime required in the type of `cont` [E0621] + let result = cont_iter.fold(Some(0), |state, val| { + state.map_or(None, |mask| { + let bit = 1 << val; + if mask & bit == 0 {Some(mask|bit)} else {None} + }) + }); + result.is_some() +} + +fn main() { + check(&(3, 5)); +} diff --git a/tests/ui/lifetimes/iterator-trait-lifetime-error-13058.stderr b/tests/ui/lifetimes/iterator-trait-lifetime-error-13058.stderr new file mode 100644 index 00000000000..e6564e36b21 --- /dev/null +++ b/tests/ui/lifetimes/iterator-trait-lifetime-error-13058.stderr @@ -0,0 +1,14 @@ +error[E0621]: explicit lifetime required in the type of `cont` + --> $DIR/iterator-trait-lifetime-error-13058.rs:16:21 + | +LL | let cont_iter = cont.iter(); + | ^^^^^^^^^^^ lifetime `'r` required + | +help: add explicit lifetime `'r` to the type of `cont` + | +LL | fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &'r T) -> bool + | ++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/iterator-trait-lifetime-error.rs b/tests/ui/lifetimes/iterator-trait-lifetime-error.rs deleted file mode 100644 index a5806feb720..00000000000 --- a/tests/ui/lifetimes/iterator-trait-lifetime-error.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::ops::Range; - -trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } - -impl<'r> Itble<'r, usize, Range> for (usize, usize) { - fn iter(&'r self) -> Range { - let &(min, max) = self; - min..max - } -} - -fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool -{ - let cont_iter = cont.iter(); -//~^ ERROR explicit lifetime required in the type of `cont` [E0621] - let result = cont_iter.fold(Some(0), |state, val| { - state.map_or(None, |mask| { - let bit = 1 << val; - if mask & bit == 0 {Some(mask|bit)} else {None} - }) - }); - result.is_some() -} - -fn main() { - check(&(3, 5)); -} diff --git a/tests/ui/lifetimes/lifetime-inference-destructuring-arg.rs b/tests/ui/lifetimes/lifetime-inference-destructuring-arg.rs new file mode 100644 index 00000000000..7a019a71d75 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-inference-destructuring-arg.rs @@ -0,0 +1,26 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13167 + +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +use std::slice; + +pub struct PhfMapEntries<'a, T: 'a> { + iter: slice::Iter<'a, (&'static str, T)>, +} + +impl<'a, T> Iterator for PhfMapEntries<'a, T> { + type Item = (&'static str, &'a T); + + fn next(&mut self) -> Option<(&'static str, &'a T)> { + self.iter.by_ref().map(|&(key, ref value)| (key, value)).next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/matcher-trait-equality-13323.rs b/tests/ui/lifetimes/matcher-trait-equality-13323.rs new file mode 100644 index 00000000000..efd56294b39 --- /dev/null +++ b/tests/ui/lifetimes/matcher-trait-equality-13323.rs @@ -0,0 +1,60 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13323 + +//@ run-pass + +struct StrWrap { + s: String +} + +impl StrWrap { + fn new(s: &str) -> StrWrap { + StrWrap { s: s.to_string() } + } + + fn get_s<'a>(&'a self) -> &'a str { + &self.s + } +} + +struct MyStruct { + s: StrWrap +} + +impl MyStruct { + fn new(s: &str) -> MyStruct { + MyStruct { s: StrWrap::new(s) } + } + + fn get_str_wrap<'a>(&'a self) -> &'a StrWrap { + &self.s + } +} + +trait Matcher { + fn matches(&self, actual: T) -> bool; +} + +fn assert_that>(actual: T, matcher: &U) { + assert!(matcher.matches(actual)); +} + +struct EqualTo { + expected: T +} + +impl Matcher for EqualTo { + fn matches(&self, actual: T) -> bool { + self.expected.eq(&actual) + } +} + +fn equal_to(expected: T) -> Box> { + Box::new(EqualTo { expected: expected }) +} + +pub fn main() { + let my_struct = MyStruct::new("zomg"); + let s = my_struct.get_str_wrap(); + + assert_that(s.get_s(), &*equal_to("zomg")); +} diff --git a/tests/ui/lifetimes/struct-lifetime-field-assignment-13405.rs b/tests/ui/lifetimes/struct-lifetime-field-assignment-13405.rs new file mode 100644 index 00000000000..9482d89681b --- /dev/null +++ b/tests/ui/lifetimes/struct-lifetime-field-assignment-13405.rs @@ -0,0 +1,21 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13405 + +//@ check-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Foo<'a> { + i: &'a bool, + j: Option<&'a isize>, +} + +impl<'a> Foo<'a> { + fn bar(&mut self, j: &isize) { + let child = Foo { + i: self.i, + j: Some(j) + }; + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/struct-lifetime-field-assignment.rs b/tests/ui/lifetimes/struct-lifetime-field-assignment.rs deleted file mode 100644 index 80b298d2f37..00000000000 --- a/tests/ui/lifetimes/struct-lifetime-field-assignment.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ check-pass -#![allow(dead_code)] -#![allow(unused_variables)] - -struct Foo<'a> { - i: &'a bool, - j: Option<&'a isize>, -} - -impl<'a> Foo<'a> { - fn bar(&mut self, j: &isize) { - let child = Foo { - i: self.i, - j: Some(j) - }; - } -} - -fn main() {} diff --git a/tests/ui/lifetimes/unsafe-transmute-in-find-11740.rs b/tests/ui/lifetimes/unsafe-transmute-in-find-11740.rs new file mode 100644 index 00000000000..eeecd2e9e40 --- /dev/null +++ b/tests/ui/lifetimes/unsafe-transmute-in-find-11740.rs @@ -0,0 +1,28 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/11740 + +//@ check-pass + +struct Attr { + name: String, + value: String, +} + +struct Element { + attrs: Vec>, +} + +impl Element { + pub unsafe fn get_attr<'a>(&'a self, name: &str) { + self.attrs + .iter() + .find(|attr| { + let attr: &&Box = std::mem::transmute(attr); + true + }); + } +} + +fn main() { + let element = Element { attrs: Vec::new() }; + unsafe { let () = element.get_attr("foo"); }; +} diff --git a/tests/ui/match/function-in-pattern-error.rs b/tests/ui/match/function-in-pattern-error.rs deleted file mode 100644 index 1ac1c3d818e..00000000000 --- a/tests/ui/match/function-in-pattern-error.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod foo { pub fn bar() {} } - -fn main() { - match () { - foo::bar => {} - //~^ ERROR expected unit struct, unit variant or constant, found function `foo::bar` - } -} diff --git a/tests/ui/match/guard-literal-range-shadow.rs b/tests/ui/match/guard-literal-range-shadow.rs deleted file mode 100644 index fbd1d75067b..00000000000 --- a/tests/ui/match/guard-literal-range-shadow.rs +++ /dev/null @@ -1,178 +0,0 @@ -//@ run-pass - -// Tests that match expression handles overlapped literal and range -// properly in the presence of guard function. - -fn val() -> usize { 1 } - -static CONST: usize = 1; - -pub fn main() { - lit_shadow_range(); - range_shadow_lit(); - range_shadow_range(); - multi_pats_shadow_lit(); - multi_pats_shadow_range(); - lit_shadow_multi_pats(); - range_shadow_multi_pats(); - misc(); -} - -fn lit_shadow_range() { - assert_eq!(2, match 1 { - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); - - let x = 0; - assert_eq!(2, match x+1 { - 0 => 0, - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); - - assert_eq!(2, match val() { - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); - - assert_eq!(2, match CONST { - 0 => 0, - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); - - // value is out of the range of second arm, should match wildcard pattern - assert_eq!(3, match 3 { - 1 if false => 1, - 1..=2 => 2, - _ => 3 - }); -} - -fn range_shadow_lit() { - assert_eq!(2, match 1 { - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); - - let x = 0; - assert_eq!(2, match x+1 { - 0 => 0, - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); - - assert_eq!(2, match val() { - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); - - assert_eq!(2, match CONST { - 0 => 0, - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); - - // ditto - assert_eq!(3, match 3 { - 1..=2 if false => 1, - 1 => 2, - _ => 3 - }); -} - -fn range_shadow_range() { - assert_eq!(2, match 1 { - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); - - let x = 0; - assert_eq!(2, match x+1 { - 100 => 0, - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); - - assert_eq!(2, match val() { - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); - - assert_eq!(2, match CONST { - 100 => 0, - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); - - // ditto - assert_eq!(3, match 5 { - 0..=2 if false => 1, - 1..=3 => 2, - _ => 3, - }); -} - -fn multi_pats_shadow_lit() { - assert_eq!(2, match 1 { - 100 => 0, - 0 | 1..=10 if false => 1, - 1 => 2, - _ => 3, - }); -} - -fn multi_pats_shadow_range() { - assert_eq!(2, match 1 { - 100 => 0, - 0 | 1..=10 if false => 1, - 1..=3 => 2, - _ => 3, - }); -} - -fn lit_shadow_multi_pats() { - assert_eq!(2, match 1 { - 100 => 0, - 1 if false => 1, - 0 | 1..=10 => 2, - _ => 3, - }); -} - -fn range_shadow_multi_pats() { - assert_eq!(2, match 1 { - 100 => 0, - 1..=3 if false => 1, - 0 | 1..=10 => 2, - _ => 3, - }); -} - -fn misc() { - enum Foo { - Bar(#[allow(dead_code)] usize, bool) - } - // This test basically mimics how trace_macros! macro is implemented, - // which is a rare combination of vector patterns, multiple wild-card - // patterns and guard functions. - let r = match [Foo::Bar(0, false)] { - [Foo::Bar(_, pred)] if pred => 1, - [Foo::Bar(_, pred)] if !pred => 2, - _ => 0, - }; - assert_eq!(2, r); -} diff --git a/tests/ui/match/option-result-mismatch-11844.rs b/tests/ui/match/option-result-mismatch-11844.rs new file mode 100644 index 00000000000..24a2004134d --- /dev/null +++ b/tests/ui/match/option-result-mismatch-11844.rs @@ -0,0 +1,10 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/11844 + +fn main() { + let a = Some(Box::new(1)); + match a { + Ok(a) => //~ ERROR: mismatched types + println!("{}",a), + None => panic!() + } +} diff --git a/tests/ui/match/option-result-mismatch-11844.stderr b/tests/ui/match/option-result-mismatch-11844.stderr new file mode 100644 index 00000000000..8a84b7b8a48 --- /dev/null +++ b/tests/ui/match/option-result-mismatch-11844.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/option-result-mismatch-11844.rs:6:9 + | +LL | match a { + | - this expression has type `Option>` +LL | Ok(a) => + | ^^^^^ expected `Option>`, found `Result<_, _>` + | + = note: expected enum `Option>` + found enum `Result<_, _>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/option-result-mismatch.rs b/tests/ui/match/option-result-mismatch.rs deleted file mode 100644 index f974a470296..00000000000 --- a/tests/ui/match/option-result-mismatch.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn main() { - let a = Some(Box::new(1)); - match a { - Ok(a) => //~ ERROR: mismatched types - println!("{}",a), - None => panic!() - } -} diff --git a/tests/ui/match/option-result-type-param-mismatch-13466.rs b/tests/ui/match/option-result-type-param-mismatch-13466.rs new file mode 100644 index 00000000000..05dbdfdee0e --- /dev/null +++ b/tests/ui/match/option-result-type-param-mismatch-13466.rs @@ -0,0 +1,24 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13466 + +// Regression test for #13466 + +//@ dont-require-annotations: NOTE + +pub fn main() { + // The expected arm type `Option` has one type parameter, while + // the actual arm `Result` has two. typeck should not be + // tricked into looking up a non-existing second type parameter. + let _x: usize = match Some(1) { + Ok(u) => u, + //~^ ERROR mismatched types + //~| NOTE expected enum `Option<{integer}>` + //~| NOTE found enum `Result<_, _>` + //~| NOTE expected `Option<{integer}>`, found `Result<_, _>` + + Err(e) => panic!(e) + //~^ ERROR mismatched types + //~| NOTE expected enum `Option<{integer}>` + //~| NOTE found enum `Result<_, _>` + //~| NOTE expected `Option<{integer}>`, found `Result<_, _>` + }; +} diff --git a/tests/ui/match/option-result-type-param-mismatch-13466.stderr b/tests/ui/match/option-result-type-param-mismatch-13466.stderr new file mode 100644 index 00000000000..b0cf1591f5e --- /dev/null +++ b/tests/ui/match/option-result-type-param-mismatch-13466.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/option-result-type-param-mismatch-13466.rs:12:9 + | +LL | let _x: usize = match Some(1) { + | ------- this expression has type `Option<{integer}>` +LL | Ok(u) => u, + | ^^^^^ expected `Option<{integer}>`, found `Result<_, _>` + | + = note: expected enum `Option<{integer}>` + found enum `Result<_, _>` + +error[E0308]: mismatched types + --> $DIR/option-result-type-param-mismatch-13466.rs:18:9 + | +LL | let _x: usize = match Some(1) { + | ------- this expression has type `Option<{integer}>` +... +LL | Err(e) => panic!(e) + | ^^^^^^ expected `Option<{integer}>`, found `Result<_, _>` + | + = note: expected enum `Option<{integer}>` + found enum `Result<_, _>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/option-result-type-param-mismatch.rs b/tests/ui/match/option-result-type-param-mismatch.rs deleted file mode 100644 index 78ce4c1d2f6..00000000000 --- a/tests/ui/match/option-result-type-param-mismatch.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Regression test for #13466 - -//@ dont-require-annotations: NOTE - -pub fn main() { - // The expected arm type `Option` has one type parameter, while - // the actual arm `Result` has two. typeck should not be - // tricked into looking up a non-existing second type parameter. - let _x: usize = match Some(1) { - Ok(u) => u, - //~^ ERROR mismatched types - //~| NOTE expected enum `Option<{integer}>` - //~| NOTE found enum `Result<_, _>` - //~| NOTE expected `Option<{integer}>`, found `Result<_, _>` - - Err(e) => panic!(e) - //~^ ERROR mismatched types - //~| NOTE expected enum `Option<{integer}>` - //~| NOTE found enum `Result<_, _>` - //~| NOTE expected `Option<{integer}>`, found `Result<_, _>` - }; -} diff --git a/tests/ui/match/overeager-sub-match-pruning-13027.rs b/tests/ui/match/overeager-sub-match-pruning-13027.rs new file mode 100644 index 00000000000..c4feb697f7d --- /dev/null +++ b/tests/ui/match/overeager-sub-match-pruning-13027.rs @@ -0,0 +1,180 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13027 + +//@ run-pass + +// Tests that match expression handles overlapped literal and range +// properly in the presence of guard function. + +fn val() -> usize { 1 } + +static CONST: usize = 1; + +pub fn main() { + lit_shadow_range(); + range_shadow_lit(); + range_shadow_range(); + multi_pats_shadow_lit(); + multi_pats_shadow_range(); + lit_shadow_multi_pats(); + range_shadow_multi_pats(); + misc(); +} + +fn lit_shadow_range() { + assert_eq!(2, match 1 { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + let x = 0; + assert_eq!(2, match x+1 { + 0 => 0, + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + assert_eq!(2, match val() { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + assert_eq!(2, match CONST { + 0 => 0, + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + // value is out of the range of second arm, should match wildcard pattern + assert_eq!(3, match 3 { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); +} + +fn range_shadow_lit() { + assert_eq!(2, match 1 { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + let x = 0; + assert_eq!(2, match x+1 { + 0 => 0, + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + assert_eq!(2, match val() { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + assert_eq!(2, match CONST { + 0 => 0, + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + // ditto + assert_eq!(3, match 3 { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); +} + +fn range_shadow_range() { + assert_eq!(2, match 1 { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + let x = 0; + assert_eq!(2, match x+1 { + 100 => 0, + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + assert_eq!(2, match val() { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + assert_eq!(2, match CONST { + 100 => 0, + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + // ditto + assert_eq!(3, match 5 { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); +} + +fn multi_pats_shadow_lit() { + assert_eq!(2, match 1 { + 100 => 0, + 0 | 1..=10 if false => 1, + 1 => 2, + _ => 3, + }); +} + +fn multi_pats_shadow_range() { + assert_eq!(2, match 1 { + 100 => 0, + 0 | 1..=10 if false => 1, + 1..=3 => 2, + _ => 3, + }); +} + +fn lit_shadow_multi_pats() { + assert_eq!(2, match 1 { + 100 => 0, + 1 if false => 1, + 0 | 1..=10 => 2, + _ => 3, + }); +} + +fn range_shadow_multi_pats() { + assert_eq!(2, match 1 { + 100 => 0, + 1..=3 if false => 1, + 0 | 1..=10 => 2, + _ => 3, + }); +} + +fn misc() { + enum Foo { + Bar(#[allow(dead_code)] usize, bool) + } + // This test basically mimics how trace_macros! macro is implemented, + // which is a rare combination of vector patterns, multiple wild-card + // patterns and guard functions. + let r = match [Foo::Bar(0, false)] { + [Foo::Bar(_, pred)] if pred => 1, + [Foo::Bar(_, pred)] if !pred => 2, + _ => 0, + }; + assert_eq!(2, r); +} diff --git a/tests/ui/match/slice-move-out-error-12567.rs b/tests/ui/match/slice-move-out-error-12567.rs new file mode 100644 index 00000000000..3f9bf9c76cf --- /dev/null +++ b/tests/ui/match/slice-move-out-error-12567.rs @@ -0,0 +1,15 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12567 + +fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) { + match (l1, l2) { + //~^ ERROR: cannot move out of type `[T]`, a non-copy slice + //~| ERROR: cannot move out of type `[T]`, a non-copy slice + (&[], &[]) => println!("both empty"), + (&[], &[hd, ..]) | (&[hd, ..], &[]) + => println!("one empty"), + (&[hd1, ..], &[hd2, ..]) + => println!("both nonempty"), + } +} + +fn main() {} diff --git a/tests/ui/match/slice-move-out-error-12567.stderr b/tests/ui/match/slice-move-out-error-12567.stderr new file mode 100644 index 00000000000..ab5377d4701 --- /dev/null +++ b/tests/ui/match/slice-move-out-error-12567.stderr @@ -0,0 +1,51 @@ +error[E0508]: cannot move out of type `[T]`, a non-copy slice + --> $DIR/slice-move-out-error-12567.rs:4:11 + | +LL | match (l1, l2) { + | ^^^^^^^^ cannot move out of here +... +LL | (&[], &[hd, ..]) | (&[hd, ..], &[]) + | -- data moved here +LL | => println!("one empty"), +LL | (&[hd1, ..], &[hd2, ..]) + | --- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - (&[], &[hd, ..]) | (&[hd, ..], &[]) +LL + (&[], [hd, ..]) | (&[hd, ..], &[]) + | +help: consider removing the borrow + | +LL - (&[hd1, ..], &[hd2, ..]) +LL + (&[hd1, ..], [hd2, ..]) + | + +error[E0508]: cannot move out of type `[T]`, a non-copy slice + --> $DIR/slice-move-out-error-12567.rs:4:11 + | +LL | match (l1, l2) { + | ^^^^^^^^ cannot move out of here +... +LL | (&[], &[hd, ..]) | (&[hd, ..], &[]) + | -- data moved here +LL | => println!("one empty"), +LL | (&[hd1, ..], &[hd2, ..]) + | --- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - (&[], &[hd, ..]) | (&[hd, ..], &[]) +LL + (&[], [hd, ..]) | (&[hd, ..], &[]) + | +help: consider removing the borrow + | +LL - (&[hd1, ..], &[hd2, ..]) +LL + ([hd1, ..], &[hd2, ..]) + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/match/slice-move-out-error.rs b/tests/ui/match/slice-move-out-error.rs deleted file mode 100644 index 1b2a37de475..00000000000 --- a/tests/ui/match/slice-move-out-error.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) { - match (l1, l2) { - //~^ ERROR: cannot move out of type `[T]`, a non-copy slice - //~| ERROR: cannot move out of type `[T]`, a non-copy slice - (&[], &[]) => println!("both empty"), - (&[], &[hd, ..]) | (&[hd, ..], &[]) - => println!("one empty"), - (&[hd1, ..], &[hd2, ..]) - => println!("both nonempty"), - } -} - -fn main() {} diff --git a/tests/ui/match/string-literal-match-patterns.rs b/tests/ui/match/string-literal-match-patterns.rs deleted file mode 100644 index dd752227bbe..00000000000 --- a/tests/ui/match/string-literal-match-patterns.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ check-pass -#![allow(dead_code)] - -struct A { - a: String -} - -fn borrow<'a>(binding: &'a A) -> &'a str { - match &*binding.a { - "in" => "in_", - "ref" => "ref_", - ident => ident - } -} - -fn main() {} diff --git a/tests/ui/match/struct-reference-patterns-12285.rs b/tests/ui/match/struct-reference-patterns-12285.rs new file mode 100644 index 00000000000..246e230b0de --- /dev/null +++ b/tests/ui/match/struct-reference-patterns-12285.rs @@ -0,0 +1,16 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12285 + +//@ run-pass + +struct S; + +fn main() { + match Some(&S) { + Some(&S) => {}, + _x => unreachable!() + } + match Some(&S) { + Some(&S) => {}, + None => unreachable!() + } +} diff --git a/tests/ui/match/struct-reference-patterns.rs b/tests/ui/match/struct-reference-patterns.rs deleted file mode 100644 index fe199147128..00000000000 --- a/tests/ui/match/struct-reference-patterns.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass - -struct S; - -fn main() { - match Some(&S) { - Some(&S) => {}, - _x => unreachable!() - } - match Some(&S) { - Some(&S) => {}, - None => unreachable!() - } -} diff --git a/tests/ui/panics/explicit-panic-unreachable.rs b/tests/ui/panics/explicit-panic-unreachable.rs deleted file mode 100644 index f3b1b643c45..00000000000 --- a/tests/ui/panics/explicit-panic-unreachable.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-fail -//@ error-pattern:explicit panic -//@ needs-subprocess - -pub fn main() { - panic!(); - println!("{}", 1); -} diff --git a/tests/ui/panics/unwrap-or-panic-input.rs b/tests/ui/panics/unwrap-or-panic-input.rs deleted file mode 100644 index 99ffba3fba5..00000000000 --- a/tests/ui/panics/unwrap-or-panic-input.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-fail -//@ error-pattern:bad input -//@ needs-subprocess - -fn main() { - Some("foo").unwrap_or(panic!("bad input")).to_string(); -} diff --git a/tests/ui/parser/encode-symbol-ice-12920.rs b/tests/ui/parser/encode-symbol-ice-12920.rs new file mode 100644 index 00000000000..87389c0ffb4 --- /dev/null +++ b/tests/ui/parser/encode-symbol-ice-12920.rs @@ -0,0 +1,10 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12920 + +//@ run-fail +//@ error-pattern:explicit panic +//@ needs-subprocess + +pub fn main() { + panic!(); + println!("{}", 1); +} diff --git a/tests/ui/privacy/private-unit-struct-assignment.rs b/tests/ui/privacy/private-unit-struct-assignment.rs index 7794be37b85..b8e1c4ecb18 100644 --- a/tests/ui/privacy/private-unit-struct-assignment.rs +++ b/tests/ui/privacy/private-unit-struct-assignment.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13407 + mod A { struct C; } diff --git a/tests/ui/privacy/private-unit-struct-assignment.stderr b/tests/ui/privacy/private-unit-struct-assignment.stderr new file mode 100644 index 00000000000..8c36a08846d --- /dev/null +++ b/tests/ui/privacy/private-unit-struct-assignment.stderr @@ -0,0 +1,27 @@ +error[E0603]: unit struct `C` is private + --> $DIR/private-unit-struct-assignment.rs:8:8 + | +LL | A::C = 1; + | ^ private unit struct + | +note: the unit struct `C` is defined here + --> $DIR/private-unit-struct-assignment.rs:4:5 + | +LL | struct C; + | ^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/private-unit-struct-assignment.rs:8:5 + | +LL | struct C; + | -------- unit struct defined here +... +LL | A::C = 1; + | ^^^^ - this expression has type `{integer}` + | | + | expected integer, found `C` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0603. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/privacy/use-in-impl-scope-12729.rs b/tests/ui/privacy/use-in-impl-scope-12729.rs new file mode 100644 index 00000000000..58fe042beec --- /dev/null +++ b/tests/ui/privacy/use-in-impl-scope-12729.rs @@ -0,0 +1,16 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12729 + +//@ edition: 2015 +//@ check-pass +#![allow(dead_code)] + +pub struct Foo; + +mod bar { + use Foo; + + impl Foo { + fn baz(&self) {} + } +} +fn main() {} diff --git a/tests/ui/resolve/reference-clone-nonclone-11820.rs b/tests/ui/resolve/reference-clone-nonclone-11820.rs new file mode 100644 index 00000000000..74dad96da94 --- /dev/null +++ b/tests/ui/resolve/reference-clone-nonclone-11820.rs @@ -0,0 +1,15 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/11820 + +//@ run-pass + +#![allow(noop_method_call)] + +struct NoClone; + +fn main() { + let rnc = &NoClone; + let rsnc = &Some(NoClone); + + let _: &NoClone = rnc.clone(); + let _: &Option = rsnc.clone(); +} diff --git a/tests/ui/statics/enum-with-static-str-variant-13214.rs b/tests/ui/statics/enum-with-static-str-variant-13214.rs new file mode 100644 index 00000000000..1db37da632d --- /dev/null +++ b/tests/ui/statics/enum-with-static-str-variant-13214.rs @@ -0,0 +1,24 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13214 + +//@ build-pass +#![allow(dead_code)] +// defining static with struct that contains enum +// with &'static str variant used to cause ICE + + +pub enum Foo { + Bar, + Baz(&'static str), +} + +pub static TEST: Test = Test { + foo: Foo::Bar, + c: 'a' +}; + +pub struct Test { + foo: Foo, + c: char, +} + +fn main() {} diff --git a/tests/ui/statics/enum-with-static-str-variant.rs b/tests/ui/statics/enum-with-static-str-variant.rs deleted file mode 100644 index 8140ec943a0..00000000000 --- a/tests/ui/statics/enum-with-static-str-variant.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ build-pass -#![allow(dead_code)] -// defining static with struct that contains enum -// with &'static str variant used to cause ICE - - -pub enum Foo { - Bar, - Baz(&'static str), -} - -pub static TEST: Test = Test { - foo: Foo::Bar, - c: 'a' -}; - -pub struct Test { - foo: Foo, - c: char, -} - -fn main() {} diff --git a/tests/ui/threads/moved-value-in-thread-loop.rs b/tests/ui/threads/moved-value-in-thread-loop.rs deleted file mode 100644 index 091e8fe8b2a..00000000000 --- a/tests/ui/threads/moved-value-in-thread-loop.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::sync::mpsc::channel; -use std::thread; - -fn main() { - let (tx, rx) = channel(); - let _t = thread::spawn(move|| -> () { - loop { - let tx = tx; - //~^ ERROR: use of moved value: `tx` - tx.send(1); - } - }); -} diff --git a/tests/ui/traits/any-trait-object-debug.rs b/tests/ui/traits/any-trait-object-debug.rs deleted file mode 100644 index eaf92d413d5..00000000000 --- a/tests/ui/traits/any-trait-object-debug.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-pass -fn main() { - fn test() -> Box { Box::new(1) } - println!("{:?}", test()) -} diff --git a/tests/ui/traits/default-method-lifetime-params-13204.rs b/tests/ui/traits/default-method-lifetime-params-13204.rs new file mode 100644 index 00000000000..cdf34ab773c --- /dev/null +++ b/tests/ui/traits/default-method-lifetime-params-13204.rs @@ -0,0 +1,27 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13204 + +//@ run-pass +#![allow(unused_mut)] +// Test that when instantiating trait default methods, typeck handles +// lifetime parameters defined on the method bound correctly. + + +pub trait Foo { + fn bar<'a, I: Iterator>(&self, it: I) -> usize { + let mut xs = it.filter(|_| true); + xs.count() + } +} + +pub struct Baz; + +impl Foo for Baz { + // When instantiating `Foo::bar` for `Baz` here, typeck used to + // ICE due to the lifetime parameter of `bar`. +} + +fn main() { + let x = Baz; + let y = vec![(), (), ()]; + assert_eq!(x.bar(y.iter()), 3); +} diff --git a/tests/ui/traits/default-method-lifetime-params.rs b/tests/ui/traits/default-method-lifetime-params.rs deleted file mode 100644 index 01362f6fe61..00000000000 --- a/tests/ui/traits/default-method-lifetime-params.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ run-pass -#![allow(unused_mut)] -// Test that when instantiating trait default methods, typeck handles -// lifetime parameters defined on the method bound correctly. - - -pub trait Foo { - fn bar<'a, I: Iterator>(&self, it: I) -> usize { - let mut xs = it.filter(|_| true); - xs.count() - } -} - -pub struct Baz; - -impl Foo for Baz { - // When instantiating `Foo::bar` for `Baz` here, typeck used to - // ICE due to the lifetime parameter of `bar`. -} - -fn main() { - let x = Baz; - let y = vec![(), (), ()]; - assert_eq!(x.bar(y.iter()), 3); -} diff --git a/tests/ui/traits/deref-chain-method-calls.rs b/tests/ui/traits/deref-chain-method-calls.rs deleted file mode 100644 index bf4ec388c4f..00000000000 --- a/tests/ui/traits/deref-chain-method-calls.rs +++ /dev/null @@ -1,74 +0,0 @@ -//@ run-pass -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -use std::ops::Deref; - -struct Root { - jsref: JSRef -} - -impl Deref for Root { - type Target = JSRef; - - fn deref<'a>(&'a self) -> &'a JSRef { - &self.jsref - } -} - -#[derive(Copy, Clone)] -struct JSRef { - node: *const Node -} - -impl Deref for JSRef { - type Target = Node; - - fn deref<'a>(&'a self) -> &'a Node { - self.get() - } -} - -trait INode { - fn RemoveChild(&self); -} - -impl INode for JSRef { - fn RemoveChild(&self) { - self.get().RemoveChild(0) - } -} - -impl JSRef { - fn AddChild(&self) { - self.get().AddChild(0); - } - - fn get<'a>(&'a self) -> &'a Node { - unsafe { - &*self.node - } - } -} - -struct Node; - -impl Node { - fn RemoveChild(&self, _a: usize) { - } - - fn AddChild(&self, _a: usize) { - } -} - -fn main() { - let n = Node; - let jsref = JSRef { node: &n }; - let root = Root { jsref: jsref }; - - root.AddChild(); - jsref.AddChild(); - - root.RemoveChild(); - jsref.RemoveChild(); -} diff --git a/tests/ui/traits/fnonce-repro-trait-impl-13434.rs b/tests/ui/traits/fnonce-repro-trait-impl-13434.rs new file mode 100644 index 00000000000..61d5a1d74ae --- /dev/null +++ b/tests/ui/traits/fnonce-repro-trait-impl-13434.rs @@ -0,0 +1,23 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13434 + +//@ run-pass +#[derive(Debug)] +struct MyStruct; + +trait Repro { + fn repro(self, s: MyStruct) -> String; +} + +impl Repro for F where F: FnOnce(MyStruct) -> String { + fn repro(self, s: MyStruct) -> String { + self(s) + } +} + +fn do_stuff(r: R) -> String { + r.repro(MyStruct) +} + +pub fn main() { + assert_eq!("MyStruct".to_string(), do_stuff(|s: MyStruct| format!("{:?}", s))); +} diff --git a/tests/ui/traits/fnonce-repro-trait-impl.rs b/tests/ui/traits/fnonce-repro-trait-impl.rs deleted file mode 100644 index caf7b632393..00000000000 --- a/tests/ui/traits/fnonce-repro-trait-impl.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ run-pass -#[derive(Debug)] -struct MyStruct; - -trait Repro { - fn repro(self, s: MyStruct) -> String; -} - -impl Repro for F where F: FnOnce(MyStruct) -> String { - fn repro(self, s: MyStruct) -> String { - self(s) - } -} - -fn do_stuff(r: R) -> String { - r.repro(MyStruct) -} - -pub fn main() { - assert_eq!("MyStruct".to_string(), do_stuff(|s: MyStruct| format!("{:?}", s))); -} diff --git a/tests/ui/traits/matcher-trait-equality.rs b/tests/ui/traits/matcher-trait-equality.rs deleted file mode 100644 index 8f334404f9a..00000000000 --- a/tests/ui/traits/matcher-trait-equality.rs +++ /dev/null @@ -1,58 +0,0 @@ -//@ run-pass - -struct StrWrap { - s: String -} - -impl StrWrap { - fn new(s: &str) -> StrWrap { - StrWrap { s: s.to_string() } - } - - fn get_s<'a>(&'a self) -> &'a str { - &self.s - } -} - -struct MyStruct { - s: StrWrap -} - -impl MyStruct { - fn new(s: &str) -> MyStruct { - MyStruct { s: StrWrap::new(s) } - } - - fn get_str_wrap<'a>(&'a self) -> &'a StrWrap { - &self.s - } -} - -trait Matcher { - fn matches(&self, actual: T) -> bool; -} - -fn assert_that>(actual: T, matcher: &U) { - assert!(matcher.matches(actual)); -} - -struct EqualTo { - expected: T -} - -impl Matcher for EqualTo { - fn matches(&self, actual: T) -> bool { - self.expected.eq(&actual) - } -} - -fn equal_to(expected: T) -> Box> { - Box::new(EqualTo { expected: expected }) -} - -pub fn main() { - let my_struct = MyStruct::new("zomg"); - let s = my_struct.get_str_wrap(); - - assert_that(s.get_s(), &*equal_to("zomg")); -} diff --git a/tests/ui/traits/reference-clone-noclone.rs b/tests/ui/traits/reference-clone-noclone.rs deleted file mode 100644 index ada844f8ee1..00000000000 --- a/tests/ui/traits/reference-clone-noclone.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ run-pass - -#![allow(noop_method_call)] - -struct NoClone; - -fn main() { - let rnc = &NoClone; - let rsnc = &Some(NoClone); - - let _: &NoClone = rnc.clone(); - let _: &Option = rsnc.clone(); -} diff --git a/tests/ui/type-inference/isize-usize-mismatch-error.rs b/tests/ui/type-inference/isize-usize-mismatch-error.rs deleted file mode 100644 index 5d31d7f861c..00000000000 --- a/tests/ui/type-inference/isize-usize-mismatch-error.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ dont-require-annotations: NOTE - -fn foo(_s: i16) { } - -fn bar(_s: u32) { } - -fn main() { - foo(1*(1 as isize)); - //~^ ERROR mismatched types - //~| NOTE expected `i16`, found `isize` - - bar(1*(1 as usize)); - //~^ ERROR mismatched types - //~| NOTE expected `u32`, found `usize` -} diff --git a/tests/ui/type-inference/partial-type-hint-12909.rs b/tests/ui/type-inference/partial-type-hint-12909.rs new file mode 100644 index 00000000000..d7017f451e3 --- /dev/null +++ b/tests/ui/type-inference/partial-type-hint-12909.rs @@ -0,0 +1,21 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12909 + +//@ run-pass +#![allow(unused_variables)] + +use std::collections::HashMap; + +fn copy(&x: &T) -> T { + x +} + +fn main() { + let arr = [(1, 1), (2, 2), (3, 3)]; + + let v1: Vec<&_> = arr.iter().collect(); + let v2: Vec<_> = arr.iter().map(copy).collect(); + + let m1: HashMap<_, _> = arr.iter().map(copy).collect(); + let m2: HashMap = arr.iter().map(copy).collect(); + let m3: HashMap<_, usize> = arr.iter().map(copy).collect(); +} diff --git a/tests/ui/type-inference/type-collect-inference.rs b/tests/ui/type-inference/type-collect-inference.rs deleted file mode 100644 index f2c33806aae..00000000000 --- a/tests/ui/type-inference/type-collect-inference.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ run-pass -#![allow(unused_variables)] - -use std::collections::HashMap; - -fn copy(&x: &T) -> T { - x -} - -fn main() { - let arr = [(1, 1), (2, 2), (3, 3)]; - - let v1: Vec<&_> = arr.iter().collect(); - let v2: Vec<_> = arr.iter().map(copy).collect(); - - let m1: HashMap<_, _> = arr.iter().map(copy).collect(); - let m2: HashMap = arr.iter().map(copy).collect(); - let m3: HashMap<_, usize> = arr.iter().map(copy).collect(); -} diff --git a/tests/ui/type-inference/unit-type-add-error.rs b/tests/ui/type-inference/unit-type-add-error.rs deleted file mode 100644 index c69cd1e79e3..00000000000 --- a/tests/ui/type-inference/unit-type-add-error.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - let x = (); - 1 + - x //~^ ERROR E0277 - ; - - let x: () = (); - 1 + - x //~^ ERROR E0277 - ; -} diff --git a/tests/ui/typeck/function-in-pattern-error-12863.rs b/tests/ui/typeck/function-in-pattern-error-12863.rs new file mode 100644 index 00000000000..d2fa2555658 --- /dev/null +++ b/tests/ui/typeck/function-in-pattern-error-12863.rs @@ -0,0 +1,10 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/12863 + +mod foo { pub fn bar() {} } + +fn main() { + match () { + foo::bar => {} + //~^ ERROR expected unit struct, unit variant or constant, found function `foo::bar` + } +} diff --git a/tests/ui/typeck/function-in-pattern-error-12863.stderr b/tests/ui/typeck/function-in-pattern-error-12863.stderr new file mode 100644 index 00000000000..f28874b5d48 --- /dev/null +++ b/tests/ui/typeck/function-in-pattern-error-12863.stderr @@ -0,0 +1,9 @@ +error[E0532]: expected unit struct, unit variant or constant, found function `foo::bar` + --> $DIR/function-in-pattern-error-12863.rs:7:9 + | +LL | foo::bar => {} + | ^^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/typeck/isize-usize-mismatch-error.rs b/tests/ui/typeck/isize-usize-mismatch-error.rs new file mode 100644 index 00000000000..2fb5cf489c0 --- /dev/null +++ b/tests/ui/typeck/isize-usize-mismatch-error.rs @@ -0,0 +1,17 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13359 + +//@ dont-require-annotations: NOTE + +fn foo(_s: i16) { } + +fn bar(_s: u32) { } + +fn main() { + foo(1*(1 as isize)); + //~^ ERROR mismatched types + //~| NOTE expected `i16`, found `isize` + + bar(1*(1 as usize)); + //~^ ERROR mismatched types + //~| NOTE expected `u32`, found `usize` +} diff --git a/tests/ui/typeck/isize-usize-mismatch-error.stderr b/tests/ui/typeck/isize-usize-mismatch-error.stderr new file mode 100644 index 00000000000..d5724665a03 --- /dev/null +++ b/tests/ui/typeck/isize-usize-mismatch-error.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/isize-usize-mismatch-error.rs:10:9 + | +LL | foo(1*(1 as isize)); + | --- ^^^^^^^^^^^^^^ expected `i16`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/isize-usize-mismatch-error.rs:5:4 + | +LL | fn foo(_s: i16) { } + | ^^^ ------- +help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit + | +LL | foo((1*(1 as isize)).try_into().unwrap()); + | + +++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/isize-usize-mismatch-error.rs:14:9 + | +LL | bar(1*(1 as usize)); + | --- ^^^^^^^^^^^^^^ expected `u32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/isize-usize-mismatch-error.rs:7:4 + | +LL | fn bar(_s: u32) { } + | ^^^ ------- +help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit + | +LL | bar((1*(1 as usize)).try_into().unwrap()); + | + +++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/unit-type-add-error-11771.rs b/tests/ui/typeck/unit-type-add-error-11771.rs new file mode 100644 index 00000000000..d009f50f4b9 --- /dev/null +++ b/tests/ui/typeck/unit-type-add-error-11771.rs @@ -0,0 +1,13 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/11771 + +fn main() { + let x = (); + 1 + + x //~^ ERROR E0277 + ; + + let x: () = (); + 1 + + x //~^ ERROR E0277 + ; +} diff --git a/tests/ui/typeck/unit-type-add-error-11771.stderr b/tests/ui/typeck/unit-type-add-error-11771.stderr new file mode 100644 index 00000000000..155cc093524 --- /dev/null +++ b/tests/ui/typeck/unit-type-add-error-11771.stderr @@ -0,0 +1,39 @@ +error[E0277]: cannot add `()` to `{integer}` + --> $DIR/unit-type-add-error-11771.rs:5:7 + | +LL | 1 + + | ^ no implementation for `{integer} + ()` + | + = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Add`: + `&f128` implements `Add` + `&f128` implements `Add` + `&f16` implements `Add` + `&f16` implements `Add` + `&f32` implements `Add` + `&f32` implements `Add` + `&f64` implements `Add` + `&f64` implements `Add` + and 56 others + +error[E0277]: cannot add `()` to `{integer}` + --> $DIR/unit-type-add-error-11771.rs:10:7 + | +LL | 1 + + | ^ no implementation for `{integer} + ()` + | + = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Add`: + `&f128` implements `Add` + `&f128` implements `Add` + `&f16` implements `Add` + `&f16` implements `Add` + `&f32` implements `Add` + `&f32` implements `Add` + `&f64` implements `Add` + `&f64` implements `Add` + and 56 others + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/unwrap-or-panic-input-13202.rs b/tests/ui/typeck/unwrap-or-panic-input-13202.rs new file mode 100644 index 00000000000..29833a727c5 --- /dev/null +++ b/tests/ui/typeck/unwrap-or-panic-input-13202.rs @@ -0,0 +1,9 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/13202 + +//@ run-fail +//@ error-pattern:bad input +//@ needs-subprocess + +fn main() { + Some("foo").unwrap_or(panic!("bad input")).to_string(); +} diff --git a/tests/ui/unsafe/unsafe-transmute-in-find.rs b/tests/ui/unsafe/unsafe-transmute-in-find.rs deleted file mode 100644 index c6099c2a0c0..00000000000 --- a/tests/ui/unsafe/unsafe-transmute-in-find.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ check-pass - -struct Attr { - name: String, - value: String, -} - -struct Element { - attrs: Vec>, -} - -impl Element { - pub unsafe fn get_attr<'a>(&'a self, name: &str) { - self.attrs - .iter() - .find(|attr| { - let attr: &&Box = std::mem::transmute(attr); - true - }); - } -} - -fn main() { - let element = Element { attrs: Vec::new() }; - unsafe { let () = element.get_attr("foo"); }; -} -- cgit 1.4.1-3-g733a5 From d525e79157e32abc510714dd32628c9c155f2997 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 18 Jul 2025 18:17:15 +0000 Subject: Stall coroutines based off of ty::Coroutine, not ty::CoroutineWitness --- .../src/solve/trait_goals.rs | 11 +- .../rustc_trait_selection/src/solve/fulfill.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 60 +++++----- .../rustc_trait_selection/src/traits/select/mod.rs | 2 +- compiler/rustc_type_ir/src/flags.rs | 11 +- tests/ui/async-await/issue-70818.rs | 1 + tests/ui/async-await/issue-70818.stderr | 23 +++- tests/ui/async-await/issue-86507.stderr | 2 +- tests/ui/coroutine/clone-impl-async.rs | 6 +- tests/ui/coroutine/clone-impl-async.stderr | 132 ++++++++++----------- tests/ui/coroutine/clone-impl-static.stderr | 12 +- tests/ui/coroutine/clone-impl.rs | 1 + tests/ui/coroutine/clone-impl.stderr | 88 +++++++------- tests/ui/coroutine/ref-upvar-not-send.stderr | 14 +-- tests/ui/impl-trait/issues/issue-55872-3.stderr | 15 +-- 15 files changed, 194 insertions(+), 186 deletions(-) (limited to 'tests/ui') diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 650b85d99d2..31991565b0d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -229,7 +229,7 @@ where } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. - if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) { + if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) { return cand; } @@ -294,7 +294,7 @@ where } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. - if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) { + if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) { return cand; } @@ -1432,11 +1432,8 @@ where self.merge_trait_candidates(candidates) } - fn try_stall_coroutine_witness( - &mut self, - self_ty: I::Ty, - ) -> Option, NoSolution>> { - if let ty::CoroutineWitness(def_id, _) = self_ty.kind() { + fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option, NoSolution>> { + if let ty::Coroutine(def_id, _) = self_ty.kind() { match self.typing_mode() { TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 01bdae7435d..3f628d80662 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -355,7 +355,7 @@ impl<'tcx> TypeVisitor> for StalledOnCoroutines<'tcx> { return ControlFlow::Continue(()); } - if let ty::CoroutineWitness(def_id, _) = *ty.kind() + if let ty::Coroutine(def_id, _) = *ty.kind() && def_id.as_local().is_some_and(|def_id| self.stalled_coroutines.contains(&def_id)) { ControlFlow::Break(()) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 2c7089507a8..af6dafb3062 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -794,18 +794,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The auto impl might apply; we don't know. candidates.ambiguous = true; } - ty::Coroutine(coroutine_def_id, _) - if self.tcx().is_lang_item(def_id, LangItem::Unpin) => - { - match self.tcx().coroutine_movability(coroutine_def_id) { - hir::Movability::Static => { - // Immovable coroutines are never `Unpin`, so - // suppress the normal auto-impl candidate for it. + ty::Coroutine(coroutine_def_id, _) => { + if self.tcx().is_lang_item(def_id, LangItem::Unpin) { + match self.tcx().coroutine_movability(coroutine_def_id) { + hir::Movability::Static => { + // Immovable coroutines are never `Unpin`, so + // suppress the normal auto-impl candidate for it. + } + hir::Movability::Movable => { + // Movable coroutines are always `Unpin`, so add an + // unconditional builtin candidate with no sub-obligations. + candidates.vec.push(BuiltinCandidate); + } } - hir::Movability::Movable => { - // Movable coroutines are always `Unpin`, so add an - // unconditional builtin candidate. - candidates.vec.push(BuiltinCandidate); + } else { + if self.should_stall_coroutine(coroutine_def_id) { + candidates.ambiguous = true; + } else { + // Coroutines implement all other auto traits normally. + candidates.vec.push(AutoImplCandidate); } } } @@ -842,12 +849,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::CoroutineWitness(def_id, _) => { - if self.should_stall_coroutine_witness(def_id) { - candidates.ambiguous = true; - } else { - candidates.vec.push(AutoImplCandidate); - } + ty::CoroutineWitness(..) => { + candidates.vec.push(AutoImplCandidate); } ty::Bool @@ -866,7 +869,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::FnPtr(..) | ty::Closure(..) | ty::CoroutineClosure(..) - | ty::Coroutine(..) | ty::Never | ty::Tuple(_) | ty::UnsafeBinder(_) => { @@ -1153,6 +1155,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Ref(_, _, hir::Mutability::Mut) => {} ty::Coroutine(coroutine_def_id, args) => { + if self.should_stall_coroutine(coroutine_def_id) { + candidates.ambiguous = true; + return; + } + match self.tcx().coroutine_movability(coroutine_def_id) { hir::Movability::Static => {} hir::Movability::Movable => { @@ -1194,12 +1201,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::CoroutineWitness(coroutine_def_id, _) => { - if self.should_stall_coroutine_witness(coroutine_def_id) { - candidates.ambiguous = true; - } else { - candidates.vec.push(SizedCandidate); - } + ty::CoroutineWitness(..) => { + candidates.vec.push(SizedCandidate); } // Fallback to whatever user-defined impls or param-env clauses exist in this case. @@ -1238,7 +1241,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(..) | ty::Char | ty::Ref(..) - | ty::Coroutine(..) | ty::Array(..) | ty::Closure(..) | ty::CoroutineClosure(..) @@ -1247,14 +1249,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.vec.push(SizedCandidate); } - ty::CoroutineWitness(coroutine_def_id, _) => { - if self.should_stall_coroutine_witness(coroutine_def_id) { + ty::Coroutine(coroutine_def_id, _) => { + if self.should_stall_coroutine(coroutine_def_id) { candidates.ambiguous = true; } else { candidates.vec.push(SizedCandidate); } } + ty::CoroutineWitness(..) => { + candidates.vec.push(SizedCandidate); + } + // Conditionally `Sized`. ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => { candidates.vec.push(SizedCandidate); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d7c3543cb3f..e893add81c8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2841,7 +2841,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligations } - fn should_stall_coroutine_witness(&self, def_id: DefId) -> bool { + fn should_stall_coroutine(&self, def_id: DefId) -> bool { match self.infcx.typing_mode() { TypingMode::Analysis { defining_opaque_types_and_generators: stalled_generators } => { def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id)) diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index d7b9e0ca340..23b7f55fbbe 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -131,10 +131,7 @@ bitflags::bitflags! { /// Does this have any binders with bound vars (e.g. that need to be anonymized)? const HAS_BINDER_VARS = 1 << 23; - /// Does this type have any coroutine witnesses in it? - // FIXME: This should probably be changed to track whether the type has any - // *coroutines* in it, though this will happen if we remove coroutine witnesses - // altogether. + /// Does this type have any coroutines in it? const HAS_TY_CORO = 1 << 24; } } @@ -246,11 +243,13 @@ impl FlagComputation { self.add_flags(TypeFlags::HAS_TY_PARAM); } - ty::Closure(_, args) | ty::Coroutine(_, args) | ty::CoroutineClosure(_, args) => { + ty::Closure(_, args) + | ty::CoroutineClosure(_, args) + | ty::CoroutineWitness(_, args) => { self.add_args(args.as_slice()); } - ty::CoroutineWitness(_, args) => { + ty::Coroutine(_, args) => { self.add_flags(TypeFlags::HAS_TY_CORO); self.add_args(args.as_slice()); } diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs index bc181de8d92..c11332fe7d8 100644 --- a/tests/ui/async-await/issue-70818.rs +++ b/tests/ui/async-await/issue-70818.rs @@ -4,6 +4,7 @@ use std::future::Future; fn foo(ty: T, ty1: U) -> impl Future + Send { //~^ ERROR future cannot be sent between threads safely async { (ty, ty1) } + //~^ ERROR future cannot be sent between threads safely } fn main() {} diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr index 8de6a825042..07fd20cdd77 100644 --- a/tests/ui/async-await/issue-70818.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -1,3 +1,24 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-70818.rs:6:5 + | +LL | async { (ty, ty1) } + | ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | +note: captured value is not `Send` + --> $DIR/issue-70818.rs:6:18 + | +LL | async { (ty, ty1) } + | ^^^ has type `U` which is not `Send` +note: required by a bound in an opaque type + --> $DIR/issue-70818.rs:4:69 + | +LL | fn foo(ty: T, ty1: U) -> impl Future + Send { + | ^^^^ +help: consider restricting type parameter `U` with trait `Send` + | +LL | fn foo(ty: T, ty1: U) -> impl Future + Send { + | +++++++++++++++++++ + error: future cannot be sent between threads safely --> $DIR/issue-70818.rs:4:38 | @@ -14,5 +35,5 @@ help: consider restricting type parameter `U` with trait `Send` LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | +++++++++++++++++++ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr index 6385a8c975e..c71801dcfc8 100644 --- a/tests/ui/async-await/issue-86507.stderr +++ b/tests/ui/async-await/issue-86507.stderr @@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless | LL | let x = x; | ^ has type `&T` which is not `Send`, because `T` is not `Sync` - = note: required for the cast from `Pin>` to `Pin + Send + 'async_trait)>>` + = note: required for the cast from `Pin>` to `Pin + Send>>` help: consider further restricting type parameter `T` with trait `Sync` | LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) diff --git a/tests/ui/coroutine/clone-impl-async.rs b/tests/ui/coroutine/clone-impl-async.rs index 2794b167aa2..4e2b26d0295 100644 --- a/tests/ui/coroutine/clone-impl-async.rs +++ b/tests/ui/coroutine/clone-impl-async.rs @@ -9,7 +9,7 @@ use std::future::ready; struct NonClone; -fn main() { +fn local() { let inner_non_clone = async { let non_clone = NonClone; let () = ready(()).await; @@ -34,7 +34,9 @@ fn main() { //~^ ERROR : Copy` is not satisfied check_clone(&maybe_copy_clone); //~^ ERROR : Clone` is not satisfied +} +fn non_local() { let inner_non_clone_fn = the_inner_non_clone_fn(); check_copy(&inner_non_clone_fn); //~^ ERROR : Copy` is not satisfied @@ -69,3 +71,5 @@ async fn the_maybe_copy_clone_fn() {} fn check_copy(_x: &T) {} fn check_clone(_x: &T) {} + +fn main() {} diff --git a/tests/ui/coroutine/clone-impl-async.stderr b/tests/ui/coroutine/clone-impl-async.stderr index 62bcce2fbcb..319a5ed3d8d 100644 --- a/tests/ui/coroutine/clone-impl-async.stderr +++ b/tests/ui/coroutine/clone-impl-async.stderr @@ -1,167 +1,155 @@ -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:18:16 +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:41:16 | -LL | check_copy(&inner_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` +LL | check_copy(&inner_non_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:20:17 +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:43:17 | -LL | check_clone(&inner_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` +LL | check_clone(&inner_non_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:27:16 +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:47:16 | -LL | check_copy(&outer_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` +LL | check_copy(&outer_non_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:29:17 +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:49:17 | -LL | check_clone(&outer_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` +LL | check_clone(&outer_non_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:33:16 +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:53:16 | -LL | check_copy(&maybe_copy_clone); - | ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` +LL | check_copy(&maybe_copy_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:35:17 +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:55:17 | -LL | check_clone(&maybe_copy_clone); - | ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` +LL | check_clone(&maybe_copy_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:39:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:18:5 | -LL | check_copy(&inner_non_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_copy(&inner_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:41:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:20:5 | -LL | check_clone(&inner_non_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_clone(&inner_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:45:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:27:5 | -LL | check_copy(&outer_non_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_copy(&outer_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:47:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:29:5 | -LL | check_clone(&outer_non_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_clone(&outer_non_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `impl Future: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:51:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:33:5 | -LL | check_copy(&maybe_copy_clone_fn); - | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_copy(&maybe_copy_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:70:18 + --> $DIR/clone-impl-async.rs:72:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `impl Future: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:53:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:35:5 | -LL | check_clone(&maybe_copy_clone_fn); - | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` - | | - | required by a bound introduced by this call +LL | check_clone(&maybe_copy_clone); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:71:19 + --> $DIR/clone-impl-async.rs:73:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr index 9fb71fd5fd0..4df6b9759c3 100644 --- a/tests/ui/coroutine/clone-impl-static.stderr +++ b/tests/ui/coroutine/clone-impl-static.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Copy` is not satisfied - --> $DIR/clone-impl-static.rs:14:16 + --> $DIR/clone-impl-static.rs:14:5 | LL | check_copy(&generator); - | ---------- ^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` | note: required by a bound in `check_copy` --> $DIR/clone-impl-static.rs:20:18 @@ -13,12 +11,10 @@ LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Clone` is not satisfied - --> $DIR/clone-impl-static.rs:16:17 + --> $DIR/clone-impl-static.rs:16:5 | LL | check_clone(&generator); - | ----------- ^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` | note: required by a bound in `check_clone` --> $DIR/clone-impl-static.rs:21:19 diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs index e528f031d52..9e04e256fc1 100644 --- a/tests/ui/coroutine/clone-impl.rs +++ b/tests/ui/coroutine/clone-impl.rs @@ -42,6 +42,7 @@ fn test3_upvars() { let clonable_0: Vec = Vec::new(); let gen_clone_0 = #[coroutine] move || { + yield; drop(clonable_0); }; check_copy(&gen_clone_0); diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr index 714e5aa3d9e..f316902a42d 100644 --- a/tests/ui/coroutine/clone-impl.stderr +++ b/tests/ui/coroutine/clone-impl.stderr @@ -1,59 +1,81 @@ error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` - --> $DIR/clone-impl.rs:47:16 + --> $DIR/clone-impl.rs:48:5 | LL | move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:45:14 + --> $DIR/clone-impl.rs:46:14 | LL | drop(clonable_0); | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}` - --> $DIR/clone-impl.rs:73:16 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}` + --> $DIR/clone-impl.rs:60:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:67:5: 67:12}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:55:5: 55:12}`, the trait `Copy` is not implemented for `Vec` + | +note: coroutine does not implement `Copy` as this value is used across a yield + --> $DIR/clone-impl.rs:57:9 + | +LL | let v = vec!['a']; + | - has type `Vec` which does not implement `Copy` +LL | yield; + | ^^^^^ yield occurs here, with `v` maybe used later +note: required by a bound in `check_copy` + --> $DIR/clone-impl.rs:92:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}` + --> $DIR/clone-impl.rs:74:5 + | +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}` +... +LL | check_copy(&gen_clone_1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:68:5: 68:12}`, the trait `Copy` is not implemented for `Vec` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:71:14 + --> $DIR/clone-impl.rs:72:14 | LL | drop(clonable_1); | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` - --> $DIR/clone-impl.rs:85:16 +error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` + --> $DIR/clone-impl.rs:86:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` ... LL | check_copy(&gen_non_clone); - | ^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`, the trait `Copy` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`, the trait `Copy` is not implemented for `NonClone` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:83:14 + --> $DIR/clone-impl.rs:84:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 + --> $DIR/clone-impl.rs:92:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` @@ -63,22 +85,22 @@ LL + #[derive(Copy)] LL | struct NonClone; | -error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` - --> $DIR/clone-impl.rs:87:17 +error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` + --> $DIR/clone-impl.rs:88:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}` ... LL | check_clone(&gen_non_clone); - | ^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:81:5: 81:12}`, the trait `Clone` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:82:5: 82:12}`, the trait `Clone` is not implemented for `NonClone` | note: captured value does not implement `Clone` - --> $DIR/clone-impl.rs:83:14 + --> $DIR/clone-impl.rs:84:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone` note: required by a bound in `check_clone` - --> $DIR/clone-impl.rs:92:19 + --> $DIR/clone-impl.rs:93:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` @@ -88,28 +110,6 @@ LL + #[derive(Clone)] LL | struct NonClone; | -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}` - --> $DIR/clone-impl.rs:59:5 - | -LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}` -... -LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:5: 54:12}`, the trait `Copy` is not implemented for `Vec` - | -note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/clone-impl.rs:56:9 - | -LL | let v = vec!['a']; - | - has type `Vec` which does not implement `Copy` -LL | yield; - | ^^^^^ yield occurs here, with `v` maybe used later -note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:91:18 - | -LL | fn check_copy(_x: &T) {} - | ^^^^ required by this bound in `check_copy` - error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr index 892b5d261c2..3a5e8ec4dab 100644 --- a/tests/ui/coroutine/ref-upvar-not-send.stderr +++ b/tests/ui/coroutine/ref-upvar-not-send.stderr @@ -1,14 +1,13 @@ error: coroutine cannot be sent between threads safely - --> $DIR/ref-upvar-not-send.rs:15:30 + --> $DIR/ref-upvar-not-send.rs:15:5 | -LL | assert_send(#[coroutine] move || { - | ______________________________^ +LL | / assert_send(#[coroutine] move || { LL | | LL | | LL | | yield; LL | | let _x = x; LL | | }); - | |_____^ coroutine is not `Send` + | |______^ coroutine is not `Send` | = help: the trait `Sync` is not implemented for `*mut ()` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` @@ -23,16 +22,15 @@ LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` error: coroutine cannot be sent between threads safely - --> $DIR/ref-upvar-not-send.rs:23:30 + --> $DIR/ref-upvar-not-send.rs:23:5 | -LL | assert_send(#[coroutine] move || { - | ______________________________^ +LL | / assert_send(#[coroutine] move || { LL | | LL | | LL | | yield; LL | | let _y = y; LL | | }); - | |_____^ coroutine is not `Send` + | |______^ coroutine is not `Send` | = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()` note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` diff --git a/tests/ui/impl-trait/issues/issue-55872-3.stderr b/tests/ui/impl-trait/issues/issue-55872-3.stderr index ce2dd7f02b4..b7711e47468 100644 --- a/tests/ui/impl-trait/issues/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issues/issue-55872-3.stderr @@ -1,12 +1,3 @@ -error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}: Copy` is not satisfied - --> $DIR/issue-55872-3.rs:14:20 - | -LL | fn foo() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` -... -LL | async {} - | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` here - error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias --> $DIR/issue-55872-3.rs:14:20 | @@ -21,6 +12,12 @@ LL | fn foo() -> Self::E { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}: Copy` is not satisfied + --> $DIR/issue-55872-3.rs:14:20 + | +LL | fn foo() -> Self::E { + | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5 From e9765781b2857da90161157a3fc523f9e1d58848 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 25 Jul 2025 16:46:11 +0000 Subject: Remove the witness type from coroutine args --- .../rustc_borrowck/src/type_check/input_output.rs | 1 - .../rustc_hir_analysis/src/collect/generics_of.rs | 12 +++------ compiler/rustc_hir_typeck/src/closure.rs | 5 ---- compiler/rustc_middle/src/ty/generic_args.rs | 29 ++++++++-------------- compiler/rustc_middle/src/ty/print/pretty.rs | 8 ++---- .../src/solve/assembly/structural_traits.rs | 20 ++++++++++++--- .../src/traits/select/candidate_assembly.rs | 4 +-- .../rustc_trait_selection/src/traits/select/mod.rs | 14 ++++++++--- compiler/rustc_type_ir/src/ty_kind/closure.rs | 27 -------------------- ...sync_await.b-{closure#0}.coroutine_resume.0.mir | 8 ------ .../ui/async-await/async-closures/def-path.stderr | 4 +-- ...igher-ranked-auto-trait-6.no_assumptions.stderr | 26 +------------------ .../print/coroutine-print-verbose-2.stderr | 4 +-- .../print/coroutine-print-verbose-3.stderr | 2 +- tests/ui/impl-trait/issues/issue-55872-2.rs | 1 - tests/ui/impl-trait/issues/issue-55872-2.stderr | 10 +------- tests/ui/impl-trait/issues/issue-55872-3.rs | 1 - tests/ui/impl-trait/issues/issue-55872-3.stderr | 14 +++-------- 18 files changed, 54 insertions(+), 136 deletions(-) (limited to 'tests/ui') diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 99392ea1915..eb31b5de05d 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -86,7 +86,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // them with fresh ty vars. resume_ty: next_ty_var(), yield_ty: next_ty_var(), - witness: next_ty_var(), }, ) .args, diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 31e9c3b80fb..e2462c2d465 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -379,20 +379,14 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // for info on the usage of each of these fields. let dummy_args = match kind { ClosureKind::Closure => &["", "", ""][..], - ClosureKind::Coroutine(_) => &[ - "", - "", - "", - "", - "", - "", - ][..], + ClosureKind::Coroutine(_) => { + &["", "", "", "", ""][..] + } ClosureKind::CoroutineClosure(_) => &[ "", "", "", "", - "", ][..], }; diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a413f805873..82b7c578a1f 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -161,8 +161,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Resume type defaults to `()` if the coroutine has no argument. let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); - let interior = Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args); - // Coroutines that come from coroutine closures have not yet determined // their kind ty, so make a fresh infer var which will be constrained // later during upvar analysis. Regular coroutines always have the kind @@ -182,7 +180,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { resume_ty, yield_ty, return_ty: liberated_sig.output(), - witness: interior, tupled_upvars_ty, }, ); @@ -210,7 +207,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Compute all of the variables that will be used to populate the coroutine. let resume_ty = self.next_ty_var(expr_span); - let interior = self.next_ty_var(expr_span); let closure_kind_ty = match expected_kind { Some(kind) => Ty::from_closure_kind(tcx, kind), @@ -243,7 +239,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), tupled_upvars_ty, coroutine_captures_by_ref_ty, - coroutine_witness_ty: interior, }, ); diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 7d34d8df3f3..b02abb5ab43 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -96,14 +96,12 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArg signature_parts_ty, tupled_upvars_ty, coroutine_captures_by_ref_ty, - coroutine_witness_ty, ] => ty::CoroutineClosureArgsParts { parent_args, closure_kind_ty: closure_kind_ty.expect_ty(), signature_parts_ty: signature_parts_ty.expect_ty(), tupled_upvars_ty: tupled_upvars_ty.expect_ty(), coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(), - coroutine_witness_ty: coroutine_witness_ty.expect_ty(), }, _ => bug!("closure args missing synthetics"), } @@ -111,23 +109,16 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArg fn split_coroutine_args(self) -> ty::CoroutineArgsParts> { match self[..] { - [ - ref parent_args @ .., - kind_ty, - resume_ty, - yield_ty, - return_ty, - witness, - tupled_upvars_ty, - ] => ty::CoroutineArgsParts { - parent_args, - kind_ty: kind_ty.expect_ty(), - resume_ty: resume_ty.expect_ty(), - yield_ty: yield_ty.expect_ty(), - return_ty: return_ty.expect_ty(), - witness: witness.expect_ty(), - tupled_upvars_ty: tupled_upvars_ty.expect_ty(), - }, + [ref parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => { + ty::CoroutineArgsParts { + parent_args, + kind_ty: kind_ty.expect_ty(), + resume_ty: resume_ty.expect_ty(), + yield_ty: yield_ty.expect_ty(), + return_ty: return_ty.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + } + } _ => bug!("coroutine args missing synthetics"), } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5c44b10ba71..71eac294f15 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -913,9 +913,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { " yield_ty=", print(args.as_coroutine().yield_ty()), " return_ty=", - print(args.as_coroutine().return_ty()), - " witness=", - print(args.as_coroutine().witness()) + print(args.as_coroutine().return_ty()) ); } @@ -1035,9 +1033,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { " upvar_tys=", print(args.as_coroutine_closure().tupled_upvars_ty()), " coroutine_captures_by_ref_ty=", - print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), - " coroutine_witness_ty=", - print(args.as_coroutine_closure().coroutine_witness_ty()) + print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()) ); } p!("}}"); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index c0bebdf6fb6..faa86734d08 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -75,9 +75,16 @@ where Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()])) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { let coroutine_args = args.as_coroutine(); - Ok(ty::Binder::dummy(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])) + Ok(ty::Binder::dummy(vec![ + coroutine_args.tupled_upvars_ty(), + Ty::new_coroutine_witness( + ecx.cx(), + def_id, + ecx.cx().mk_args(coroutine_args.parent_args().as_slice()), + ), + ])) } ty::CoroutineWitness(def_id, args) => Ok(ecx @@ -245,7 +252,14 @@ where Movability::Movable => { if ecx.cx().features().coroutine_clone() { let coroutine = args.as_coroutine(); - Ok(ty::Binder::dummy(vec![coroutine.tupled_upvars_ty(), coroutine.witness()])) + Ok(ty::Binder::dummy(vec![ + coroutine.tupled_upvars_ty(), + Ty::new_coroutine_witness( + ecx.cx(), + def_id, + ecx.cx().mk_args(coroutine.parent_args().as_slice()), + ), + ])) } else { Err(NoSolution) } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index af6dafb3062..62795c8a3a6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1166,9 +1166,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.tcx().features().coroutine_clone() { let resolved_upvars = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); - let resolved_witness = - self.infcx.shallow_resolve(args.as_coroutine().witness()); - if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() { + if resolved_upvars.is_ty_var() { // Not yet resolved. candidates.ambiguous = true; } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e893add81c8..7ea1548f8f2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2196,7 +2196,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { args.as_coroutine() .upvar_tys() .iter() - .chain([args.as_coroutine().witness()]) + .chain([Ty::new_coroutine_witness( + self.tcx(), + coroutine_def_id, + self.tcx().mk_args(args.as_coroutine().parent_args()), + )]) .collect::>(), ) } else { @@ -2327,9 +2331,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ty::Binder::dummy(AutoImplConstituents { types: vec![ty], assumptions: vec![] }) } - ty::Coroutine(_, args) => { + ty::Coroutine(def_id, args) => { let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); - let witness = args.as_coroutine().witness(); + let witness = Ty::new_coroutine_witness( + self.tcx(), + def_id, + self.tcx().mk_args(args.as_coroutine().parent_args()), + ); ty::Binder::dummy(AutoImplConstituents { types: [ty].into_iter().chain(iter::once(witness)).collect(), assumptions: vec![], diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index d1ca9bdb7fb..c32f8339d0b 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -101,7 +101,6 @@ use crate::{self as ty, Interner}; /// `yield` inside the coroutine. /// * `GR`: The "return type", which is the type of value returned upon /// completion of the coroutine. -/// * `GW`: The "coroutine witness". #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct ClosureArgs { @@ -239,8 +238,6 @@ pub struct CoroutineClosureArgsParts { /// while the `tupled_upvars_ty`, representing the by-move version of the same /// captures, will be `(String,)`. pub coroutine_captures_by_ref_ty: I::Ty, - /// Witness type returned by the generator produced by this coroutine-closure. - pub coroutine_witness_ty: I::Ty, } impl CoroutineClosureArgs { @@ -251,7 +248,6 @@ impl CoroutineClosureArgs { parts.signature_parts_ty.into(), parts.tupled_upvars_ty.into(), parts.coroutine_captures_by_ref_ty.into(), - parts.coroutine_witness_ty.into(), ])), } } @@ -292,7 +288,6 @@ impl CoroutineClosureArgs { } pub fn coroutine_closure_sig(self) -> ty::Binder> { - let interior = self.coroutine_witness_ty(); let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { panic!() }; sig_tys.map_bound(|sig_tys| { let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else { @@ -302,7 +297,6 @@ impl CoroutineClosureArgs { panic!() }; CoroutineClosureSignature { - interior, tupled_inputs_ty, resume_ty, yield_ty, @@ -318,10 +312,6 @@ impl CoroutineClosureArgs { self.split().coroutine_captures_by_ref_ty } - pub fn coroutine_witness_ty(self) -> I::Ty { - self.split().coroutine_witness_ty - } - pub fn has_self_borrows(&self) -> bool { match self.coroutine_captures_by_ref_ty().kind() { ty::FnPtr(sig_tys, _) => sig_tys @@ -361,7 +351,6 @@ impl TypeVisitor for HasRegionsBoundAt { #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct CoroutineClosureSignature { - pub interior: I::Ty, pub tupled_inputs_ty: I::Ty, pub resume_ty: I::Ty, pub yield_ty: I::Ty, @@ -407,7 +396,6 @@ impl CoroutineClosureSignature { resume_ty: self.resume_ty, yield_ty: self.yield_ty, return_ty: self.return_ty, - witness: self.interior, tupled_upvars_ty, }, ); @@ -587,11 +575,6 @@ pub struct CoroutineArgsParts { pub yield_ty: I::Ty, pub return_ty: I::Ty, - /// The interior type of the coroutine. - /// Represents all types that are stored in locals - /// in the coroutine's body. - pub witness: I::Ty, - /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. pub tupled_upvars_ty: I::Ty, @@ -607,7 +590,6 @@ impl CoroutineArgs { parts.resume_ty.into(), parts.yield_ty.into(), parts.return_ty.into(), - parts.witness.into(), parts.tupled_upvars_ty.into(), ])), } @@ -629,15 +611,6 @@ impl CoroutineArgs { self.split().kind_ty } - /// This describes the types that can be contained in a coroutine. - /// It will be a type variable initially and unified in the last stages of typeck of a body. - /// It contains a tuple of all the types that could end up on a coroutine frame. - /// The state transformation MIR pass may only produce layouts which mention types - /// in this tuple. Upvars are not counted here. - pub fn witness(self) -> I::Ty { - self.split().witness - } - /// Returns an iterator over the list of types of captured paths by the coroutine. /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 109a41d1ef9..9bff257e063 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -9,10 +9,6 @@ std::future::ResumeTy, (), (), - CoroutineWitness( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [], - ), (), ], ), @@ -30,10 +26,6 @@ std::future::ResumeTy, (), (), - CoroutineWitness( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [], - ), (), ], ), diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr index 58a5b0b79c4..a507fa69760 100644 --- a/tests/ui/async-await/async-closures/def-path.stderr +++ b/tests/ui/async-await/async-closures/def-path.stderr @@ -5,11 +5,11 @@ LL | let x = async || {}; | -- the expected `async` closure body LL | LL | let () = x(); - | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?15t resume_ty=ResumeTy yield_ty=() return_ty=() witness={main::{closure#0}::{closure#0}}}` + | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?14t resume_ty=ResumeTy yield_ty=() return_ty=()}` | | | expected `async` closure body, found `()` | - = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?15t resume_ty=ResumeTy yield_ty=() return_ty=() witness={main::{closure#0}::{closure#0}}}` + = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?14t resume_ty=ResumeTy yield_ty=() return_ty=()}` found unit type `()` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr index d1f2d9a0753..d1c88101618 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr @@ -21,30 +21,6 @@ LL | Box::new(async { new(|| async { f().await }).await }) = help: consider pinning your async block and casting it to a trait object = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0308]: mismatched types - --> $DIR/higher-ranked-auto-trait-6.rs:16:5 - | -LL | Box::new(async { new(|| async { f().await }).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - = note: no two async blocks, even if identical, have the same type - = help: consider pinning your async block and casting it to a trait object - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0308]: mismatched types - --> $DIR/higher-ranked-auto-trait-6.rs:16:5 - | -LL | Box::new(async { new(|| async { f().await }).await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` - = note: no two async blocks, even if identical, have the same type - = help: consider pinning your async block and casting it to a trait object - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr index 8877d45ddda..11b78e3bcf8 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr @@ -9,7 +9,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Sync` | - = help: within `{main::{closure#0} upvar_tys=() resume_ty=() yield_ty=() return_ty=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync` + = help: within `{main::{closure#0} upvar_tys=() resume_ty=() yield_ty=() return_ty=()}`, the trait `Sync` is not implemented for `NotSync` note: coroutine is not `Sync` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:20:9 | @@ -34,7 +34,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Send` | - = help: within `{main::{closure#1} upvar_tys=() resume_ty=() yield_ty=() return_ty=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend` + = help: within `{main::{closure#1} upvar_tys=() resume_ty=() yield_ty=() return_ty=()}`, the trait `Send` is not implemented for `NotSend` note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:27:9 | diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr index 4a1e5b078a8..135e8175793 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr @@ -11,7 +11,7 @@ LL | | }; | |_____^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{main::{closure#0} upvar_tys=?4t resume_ty=() yield_ty=i32 return_ty=&'?1 str witness={main::{closure#0}}}` + found coroutine `{main::{closure#0} upvar_tys=?4t resume_ty=() yield_ty=i32 return_ty=&'?1 str}` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-55872-2.rs b/tests/ui/impl-trait/issues/issue-55872-2.rs index a3b2225126a..aea00dd9e3d 100644 --- a/tests/ui/impl-trait/issues/issue-55872-2.rs +++ b/tests/ui/impl-trait/issues/issue-55872-2.rs @@ -12,7 +12,6 @@ impl Bar for S { type E = impl std::marker::Send; fn foo() -> Self::E { //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - //~| ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias async {} } } diff --git a/tests/ui/impl-trait/issues/issue-55872-2.stderr b/tests/ui/impl-trait/issues/issue-55872-2.stderr index 51a7dd00ade..91c2ecdc8a4 100644 --- a/tests/ui/impl-trait/issues/issue-55872-2.stderr +++ b/tests/ui/impl-trait/issues/issue-55872-2.stderr @@ -4,13 +4,5 @@ error: type parameter `T` is part of concrete type but not used in parameter lis LL | fn foo() -> Self::E { | ^^^^^^^ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:13:20 - | -LL | fn foo() -> Self::E { - | ^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-55872-3.rs b/tests/ui/impl-trait/issues/issue-55872-3.rs index 763b4b9fd32..698e7f36234 100644 --- a/tests/ui/impl-trait/issues/issue-55872-3.rs +++ b/tests/ui/impl-trait/issues/issue-55872-3.rs @@ -14,7 +14,6 @@ impl Bar for S { fn foo() -> Self::E { //~^ ERROR : Copy` is not satisfied [E0277] //~| ERROR type parameter `T` is part of concrete type - //~| ERROR type parameter `T` is part of concrete type async {} } } diff --git a/tests/ui/impl-trait/issues/issue-55872-3.stderr b/tests/ui/impl-trait/issues/issue-55872-3.stderr index b7711e47468..5124c46baeb 100644 --- a/tests/ui/impl-trait/issues/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issues/issue-55872-3.stderr @@ -4,20 +4,12 @@ error: type parameter `T` is part of concrete type but not used in parameter lis LL | fn foo() -> Self::E { | ^^^^^^^ -error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-3.rs:14:20 - | -LL | fn foo() -> Self::E { - | ^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}: Copy` is not satisfied +error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}: Copy` is not satisfied --> $DIR/issue-55872-3.rs:14:20 | LL | fn foo() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:18:9: 18:14}` + | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:17:9: 17:14}` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5 From 8a3a7e625a8b607c018cdcf776fa79e29eaa56c8 Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 22 Jul 2025 20:54:22 +0200 Subject: Add lint against dangling pointers form local variables --- compiler/rustc_lint/messages.ftl | 6 + compiler/rustc_lint/src/dangling.rs | 150 ++++++++++++- compiler/rustc_lint/src/lints.rs | 16 ++ tests/ui/lint/dangling-pointers-from-locals.rs | 188 ++++++++++++++++ tests/ui/lint/dangling-pointers-from-locals.stderr | 247 +++++++++++++++++++++ 5 files changed, 599 insertions(+), 8 deletions(-) create mode 100644 tests/ui/lint/dangling-pointers-from-locals.rs create mode 100644 tests/ui/lint/dangling-pointers-from-locals.stderr (limited to 'tests/ui') diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 69fe7fe83ff..4d0c0c94a81 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -207,6 +207,12 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i lint_custom_inner_attribute_unstable = custom inner attributes are unstable +lint_dangling_pointers_from_locals = a dangling pointer will be produced because the local variable `{$local_var_name}` will be dropped + .ret_ty = return type of the {$fn_kind} is `{$ret_ty}` + .local_var = `{$local_var_name}` is part the {$fn_kind} and will be dropped at the end of the {$fn_kind} + .created_at = dangling pointer created here + .note = pointers do not have a lifetime; after returning, the `{$local_var_ty}` will be deallocated at the end of the {$fn_kind} because nothing is referencing it as far as the type system is concerned + lint_dangling_pointers_from_temporaries = a dangling pointer will be produced because the temporary `{$ty}` will be dropped .label_ptr = this pointer will immediately be invalid .label_temporary = this `{$ty}` is deallocated at the end of the statement, bind it to a variable to extend its lifetime diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index 9e19949c3b6..af4457f4314 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -1,13 +1,14 @@ use rustc_ast::visit::{visit_opt, walk_list}; use rustc_hir::attrs::AttributeKind; +use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; -use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem, find_attr}; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, LangItem, TyKind, find_attr}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::{Span, sym}; -use crate::lints::DanglingPointersFromTemporaries; +use crate::lints::{DanglingPointersFromLocals, DanglingPointersFromTemporaries}; use crate::{LateContext, LateLintPass}; declare_lint! { @@ -42,6 +43,36 @@ declare_lint! { "detects getting a pointer from a temporary" } +declare_lint! { + /// The `dangling_pointers_from_locals` lint detects getting a pointer to data + /// of a local that will be dropped at the end of the function. + /// + /// ### Example + /// + /// ```rust + /// fn f() -> *const u8 { + /// let x = 0; + /// &x // returns a dangling ptr to `x` + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Returning a pointer from a local value will not prolong its lifetime, + /// which means that the value can be dropped and the allocation freed + /// while the pointer still exists, making the pointer dangling. + /// This is not an error (as far as the type system is concerned) + /// but probably is not what the user intended either. + /// + /// If you need stronger guarantees, consider using references instead, + /// as they are statically verified by the borrow-checker to never dangle. + pub DANGLING_POINTERS_FROM_LOCALS, + Warn, + "detects returning a pointer from a local variable" +} + /// FIXME: false negatives (i.e. the lint is not emitted when it should be) /// 1. Ways to get a temporary that are not recognized: /// - `owning_temporary.field` @@ -53,20 +84,123 @@ declare_lint! { #[derive(Clone, Copy, Default)] pub(crate) struct DanglingPointers; -impl_lint_pass!(DanglingPointers => [DANGLING_POINTERS_FROM_TEMPORARIES]); +impl_lint_pass!(DanglingPointers => [DANGLING_POINTERS_FROM_TEMPORARIES, DANGLING_POINTERS_FROM_LOCALS]); // This skips over const blocks, but they cannot use or return a dangling pointer anyways. impl<'tcx> LateLintPass<'tcx> for DanglingPointers { fn check_fn( &mut self, cx: &LateContext<'tcx>, - _: FnKind<'tcx>, - _: &'tcx FnDecl<'tcx>, + fn_kind: FnKind<'tcx>, + fn_decl: &'tcx FnDecl<'tcx>, body: &'tcx Body<'tcx>, _: Span, - _: LocalDefId, + def_id: LocalDefId, ) { - DanglingPointerSearcher { cx, inside_call_args: false }.visit_body(body) + DanglingPointerSearcher { cx, inside_call_args: false }.visit_body(body); + + if let FnRetTy::Return(ret_ty) = &fn_decl.output + && let TyKind::Ptr(_) = ret_ty.kind + { + // get the return type of the function or closure + let ty = match cx.tcx.type_of(def_id).instantiate_identity().kind() { + ty::FnDef(..) => cx.tcx.fn_sig(def_id).instantiate_identity(), + ty::Closure(_, args) => args.as_closure().sig(), + _ => return, + }; + let ty = ty.output(); + + // this type is only used for layout computation and pretty-printing, neither of them rely on regions + let ty = cx.tcx.instantiate_bound_regions_with_erased(ty); + + // verify that we have a pointer type + let inner_ty = match ty.kind() { + ty::RawPtr(inner_ty, _) => *inner_ty, + _ => return, + }; + + if cx + .tcx + .layout_of(cx.typing_env().as_query_input(inner_ty)) + .is_ok_and(|layout| !layout.is_1zst()) + { + let dcx = &DanglingPointerLocalContext { + body: def_id, + fn_ret: ty, + fn_ret_span: ret_ty.span, + fn_ret_inner: inner_ty, + fn_kind: match fn_kind { + FnKind::ItemFn(..) => "function", + FnKind::Method(..) => "method", + FnKind::Closure => "closure", + }, + }; + + // look for `return`s + DanglingPointerReturnSearcher { cx, dcx }.visit_body(body); + + // analyze implicit return expression + if let ExprKind::Block(block, None) = &body.value.kind + && let innermost_block = block.innermost_block() + && let Some(expr) = innermost_block.expr + { + lint_addr_of_local(cx, dcx, expr); + } + } + } + } +} + +struct DanglingPointerLocalContext<'tcx> { + body: LocalDefId, + fn_ret: Ty<'tcx>, + fn_ret_span: Span, + fn_ret_inner: Ty<'tcx>, + fn_kind: &'static str, +} + +struct DanglingPointerReturnSearcher<'lcx, 'tcx> { + cx: &'lcx LateContext<'tcx>, + dcx: &'lcx DanglingPointerLocalContext<'tcx>, +} + +impl<'tcx> Visitor<'tcx> for DanglingPointerReturnSearcher<'_, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result { + if let ExprKind::Ret(Some(expr)) = expr.kind { + lint_addr_of_local(self.cx, self.dcx, expr); + } + walk_expr(self, expr) + } +} + +/// Look for `&` pattern and emit lint for it +fn lint_addr_of_local<'a>( + cx: &LateContext<'a>, + dcx: &DanglingPointerLocalContext<'a>, + expr: &'a Expr<'a>, +) { + // peel casts as they do not interest us here, we want the inner expression. + let (inner, _) = super::utils::peel_casts(cx, expr); + + if let ExprKind::AddrOf(_, _, inner_of) = inner.kind + && let ExprKind::Path(ref qpath) = inner_of.peel_blocks().kind + && let Res::Local(from) = cx.qpath_res(qpath, inner_of.hir_id) + && cx.tcx.hir_enclosing_body_owner(from) == dcx.body + { + cx.tcx.emit_node_span_lint( + DANGLING_POINTERS_FROM_LOCALS, + expr.hir_id, + expr.span, + DanglingPointersFromLocals { + ret_ty: dcx.fn_ret, + ret_ty_span: dcx.fn_ret_span, + fn_kind: dcx.fn_kind, + local_var: cx.tcx.hir_span(from), + local_var_name: cx.tcx.hir_ident(from), + local_var_ty: dcx.fn_ret_inner, + created_at: (expr.hir_id != inner.hir_id).then_some(inner.span), + }, + ); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index fd8d0f832aa..ef63c0dee8c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1188,6 +1188,22 @@ pub(crate) struct DanglingPointersFromTemporaries<'tcx> { pub temporary_span: Span, } +#[derive(LintDiagnostic)] +#[diag(lint_dangling_pointers_from_locals)] +#[note] +pub(crate) struct DanglingPointersFromLocals<'tcx> { + pub ret_ty: Ty<'tcx>, + #[label(lint_ret_ty)] + pub ret_ty_span: Span, + pub fn_kind: &'static str, + #[label(lint_local_var)] + pub local_var: Span, + pub local_var_name: Ident, + pub local_var_ty: Ty<'tcx>, + #[label(lint_created_at)] + pub created_at: Option, +} + // multiple_supertrait_upcastable.rs #[derive(LintDiagnostic)] #[diag(lint_multiple_supertrait_upcastable)] diff --git a/tests/ui/lint/dangling-pointers-from-locals.rs b/tests/ui/lint/dangling-pointers-from-locals.rs new file mode 100644 index 00000000000..e321df2f427 --- /dev/null +++ b/tests/ui/lint/dangling-pointers-from-locals.rs @@ -0,0 +1,188 @@ +//@ check-pass + +struct Zst((), ()); +struct Adt(u8); + +const X: u8 = 5; + +fn simple() -> *const u8 { + let x = 0; + &x + //~^ WARN a dangling pointer will be produced +} + +fn bindings() -> *const u8 { + let x = 0; + let x = &x; + x + //~^ WARN a dangling pointer will be produced +} + +fn bindings_with_return() -> *const u8 { + let x = 42; + let y = &x; + return y; + //~^ WARN a dangling pointer will be produced +} + +fn with_simple_cast() -> *const u8 { + let x = 0u8; + &x as *const u8 + //~^ WARN a dangling pointer will be produced +} + +fn bindings_and_casts() -> *const u8 { + let x = 0u8; + let x = &x as *const u8; + x as *const u8 + //~^ WARN a dangling pointer will be produced +} + +fn return_with_complex_cast() -> *mut u8 { + let mut x = 0u8; + return &mut x as *mut u8 as *const u8 as *mut u8; + //~^ WARN a dangling pointer will be produced +} + +fn with_block() -> *const u8 { + let x = 0; + &{ x } + //~^ WARN a dangling pointer will be produced +} + +fn with_many_blocks() -> *const u8 { + let x = 0; + { + { + &{ + //~^ WARN a dangling pointer will be produced + { x } + } + } + } +} + +fn simple_return() -> *const u8 { + let x = 0; + return &x; + //~^ WARN a dangling pointer will be produced +} + +fn return_mut() -> *mut u8 { + let mut x = 0; + return &mut x; + //~^ WARN a dangling pointer will be produced +} + +fn const_and_flow() -> *const u8 { + if false { + let x = 8; + return &x; + //~^ WARN a dangling pointer will be produced + } + &X // not dangling +} + +fn vector() -> *const Vec { + let x = vec![T::default()]; + &x + //~^ WARN a dangling pointer will be produced +} + +fn local_adt() -> *const Adt { + let x = Adt(5); + return &x; + //~^ WARN a dangling pointer will be produced +} + +fn closure() -> *const u8 { + let _x = || -> *const u8 { + let x = 8; + return &x; + //~^ WARN a dangling pointer will be produced + }; + &X // not dangling +} + +fn fn_ptr() -> *const fn() -> u8 { + fn ret_u8() -> u8 { + 0 + } + + let x = ret_u8 as fn() -> u8; + &x + //~^ WARN a dangling pointer will be produced +} + +fn as_arg(a: Adt) -> *const Adt { + &a + //~^ WARN a dangling pointer will be produced +} + +fn fn_ptr_as_arg(a: fn() -> u8) -> *const fn() -> u8 { + &a + //~^ WARN a dangling pointer will be produced +} + +fn ptr_as_arg(a: *const Adt) -> *const *const Adt { + &a + //~^ WARN a dangling pointer will be produced +} + +fn adt_as_arg(a: &Adt) -> *const &Adt { + &a + //~^ WARN a dangling pointer will be produced +} + +fn unit() -> *const () { + let x = (); + &x // not dangling +} + +fn zst() -> *const Zst { + let x = Zst((), ()); + &x // not dangling +} + +fn ref_implicit(a: &Adt) -> *const Adt { + a // not dangling +} + +fn ref_explicit(a: &Adt) -> *const Adt { + &*a // not dangling +} + +fn identity(a: *const Adt) -> *const Adt { + a // not dangling +} + +fn from_ref(a: &Adt) -> *const Adt { + std::ptr::from_ref(a) // not dangling +} + +fn inner_static() -> *const u8 { + static U: u8 = 5; + if false { + return &U as *const u8; // not dangling + } + &U // not dangling +} + +fn return_in_closure() { + let x = 0; + let c = || -> *const u8 { + &x // not dangling by it-self + }; +} + +fn option() -> *const Option { + let x = Some(T::default()); + &x // can't compute layout of `Option`, so cnat' be sure it won't be a ZST +} + +fn generic() -> *const T { + let x = T::default(); + &x // can't compute layout of `T`, so can't be sure it won't be a ZST +} + +fn main() {} diff --git a/tests/ui/lint/dangling-pointers-from-locals.stderr b/tests/ui/lint/dangling-pointers-from-locals.stderr new file mode 100644 index 00000000000..e1d28bf22a0 --- /dev/null +++ b/tests/ui/lint/dangling-pointers-from-locals.stderr @@ -0,0 +1,247 @@ +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:10:5 + | +LL | fn simple() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | let x = 0; + | - `x` is part the function and will be dropped at the end of the function +LL | &x + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: `#[warn(dangling_pointers_from_locals)]` on by default + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:17:5 + | +LL | fn bindings() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | let x = 0; + | - `x` is part the function and will be dropped at the end of the function +LL | let x = &x; + | -- dangling pointer created here +LL | x + | ^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:24:12 + | +LL | fn bindings_with_return() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | let x = 42; + | - `x` is part the function and will be dropped at the end of the function +LL | let y = &x; + | -- dangling pointer created here +LL | return y; + | ^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:30:5 + | +LL | fn with_simple_cast() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | let x = 0u8; + | - `x` is part the function and will be dropped at the end of the function +LL | &x as *const u8 + | --^^^^^^^^^^^^^ + | | + | dangling pointer created here + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:37:5 + | +LL | fn bindings_and_casts() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | let x = 0u8; + | - `x` is part the function and will be dropped at the end of the function +LL | let x = &x as *const u8; + | -- dangling pointer created here +LL | x as *const u8 + | ^^^^^^^^^^^^^^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:43:12 + | +LL | fn return_with_complex_cast() -> *mut u8 { + | ------- return type of the function is `*mut u8` +LL | let mut x = 0u8; + | ----- `x` is part the function and will be dropped at the end of the function +LL | return &mut x as *mut u8 as *const u8 as *mut u8; + | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | dangling pointer created here + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:49:5 + | +LL | fn with_block() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | let x = 0; + | - `x` is part the function and will be dropped at the end of the function +LL | &{ x } + | ^^^^^^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:57:13 + | +LL | fn with_many_blocks() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | let x = 0; + | - `x` is part the function and will be dropped at the end of the function +... +LL | / &{ +LL | | +LL | | { x } +LL | | } + | |_____________^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:67:12 + | +LL | fn simple_return() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | let x = 0; + | - `x` is part the function and will be dropped at the end of the function +LL | return &x; + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:73:12 + | +LL | fn return_mut() -> *mut u8 { + | ------- return type of the function is `*mut u8` +LL | let mut x = 0; + | ----- `x` is part the function and will be dropped at the end of the function +LL | return &mut x; + | ^^^^^^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:80:16 + | +LL | fn const_and_flow() -> *const u8 { + | --------- return type of the function is `*const u8` +LL | if false { +LL | let x = 8; + | - `x` is part the function and will be dropped at the end of the function +LL | return &x; + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:88:5 + | +LL | fn vector() -> *const Vec { + | ------------- return type of the function is `*const Vec` +LL | let x = vec![T::default()]; + | - `x` is part the function and will be dropped at the end of the function +LL | &x + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `Vec` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:94:12 + | +LL | fn local_adt() -> *const Adt { + | ---------- return type of the function is `*const Adt` +LL | let x = Adt(5); + | - `x` is part the function and will be dropped at the end of the function +LL | return &x; + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:101:16 + | +LL | let _x = || -> *const u8 { + | --------- return type of the closure is `*const u8` +LL | let x = 8; + | - `x` is part the closure and will be dropped at the end of the closure +LL | return &x; + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the closure because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `x` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:113:5 + | +LL | fn fn_ptr() -> *const fn() -> u8 { + | ----------------- return type of the function is `*const fn() -> u8` +... +LL | let x = ret_u8 as fn() -> u8; + | - `x` is part the function and will be dropped at the end of the function +LL | &x + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `fn() -> u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `a` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:118:5 + | +LL | fn as_arg(a: Adt) -> *const Adt { + | - ---------- return type of the function is `*const Adt` + | | + | `a` is part the function and will be dropped at the end of the function +LL | &a + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `a` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:123:5 + | +LL | fn fn_ptr_as_arg(a: fn() -> u8) -> *const fn() -> u8 { + | - ----------------- return type of the function is `*const fn() -> u8` + | | + | `a` is part the function and will be dropped at the end of the function +LL | &a + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `fn() -> u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `a` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:128:5 + | +LL | fn ptr_as_arg(a: *const Adt) -> *const *const Adt { + | - ----------------- return type of the function is `*const *const Adt` + | | + | `a` is part the function and will be dropped at the end of the function +LL | &a + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `*const Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: a dangling pointer will be produced because the local variable `a` will be dropped + --> $DIR/dangling-pointers-from-locals.rs:133:5 + | +LL | fn adt_as_arg(a: &Adt) -> *const &Adt { + | - ----------- return type of the function is `*const &Adt` + | | + | `a` is part the function and will be dropped at the end of the function +LL | &a + | ^^ + | + = note: pointers do not have a lifetime; after returning, the `&Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + +warning: 19 warnings emitted + -- cgit 1.4.1-3-g733a5 From 5aec4379e304ef280ee9a470e7ab121e4a81fd17 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Thu, 31 Jul 2025 23:59:06 +0200 Subject: detect infinite recursion with tail calls in ctfe --- compiler/rustc_mir_transform/src/ctfe_limit.rs | 2 +- .../explicit-tail-calls/infinite-recursion-in-ctfe.rs | 10 ++++++++++ .../infinite-recursion-in-ctfe.stderr | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.rs create mode 100644 tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr (limited to 'tests/ui') diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index fb17cca30f4..ac46336b834 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -18,7 +18,7 @@ impl<'tcx> crate::MirPass<'tcx> for CtfeLimit { .basic_blocks .iter_enumerated() .filter_map(|(node, node_data)| { - if matches!(node_data.terminator().kind, TerminatorKind::Call { .. }) + if matches!(node_data.terminator().kind, TerminatorKind::Call { .. } | TerminatorKind::TailCall { .. }) // Back edges in a CFG indicate loops || has_back_edge(doms, node, node_data) { diff --git a/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.rs b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.rs new file mode 100644 index 00000000000..0c55f13c16c --- /dev/null +++ b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.rs @@ -0,0 +1,10 @@ +#![feature(explicit_tail_calls)] +#![expect(incomplete_features)] + +const _: () = f(); + +const fn f() { + become f(); //~ error: constant evaluation is taking a long time +} + +fn main() {} diff --git a/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr new file mode 100644 index 00000000000..b5a96114a58 --- /dev/null +++ b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr @@ -0,0 +1,17 @@ +error: constant evaluation is taking a long time + --> $DIR/infinite-recursion-in-ctfe.rs:7:5 + | +LL | become f(); + | ^^^^^^^^^^ + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint. +help: the constant being evaluated + --> $DIR/infinite-recursion-in-ctfe.rs:4:1 + | +LL | const _: () = f(); + | ^^^^^^^^^^^ + = note: `#[deny(long_running_const_eval)]` on by default + +error: aborting due to 1 previous error + -- cgit 1.4.1-3-g733a5 From 040f71e8123b5994177f787e64aecd9b06cdfa7e Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 25 Jul 2025 15:18:51 +0200 Subject: loop match: error on `#[const_continue]` outside `#[loop_match]` --- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir_typeck/src/loops.rs | 50 ++++++++++++---------- compiler/rustc_mir_build/messages.ftl | 2 +- compiler/rustc_mir_build/src/errors.rs | 4 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 4 +- tests/ui/loop-match/const-continue-to-block.rs | 21 +++++++++ tests/ui/loop-match/const-continue-to-block.stderr | 17 +++++++- tests/ui/loop-match/invalid.rs | 19 ++++++++ tests/ui/loop-match/invalid.stderr | 22 +++++++--- 9 files changed, 107 insertions(+), 34 deletions(-) (limited to 'tests/ui') diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1b1b3ced44d..08361718108 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3016,7 +3016,7 @@ impl fmt::Display for LoopIdError { } } -#[derive(Copy, Clone, Debug, HashStable_Generic)] +#[derive(Copy, Clone, Debug, PartialEq, HashStable_Generic)] pub struct Destination { /// This is `Some(_)` iff there is an explicit user-specified 'label pub label: Option