summaryrefslogtreecommitdiffstats
path: root/tests/ui/rfcs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
commit64d98f8ee037282c35007b64c2649055c56af1db (patch)
tree5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /tests/ui/rfcs
parentAdding debian version 1.67.1+dfsg1-1. (diff)
downloadrustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz
rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/rfcs')
-rw-r--r--tests/ui/rfcs/rfc-1014-2.rs31
-rw-r--r--tests/ui/rfcs/rfc-1014.rs34
-rw-r--r--tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs20
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs6
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-empty.rs2
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs7
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs3
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs6
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result.rs6
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs4
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs18
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs40
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs45
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs20
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs249
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs34
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs9
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs16
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs14
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs25
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs22
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs19
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs12
-rw-r--r--tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs15
-rw-r--r--tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs20
-rw-r--r--tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs32
-rw-r--r--tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs38
-rw-r--r--tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs33
-rw-r--r--tests/ui/rfcs/rfc-2302-self-struct-ctor.rs127
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs52
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs20
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs6
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs12
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr18
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs34
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr105
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs9
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr83
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs69
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr83
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs21
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr11
-rw-r--r--tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs15
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs28
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs29
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr22
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs12
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs31
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs43
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr15
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs56
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr21
-rw-r--r--tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs23
-rw-r--r--tests/ui/rfcs/rfc1445/eq-allows-match.rs17
-rw-r--r--tests/ui/rfcs/rfc1623-2.rs99
-rw-r--r--tests/ui/rfcs/rfc1623-2.stderr39
-rw-r--r--tests/ui/rfcs/rfc1623-3.rs14
-rw-r--r--tests/ui/rfcs/rfc1623-3.stderr35
-rw-r--r--tests/ui/rfcs/rfc1623.rs75
-rw-r--r--tests/ui/rfcs/rfc1717/library-override.rs14
-rw-r--r--tests/ui/rfcs/rfc1857-drop-order.rs224
64 files changed, 2286 insertions, 0 deletions
diff --git a/tests/ui/rfcs/rfc-1014-2.rs b/tests/ui/rfcs/rfc-1014-2.rs
new file mode 100644
index 000000000..7dd65701f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1014-2.rs
@@ -0,0 +1,31 @@
+// run-pass
+#![allow(dead_code)]
+
+#![feature(rustc_private)]
+
+extern crate libc;
+
+type DWORD = u32;
+type HANDLE = *mut u8;
+type BOOL = i32;
+
+#[cfg(windows)]
+extern "system" {
+ fn SetStdHandle(nStdHandle: DWORD, nHandle: HANDLE) -> BOOL;
+}
+
+#[cfg(windows)]
+fn close_stdout() {
+ const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
+ unsafe { SetStdHandle(STD_OUTPUT_HANDLE, 0 as HANDLE); }
+}
+
+#[cfg(windows)]
+fn main() {
+ close_stdout();
+ println!("hello");
+ println!("world");
+}
+
+#[cfg(not(windows))]
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-1014.rs b/tests/ui/rfcs/rfc-1014.rs
new file mode 100644
index 000000000..c454dfa4e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1014.rs
@@ -0,0 +1,34 @@
+// run-pass
+#![allow(dead_code)]
+// ignore-wasm32-bare no libc
+// ignore-sgx no libc
+
+#![feature(rustc_private)]
+
+extern crate libc;
+
+type DWORD = u32;
+type HANDLE = *mut u8;
+
+#[cfg(windows)]
+extern "system" {
+ fn GetStdHandle(which: DWORD) -> HANDLE;
+ fn CloseHandle(handle: HANDLE) -> i32;
+}
+
+#[cfg(windows)]
+fn close_stdout() {
+ const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
+ unsafe { CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE)); }
+}
+
+#[cfg(not(windows))]
+fn close_stdout() {
+ unsafe { libc::close(1); }
+}
+
+fn main() {
+ close_stdout();
+ println!("hello");
+ println!("world");
+}
diff --git a/tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs b/tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs
new file mode 100644
index 000000000..329fadb15
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+#![feature(as_array_of_cells)]
+
+use std::cell::Cell;
+
+fn main() {
+ let slice: &mut [i32] = &mut [1, 2, 3];
+ let cell_slice: &Cell<[i32]> = Cell::from_mut(slice);
+ let slice_cell: &[Cell<i32>] = cell_slice.as_slice_of_cells();
+
+ assert_eq!(slice_cell.len(), 3);
+
+ let mut array: [i32; 3] = [1, 2, 3];
+ let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
+ let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
+
+ array_cell[0].set(99);
+ assert_eq!(array, [99, 2, 3]);
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
new file mode 100644
index 000000000..e98582cbc
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
@@ -0,0 +1,6 @@
+// run-pass
+use std::error::Error;
+
+fn main() -> Result<(), Box<dyn Error>> {
+ Ok(())
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-empty.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-empty.rs
new file mode 100644
index 000000000..bac695d4e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-empty.rs
@@ -0,0 +1,2 @@
+// run-pass
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs
new file mode 100644
index 000000000..6d4c15620
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs
@@ -0,0 +1,7 @@
+// run-pass
+
+use std::process::ExitCode;
+
+fn main() -> ExitCode {
+ ExitCode::SUCCESS
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs
new file mode 100644
index 000000000..c06a135dc
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs
@@ -0,0 +1,3 @@
+// run-pass
+
+fn main() -> impl std::process::Termination { }
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs
new file mode 100644
index 000000000..b0e932e1f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs
@@ -0,0 +1,6 @@
+// run-pass
+use std::io::Error;
+
+fn main() -> Result<(), Box<Error>> {
+ Ok(())
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result.rs
new file mode 100644
index 000000000..30f36c244
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result.rs
@@ -0,0 +1,6 @@
+// run-pass
+use std::io::Error;
+
+fn main() -> Result<(), Error> {
+ Ok(())
+}
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs
new file mode 100644
index 000000000..f0591c38c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs
@@ -0,0 +1,4 @@
+// run-pass
+fn main() -> Result<(), &'static str> {
+ Ok(())
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs
new file mode 100644
index 000000000..0d1cded36
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(unreachable_patterns)]
+#![feature(box_patterns)]
+
+struct Foo{}
+
+pub fn main() {
+ let b = Box::new(Foo{});
+ let box f = &b;
+ let _: &Foo = f;
+
+ match &&&b {
+ box f => {
+ let _: &Foo = f;
+ },
+ _ => panic!(),
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs
new file mode 100644
index 000000000..d5bca6a24
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs
@@ -0,0 +1,40 @@
+// run-pass
+const CONST_REF: &[u8; 3] = b"foo";
+
+trait Foo {
+ const CONST_REF_DEFAULT: &'static [u8; 3] = b"bar";
+ const CONST_REF: &'static [u8; 3];
+}
+
+impl Foo for i32 {
+ const CONST_REF: &'static [u8; 3] = b"jjj";
+}
+
+impl Foo for i64 {
+ const CONST_REF_DEFAULT: &'static [u8; 3] = b"ggg";
+ const CONST_REF: &'static [u8; 3] = b"fff";
+}
+
+// Check that (associated and free) const references are not mistaken for a
+// non-reference pattern (in which case they would be auto-dereferenced, making
+// the types mismatched).
+
+fn const_ref() -> bool {
+ let f = b"foo";
+ match f {
+ CONST_REF => true,
+ _ => false,
+ }
+}
+
+fn associated_const_ref() -> bool {
+ match (b"bar", b"jjj", b"ggg", b"fff") {
+ (i32::CONST_REF_DEFAULT, i32::CONST_REF, i64::CONST_REF_DEFAULT, i64::CONST_REF) => true,
+ _ => false,
+ }
+}
+
+pub fn main() {
+ assert!(const_ref());
+ assert!(associated_const_ref());
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs
new file mode 100644
index 000000000..52fbb90ed
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs
@@ -0,0 +1,45 @@
+// run-pass
+enum Wrapper {
+ Wrap(i32),
+}
+
+use Wrapper::Wrap;
+
+pub fn main() {
+ let Wrap(x) = &Wrap(3);
+ println!("{}", *x);
+
+ let Wrap(x) = &mut Wrap(3);
+ println!("{}", *x);
+
+ if let Some(x) = &Some(3) {
+ println!("{}", *x);
+ } else {
+ panic!();
+ }
+
+ if let Some(x) = &mut Some(3) {
+ println!("{}", *x);
+ } else {
+ panic!();
+ }
+
+ if let Some(x) = &mut Some(3) {
+ *x += 1;
+ } else {
+ panic!();
+ }
+
+ while let Some(x) = &Some(3) {
+ println!("{}", *x);
+ break;
+ }
+ while let Some(x) = &mut Some(3) {
+ println!("{}", *x);
+ break;
+ }
+ while let Some(x) = &mut Some(3) {
+ *x += 1;
+ break;
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs
new file mode 100644
index 000000000..a5a24a806
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs
@@ -0,0 +1,20 @@
+// run-pass
+pub fn main() {
+ let mut tups = vec![(0u8, 1u8)];
+
+ for (n, m) in &tups {
+ let _: &u8 = n;
+ let _: &u8 = m;
+ }
+
+ for (n, m) in &mut tups {
+ *n += 1;
+ *m += 2;
+ }
+
+ assert_eq!(tups, vec![(1u8, 3u8)]);
+
+ for (n, m) in tups {
+ println!("{} {}", m, n);
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs
new file mode 100644
index 000000000..0207f607b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs
@@ -0,0 +1,249 @@
+// run-pass
+#![allow(unused_variables)]
+fn some_or_wildcard(r: &Option<i32>, b: &i32) {
+ let _: &i32 = match r {
+ Some(a) => a,
+ _ => b,
+ };
+}
+
+fn none_or_wildcard(r: &Option<i32>, b: &i32) {
+ let _: &i32 = match r {
+ None => b,
+ _ => b,
+ };
+}
+
+fn some_or_ref_none(r: &Option<i32>, b: &i32) {
+ let _: &i32 = match r {
+ Some(a) => a,
+ &None => b,
+ };
+}
+
+fn ref_some_or_none(r: &Option<i32>, b: &i32) {
+ let _: &i32 = match r {
+ &Some(ref a) => a,
+ None => b,
+ };
+}
+
+fn some_or_self(r: &Option<i32>) {
+ let _: &Option<i32> = match r {
+ Some(n) => {
+ let _: &i32 = n;
+ r
+ },
+ x => x,
+ };
+}
+
+fn multiple_deref(r: &&&&&Option<i32>) {
+ let _: i32 = match r {
+ Some(a) => *a,
+ None => 5,
+ };
+}
+
+fn match_with_or() {
+ // FIXME(tschottdorf): #44912.
+ //
+ // let x = &Some((3, 3));
+ // let _: &i32 = match x {
+ // Some((x, 3)) | &Some((ref x, 5)) => x,
+ // _ => &5i32,
+ // };
+}
+
+fn nested_mixed() {
+ match (&Some(5), &Some(6)) {
+ (Some(a), &Some(mut b)) => {
+ // Here, the `a` will be `&i32`, because in the first half of the tuple
+ // we hit a non-reference pattern and shift into `ref` mode.
+ //
+ // In the second half of the tuple there's no non-reference pattern,
+ // so `b` will be `i32` (bound with `move` mode). Moreover, `b` is
+ // mutable.
+ let _: &i32 = a;
+ b = 7;
+ let _: i32 = b;
+ },
+ _ => {},
+ };
+}
+
+fn nested_mixed_multiple_deref_1() {
+ let x = (1, &Some(5));
+ let y = &Some(x);
+ match y {
+ Some((a, Some(b))) => {
+ let _: &i32 = a;
+ let _: &i32 = b;
+ },
+ _ => {},
+ };
+}
+
+fn nested_mixed_multiple_deref_2() {
+ let x = &Some(5);
+ let y = &x;
+ match y {
+ Some(z) => {
+ let _: &i32 = z;
+ },
+ _ => {},
+ }
+}
+
+fn new_mutable_reference() {
+ let mut x = &mut Some(5);
+ match &mut x {
+ Some(y) => {
+ *y = 5;
+ },
+ None => { },
+ }
+
+ match &mut x {
+ Some(y) => {
+ println!("{}", *y);
+ },
+ None => {},
+ }
+}
+
+fn let_implicit_ref_binding() {
+ struct Foo(i32);
+
+ // Note that these rules apply to any pattern matching
+ // whether it be in a `match` or a `let`.
+ // For example, `x` here is a `ref` binding:
+ let Foo(x) = &Foo(3);
+ let _: &i32 = x;
+}
+
+fn explicit_mut_binding() {
+ match &Some(5i32) {
+ Some(mut n) => {
+ n += 1;
+ let _ = n;
+ }
+ None => {},
+ };
+
+ match &mut Some(5i32) {
+ Some(n) => {
+ *n += 1;
+ let _ = n;
+ }
+ None => {},
+ };
+
+ match &mut &mut Some(5i32) {
+ Some(n) => {
+ let _: &mut i32 = n;
+ }
+ None => {},
+ };
+}
+
+fn tuple_mut_and_mut_mut() {
+ match (Some(5i32), &Some(5i32)) {
+ (Some(n), Some(m)) => {
+ // `n` and `m` are bound as immutable references. Make new references from them to
+ // assert that.
+ let r = n;
+ let _ = r;
+ let q = m;
+ let _ = q;
+
+ // Assert the types. Note that we use `n` and `m` here which would fail had they been
+ // moved due to the assignments above.
+ let _: i32 = n;
+ let _: &i32 = m;
+ }
+ (_, _) => {},
+ };
+
+ match (&Some(5i32), &&Some(5i32)) {
+ (Some(n), Some(m)) => {
+ let _: &i32 = n;
+ let _: &i32 = m;
+ }
+ (_, _) => {},
+ };
+
+ match &mut &mut (Some(5i32), Some(5i32)) {
+ (Some(n), Some(m)) => {
+ // Dereferenced through &mut &mut, so a mutable binding results.
+ let _: &mut i32 = n;
+ let _: &mut i32 = m;
+ }
+ (_, _) => {},
+ };
+
+ match (&mut Some(5i32), &mut &mut Some(5i32)) {
+ (Some(n), Some(m)) => {
+ let _: &mut i32 = n;
+ let _: &mut i32 = m;
+ }
+ (_, _) => {},
+ };
+}
+
+fn min_mir_embedded_type() {
+ // The reduced invocation that an ICE was diagnosed with (was consuming
+ // adjustments in wrong order).
+ match (0u8, &&Some(5i32)) {
+ (_, Some(m)) => {
+ let _: &i32 = m;
+ }
+ (_, _) => {},
+ };
+}
+
+fn no_autoderef() {
+ // Binding.
+ let x = &3;
+ println!("{}", *x);
+
+ // Wildcard.
+ let _ = &3;
+
+ // Constant of generic type (string)
+ const Y: &'static str = "foo";
+ assert_eq!(0, match "foo" {
+ Y => 0,
+ _ => 1,
+ });
+
+ // Reference pattern.
+ let &x = &3;
+}
+
+pub fn main() {
+ let r: &Option<i32> = &Some(3);
+ let b = &4i32;
+
+ none_or_wildcard(r, b);
+ some_or_wildcard(r, b);
+ some_or_ref_none(r, b);
+ ref_some_or_none(r, b);
+
+ some_or_self(r);
+ multiple_deref(&&&&r);
+ match_with_or();
+
+ nested_mixed();
+ nested_mixed_multiple_deref_1();
+ nested_mixed_multiple_deref_2();
+
+ new_mutable_reference();
+ explicit_mut_binding();
+ tuple_mut_and_mut_mut();
+ min_mir_embedded_type();
+
+ let_implicit_ref_binding();
+
+ no_autoderef();
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs
new file mode 100644
index 000000000..937975359
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs
@@ -0,0 +1,34 @@
+// run-pass
+#![allow(dead_code)]
+fn with_u8() {
+ let s = 5u8;
+ let r = match &s {
+ 4 => false,
+ 5 => true,
+ _ => false,
+ };
+ assert!(r);
+}
+
+// A string literal isn't mistaken for a non-ref pattern (in which case we'd
+// deref `s` and mess things up).
+fn with_str() {
+ let s: &'static str = "abc";
+ match s {
+ "abc" => true,
+ _ => panic!(),
+ };
+}
+
+// Ditto with byte strings.
+fn with_bytes() {
+ let s: &'static [u8] = b"abc";
+ match s {
+ b"abc" => true,
+ _ => panic!(),
+ };
+}
+
+pub fn main() {
+ with_str();
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs
new file mode 100644
index 000000000..f8abd1b96
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs
@@ -0,0 +1,9 @@
+// run-pass
+pub fn main() {
+ let i = 5;
+ match &&&&i {
+ 1 ..= 3 => panic!(),
+ 4 ..= 8 => {},
+ _ => panic!(),
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs
new file mode 100644
index 000000000..b74e45c93
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs
@@ -0,0 +1,16 @@
+// run-pass
+fn foo<'a, 'b>(x: &'a &'b Option<u32>) -> &'a u32 {
+ let x: &'a &'a Option<u32> = x;
+ match x {
+ Some(r) => {
+ let _: &u32 = r;
+ r
+ },
+ &None => panic!(),
+ }
+}
+
+pub fn main() {
+ let x = Some(5);
+ foo(&&x);
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs
new file mode 100644
index 000000000..3b9d07610
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs
@@ -0,0 +1,14 @@
+// run-pass
+// Test that we "reset" the mode as we pass through a `&` pattern.
+//
+// cc #46688
+
+fn surprise(x: i32) {
+ assert_eq!(x, 2);
+}
+
+fn main() {
+ let x = &(1, &2);
+ let (_, &b) = x;
+ surprise(b);
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
new file mode 100644
index 000000000..33229a205
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+fn slice_pat() {
+ let sl: &[u8] = b"foo";
+
+ match sl {
+ [first, remainder @ ..] => {
+ let _: &u8 = first;
+ assert_eq!(first, &b'f');
+ assert_eq!(remainder, b"oo");
+ }
+ [] => panic!(),
+ }
+}
+
+fn slice_pat_omission() {
+ match &[0, 1, 2] {
+ [..] => {}
+ };
+}
+
+fn main() {
+ slice_pat();
+ slice_pat_omission();
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs
new file mode 100644
index 000000000..5a00e5b68
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs
@@ -0,0 +1,22 @@
+// run-pass
+#[derive(Debug, PartialEq)]
+struct Foo {
+ x: u8,
+}
+
+pub fn main() {
+ let mut foo = Foo {
+ x: 1,
+ };
+
+ match &mut foo {
+ Foo{x: n} => {
+ *n += 1;
+ },
+ };
+
+ assert_eq!(foo, Foo{x: 2});
+
+ let Foo{x: n} = &foo;
+ assert_eq!(*n, 2);
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs
new file mode 100644
index 000000000..0cf9ba1b4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(dead_code)]
+enum Foo {
+ Bar(Option<i8>, (), (), Vec<i32>),
+ Baz,
+}
+
+pub fn main() {
+ let foo = Foo::Bar(Some(1), (), (), vec![2, 3]);
+
+ match &foo {
+ Foo::Baz => panic!(),
+ Foo::Bar(None, ..) => panic!(),
+ Foo::Bar(Some(n), .., v) => {
+ assert_eq!((*v).len(), 2);
+ assert_eq!(*n, 1);
+ }
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs
new file mode 100644
index 000000000..4c22aa2d7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs
@@ -0,0 +1,12 @@
+// run-pass
+pub fn main() {
+ let foo = (Some(1), (), (), vec![2, 3]);
+
+ match &foo {
+ (Some(n), .., v) => {
+ assert_eq!((*v).len(), 2);
+ assert_eq!(*n, 1);
+ }
+ (None, (), (), ..) => panic!(),
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs b/tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs
new file mode 100644
index 000000000..d359067f6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs
@@ -0,0 +1,15 @@
+// run-pass
+use std::mem;
+
+#[r#repr(r#C, r#packed)]
+struct Test {
+ a: bool, b: u64
+}
+
+#[r#derive(r#Debug)]
+struct Test2(#[allow(unused_tuple_struct_fields)] u32);
+
+pub fn main() {
+ assert_eq!(mem::size_of::<Test>(), 9);
+ assert_eq!("Test2(123)", format!("{:?}", Test2(123)));
+}
diff --git a/tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs b/tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs
new file mode 100644
index 000000000..f2fe59668
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs
@@ -0,0 +1,20 @@
+// run-pass
+fn r#fn(r#match: u32) -> u32 {
+ r#match
+}
+
+pub fn main() {
+ let r#struct = 1;
+ assert_eq!(1, r#struct);
+
+ let foo = 2;
+ assert_eq!(2, r#foo);
+
+ let r#bar = 3;
+ assert_eq!(3, bar);
+
+ assert_eq!(4, r#fn(4));
+
+ let r#true = false;
+ assert_eq!(r#true, false);
+}
diff --git a/tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs b/tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs
new file mode 100644
index 000000000..466522517
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs
@@ -0,0 +1,32 @@
+// run-pass
+#[derive(Debug, PartialEq, Eq)]
+struct IntWrapper(u32);
+
+#[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Hash, Copy, Clone, Default)]
+struct HasKeywordField {
+ r#struct: u32,
+}
+
+struct Generic<r#T>(T);
+
+trait Trait {
+ fn r#trait(&self) -> u32;
+}
+impl Trait for Generic<u32> {
+ fn r#trait(&self) -> u32 {
+ self.0
+ }
+}
+
+pub fn main() {
+ assert_eq!(IntWrapper(1), r#IntWrapper(1));
+
+ match IntWrapper(2) {
+ r#IntWrapper(r#struct) => assert_eq!(2, r#struct),
+ }
+
+ assert_eq!("HasKeywordField { struct: 3 }", format!("{:?}", HasKeywordField { r#struct: 3 }));
+
+ assert_eq!(4, Generic(4).0);
+ assert_eq!(5, Generic(5).r#trait());
+}
diff --git a/tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs b/tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs
new file mode 100644
index 000000000..0ab7e17f8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs
@@ -0,0 +1,38 @@
+// run-pass
+#![feature(decl_macro)]
+
+macro_rules! r#struct {
+ ($r#struct:expr) => { $r#struct }
+}
+
+macro_rules! old_macro {
+ ($a:expr) => {$a}
+}
+
+macro r#decl_macro($r#fn:expr) {
+ $r#fn
+}
+
+macro passthrough($id:ident) {
+ $id
+}
+
+macro_rules! test_pat_match {
+ (a) => { 6 };
+ (r#a) => { 7 };
+}
+
+pub fn main() {
+ r#println!("{struct}", r#struct = 1);
+ assert_eq!(2, r#struct!(2));
+ assert_eq!(3, r#old_macro!(3));
+ assert_eq!(4, decl_macro!(4));
+
+ let r#match = 5;
+ assert_eq!(5, passthrough!(r#match));
+
+ assert_eq!("r#struct", stringify!(r#struct));
+
+ assert_eq!(6, test_pat_match!(a));
+ assert_eq!(7, test_pat_match!(r#a));
+}
diff --git a/tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs b/tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs
new file mode 100644
index 000000000..22f04c58f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs
@@ -0,0 +1,33 @@
+// run-pass
+#![allow(dead_code)]
+
+enum E {
+ V(u8),
+ U(u8),
+ W,
+}
+use E::*;
+
+fn main() {
+ let mut e = V(10);
+
+ if let V(x) | U(x) = e {
+ assert_eq!(x, 10);
+ }
+ while let V(x) | U(x) = e {
+ assert_eq!(x, 10);
+ e = W;
+ }
+
+ // Accept leading `|`:
+
+ let mut e = V(10);
+
+ if let | V(x) | U(x) = e {
+ assert_eq!(x, 10);
+ }
+ while let | V(x) | U(x) = e {
+ assert_eq!(x, 10);
+ e = W;
+ }
+}
diff --git a/tests/ui/rfcs/rfc-2302-self-struct-ctor.rs b/tests/ui/rfcs/rfc-2302-self-struct-ctor.rs
new file mode 100644
index 000000000..1ec20c500
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2302-self-struct-ctor.rs
@@ -0,0 +1,127 @@
+// run-pass
+
+#![allow(dead_code)]
+
+use std::fmt::Display;
+
+struct ST1(i32, i32);
+
+impl ST1 {
+ fn new() -> Self {
+ ST1(0, 1)
+ }
+
+ fn ctor() -> Self {
+ Self(1,2) // Self as a constructor
+ }
+
+ fn pattern(self) {
+ match self {
+ Self(x, y) => println!("{} {}", x, y), // Self as a pattern
+ }
+ }
+}
+
+struct ST2<T>(T); // With type parameter
+
+impl<T> ST2<T> where T: Display {
+
+ fn ctor(v: T) -> Self {
+ Self(v)
+ }
+
+ fn pattern(&self) {
+ match self {
+ Self(ref v) => println!("{}", v),
+ }
+ }
+}
+
+struct ST3<'a>(&'a i32); // With lifetime parameter
+
+impl<'a> ST3<'a> {
+
+ fn ctor(v: &'a i32) -> Self {
+ Self(v)
+ }
+
+ fn pattern(self) {
+ let Self(ref v) = self;
+ println!("{}", v);
+ }
+}
+
+struct ST4(usize);
+
+impl ST4 {
+ fn map(opt: Option<usize>) -> Option<Self> {
+ opt.map(Self) // use `Self` as a function passed somewhere
+ }
+}
+
+struct ST5; // unit struct
+
+impl ST5 {
+ fn ctor() -> Self {
+ Self // `Self` as a unit struct value
+ }
+
+ fn pattern(self) -> Self {
+ match self {
+ Self => Self, // `Self` as a unit struct value for matching
+ }
+ }
+}
+
+struct ST6(i32);
+type T = ST6;
+impl T {
+ fn ctor() -> Self {
+ ST6(1)
+ }
+
+ fn type_alias(self) {
+ let Self(_x) = match self { Self(x) => Self(x) };
+ let _opt: Option<Self> = Some(0).map(Self);
+ }
+}
+
+struct ST7<T1, T2>(T1, T2);
+
+impl ST7<i32, usize> {
+
+ fn ctor() -> Self {
+ Self(1, 2)
+ }
+
+ fn pattern(self) -> Self {
+ match self {
+ Self(x, y) => Self(x, y),
+ }
+ }
+}
+
+fn main() {
+ let v1 = ST1::ctor();
+ v1.pattern();
+
+ let v2 = ST2::ctor(10);
+ v2.pattern();
+
+ let local = 42;
+ let v3 = ST3::ctor(&local);
+ v3.pattern();
+
+ let v4 = Some(1usize);
+ let _ = ST4::map(v4);
+
+ let v5 = ST5::ctor();
+ v5.pattern();
+
+ let v6 = ST6::ctor();
+ v6.type_alias();
+
+ let v7 = ST7::<i32, usize>::ctor();
+ let r = v7.pattern();
+ println!("{} {}", r.0, r.1)
+}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs
new file mode 100644
index 000000000..e0842bfa4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs
@@ -0,0 +1,52 @@
+// Tests the new rules added by RFC 2396, including:
+// - applying `#[target_feature]` to safe functions is allowed
+// - calling functions with `#[target_feature]` is allowed in
+// functions which have (at least) the same features
+// - calling functions with `#[target_feature]` is allowed in
+// unsafe contexts
+// - functions with `#[target_feature]` can coerce to unsafe fn pointers
+
+// check-pass
+// only-x86_64
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![feature(target_feature_11)]
+
+#[target_feature(enable = "sse2")]
+const fn sse2() {}
+
+#[cfg(target_feature = "sse2")]
+const SSE2_ONLY: () = unsafe {
+ sse2();
+};
+
+#[target_feature(enable = "sse2")]
+fn also_sse2() {
+ sse2();
+}
+
+#[target_feature(enable = "sse2")]
+#[target_feature(enable = "avx")]
+fn sse2_and_avx() {
+ sse2();
+}
+
+struct Foo;
+
+impl Foo {
+ #[target_feature(enable = "sse2")]
+ fn sse2(&self) {
+ sse2();
+ }
+}
+
+fn main() {
+ if cfg!(target_feature = "sse2") {
+ unsafe {
+ sse2();
+ Foo.sse2();
+ }
+ }
+ let sse2_ptr: unsafe fn() = sse2;
+}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs
new file mode 100644
index 000000000..a59d7c2d7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs
@@ -0,0 +1,20 @@
+// Tests #73631: closures inherit `#[target_feature]` annotations
+
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+// only-x86_64
+
+#![feature(target_feature_11)]
+
+#[target_feature(enable="avx")]
+fn also_use_avx() {
+ println!("Hello from AVX")
+}
+
+#[target_feature(enable="avx")]
+fn use_avx() -> Box<dyn Fn()> {
+ Box::new(|| also_use_avx())
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs
new file mode 100644
index 000000000..975d7a1f6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs
@@ -0,0 +1,6 @@
+// only-x86_64
+
+#[target_feature(enable = "sse2")] //~ ERROR can only be applied to `unsafe` functions
+fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr
new file mode 100644
index 000000000..18917fd25
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr
@@ -0,0 +1,14 @@
+error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
+ --> $DIR/feature-gate-target_feature_11.rs:3:1
+ |
+LL | #[target_feature(enable = "sse2")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn foo() {}
+ | -------- not an `unsafe` function
+ |
+ = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information
+ = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
new file mode 100644
index 000000000..cf5815df5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+ --> $DIR/fn-ptr.rs:11:21
+ |
+LL | #[target_feature(enable = "sse2")]
+ | ---------------------------------- `#[target_feature]` added here
+...
+LL | let foo: fn() = foo;
+ | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers
+ | |
+ | expected due to this
+ |
+ = note: expected fn pointer `fn()`
+ found fn item `fn() {foo}`
+ = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs
new file mode 100644
index 000000000..c95d4a08e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs
@@ -0,0 +1,12 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+// only-x86_64
+
+#![feature(target_feature_11)]
+
+#[target_feature(enable = "sse2")]
+fn foo() {}
+
+fn main() {
+ let foo: fn() = foo; //~ ERROR mismatched types
+}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr
new file mode 100644
index 000000000..cf5815df5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+ --> $DIR/fn-ptr.rs:11:21
+ |
+LL | #[target_feature(enable = "sse2")]
+ | ---------------------------------- `#[target_feature]` added here
+...
+LL | let foo: fn() = foo;
+ | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers
+ | |
+ | expected due to this
+ |
+ = note: expected fn pointer `fn()`
+ found fn item `fn() {foo}`
+ = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs
new file mode 100644
index 000000000..43bda4962
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs
@@ -0,0 +1,34 @@
+// only-x86_64
+
+#![feature(target_feature_11)]
+
+#[target_feature(enable = "avx")]
+fn foo() {}
+
+#[target_feature(enable = "avx")]
+unsafe fn foo_unsafe() {}
+
+fn call(f: impl Fn()) {
+ f()
+}
+
+fn call_mut(f: impl FnMut()) {
+ f()
+}
+
+fn call_once(f: impl FnOnce()) {
+ f()
+}
+
+fn main() {
+ call(foo); //~ ERROR expected a `Fn<()>` closure, found `fn() {foo}`
+ call_mut(foo); //~ ERROR expected a `FnMut<()>` closure, found `fn() {foo}`
+ call_once(foo); //~ ERROR expected a `FnOnce<()>` closure, found `fn() {foo}`
+
+ call(foo_unsafe);
+ //~^ ERROR expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+ call_mut(foo_unsafe);
+ //~^ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+ call_once(foo_unsafe);
+ //~^ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
new file mode 100644
index 000000000..fc7bf2277
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
@@ -0,0 +1,105 @@
+error[E0277]: expected a `Fn<()>` closure, found `fn() {foo}`
+ --> $DIR/fn-traits.rs:24:10
+ |
+LL | call(foo);
+ | ---- ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}`
+ = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
+ = note: `#[target_feature]` functions do not implement the `Fn` traits
+note: required by a bound in `call`
+ --> $DIR/fn-traits.rs:11:17
+ |
+LL | fn call(f: impl Fn()) {
+ | ^^^^ required by this bound in `call`
+
+error[E0277]: expected a `FnMut<()>` closure, found `fn() {foo}`
+ --> $DIR/fn-traits.rs:25:14
+ |
+LL | call_mut(foo);
+ | -------- ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}`
+ = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
+ = note: `#[target_feature]` functions do not implement the `Fn` traits
+note: required by a bound in `call_mut`
+ --> $DIR/fn-traits.rs:15:21
+ |
+LL | fn call_mut(f: impl FnMut()) {
+ | ^^^^^^^ required by this bound in `call_mut`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `fn() {foo}`
+ --> $DIR/fn-traits.rs:26:15
+ |
+LL | call_once(foo);
+ | --------- ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}`
+ = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
+ = note: `#[target_feature]` functions do not implement the `Fn` traits
+note: required by a bound in `call_once`
+ --> $DIR/fn-traits.rs:19:22
+ |
+LL | fn call_once(f: impl FnOnce()) {
+ | ^^^^^^^^ required by this bound in `call_once`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+ --> $DIR/fn-traits.rs:28:10
+ |
+LL | call(foo_unsafe);
+ | ---- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+ = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
+ = note: `#[target_feature]` functions do not implement the `Fn` traits
+note: required by a bound in `call`
+ --> $DIR/fn-traits.rs:11:17
+ |
+LL | fn call(f: impl Fn()) {
+ | ^^^^ required by this bound in `call`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+ --> $DIR/fn-traits.rs:30:14
+ |
+LL | call_mut(foo_unsafe);
+ | -------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+ = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
+ = note: `#[target_feature]` functions do not implement the `Fn` traits
+note: required by a bound in `call_mut`
+ --> $DIR/fn-traits.rs:15:21
+ |
+LL | fn call_mut(f: impl FnMut()) {
+ | ^^^^^^^ required by this bound in `call_mut`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+ --> $DIR/fn-traits.rs:32:15
+ |
+LL | call_once(foo_unsafe);
+ | --------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+ = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
+ = note: `#[target_feature]` functions do not implement the `Fn` traits
+note: required by a bound in `call_once`
+ --> $DIR/fn-traits.rs:19:22
+ |
+LL | fn call_once(f: impl FnOnce()) {
+ | ^^^^^^^^ required by this bound in `call_once`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs
new file mode 100644
index 000000000..033dcdfc0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+#![feature(target_feature_11)]
+
+struct S<T>(T)
+where
+ [T; (|| {}, 1).1]: Copy;
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr
new file mode 100644
index 000000000..0ef7b8b09
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr
@@ -0,0 +1,83 @@
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:23:5
+ |
+LL | sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:26:5
+ |
+LL | avx_bmi2();
+ | ^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:29:5
+ |
+LL | Quux.avx_bmi2();
+ | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:36:5
+ |
+LL | avx_bmi2();
+ | ^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:39:5
+ |
+LL | Quux.avx_bmi2();
+ | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:46:5
+ |
+LL | sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:49:5
+ |
+LL | avx_bmi2();
+ | ^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:52:5
+ |
+LL | Quux.avx_bmi2();
+ | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:60:5
+ |
+LL | sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:65:18
+ |
+LL | const name: () = sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs
new file mode 100644
index 000000000..cebc6f947
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs
@@ -0,0 +1,69 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+// only-x86_64
+
+#![feature(target_feature_11)]
+
+#[target_feature(enable = "sse2")]
+const fn sse2() {}
+
+#[target_feature(enable = "avx")]
+#[target_feature(enable = "bmi2")]
+fn avx_bmi2() {}
+
+struct Quux;
+
+impl Quux {
+ #[target_feature(enable = "avx")]
+ #[target_feature(enable = "bmi2")]
+ fn avx_bmi2(&self) {}
+}
+
+fn foo() {
+ sse2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
+ avx_bmi2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
+ Quux.avx_bmi2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe
+}
+
+#[target_feature(enable = "sse2")]
+fn bar() {
+ avx_bmi2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
+ Quux.avx_bmi2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe
+}
+
+#[target_feature(enable = "avx")]
+fn baz() {
+ sse2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
+ avx_bmi2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
+ Quux.avx_bmi2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe
+}
+
+#[target_feature(enable = "avx")]
+#[target_feature(enable = "bmi2")]
+fn qux() {
+ sse2();
+ //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+ //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
+}
+
+const name: () = sse2();
+//[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
+//[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr
new file mode 100644
index 000000000..c75ac6e8b
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr
@@ -0,0 +1,83 @@
+error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:23:5
+ |
+LL | sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:26:5
+ |
+LL | avx_bmi2();
+ | ^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:29:5
+ |
+LL | Quux.avx_bmi2();
+ | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:36:5
+ |
+LL | avx_bmi2();
+ | ^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:39:5
+ |
+LL | Quux.avx_bmi2();
+ | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:46:5
+ |
+LL | sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:49:5
+ |
+LL | avx_bmi2();
+ | ^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:52:5
+ |
+LL | Quux.avx_bmi2();
+ | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:60:5
+ |
+LL | sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
+ --> $DIR/safe-calls.rs:65:18
+ |
+LL | const name: () = sse2();
+ | ^^^^^^ call to function with `#[target_feature]`
+ |
+ = note: can only be called if the required target features are available
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs
new file mode 100644
index 000000000..7314fa8cc
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs
@@ -0,0 +1,21 @@
+// only-x86_64
+
+#![feature(target_feature_11)]
+
+trait Foo {
+ fn foo(&self);
+ unsafe fn unsf_foo(&self);
+}
+
+struct Bar;
+
+impl Foo for Bar {
+ #[target_feature(enable = "sse2")]
+ //~^ ERROR cannot be applied to safe trait method
+ fn foo(&self) {}
+
+ #[target_feature(enable = "sse2")]
+ unsafe fn unsf_foo(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
new file mode 100644
index 000000000..07d6e0900
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
@@ -0,0 +1,11 @@
+error: `#[target_feature(..)]` cannot be applied to safe trait method
+ --> $DIR/trait-impl.rs:13:5
+ |
+LL | #[target_feature(enable = "sse2")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
+LL |
+LL | fn foo(&self) {}
+ | ------------- not an `unsafe` function
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs b/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs
new file mode 100644
index 000000000..6d7bca4da
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Test that removed keywords are allowed as identifiers.
+fn main () {
+ let offsetof = ();
+ let alignof = ();
+ let sizeof = ();
+ let pure = ();
+}
+
+fn offsetof() {}
+fn alignof() {}
+fn sizeof() {}
+fn pure() {}
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs
new file mode 100644
index 000000000..75e48bf4a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs
@@ -0,0 +1,28 @@
+// check-pass
+
+#![feature(type_changing_struct_update)]
+#![allow(incomplete_features)]
+
+use std::any::Any;
+
+struct Foo<A, B: ?Sized, C: ?Sized> {
+ a: A,
+ b: Box<B>,
+ c: Box<C>,
+}
+
+struct B;
+struct C;
+
+fn main() {
+ let y = Foo::<usize, dyn Any, dyn Any> {
+ a: 0,
+ b: Box::new(B),
+ ..Foo {
+ a: 0,
+ b: Box::new(B),
+ // C needs to be told to coerce to `Box<dyn Any>`
+ c: Box::new(C),
+ }
+ };
+}
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs
new file mode 100644
index 000000000..1e8b99ba5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs
@@ -0,0 +1,29 @@
+// gate-test-type_changing_struct_update
+
+#[derive(Debug)]
+struct Machine<S> {
+ state: S,
+ common_field1: &'static str,
+ common_field2: i32,
+}
+#[derive(Debug)]
+struct State1;
+#[derive(Debug, PartialEq)]
+struct State2;
+
+fn update_to_state2() {
+ let m1: Machine<State1> = Machine {
+ state: State1,
+ common_field1: "hello",
+ common_field2: 2,
+ };
+ let m2: Machine<State2> = Machine {
+ state: State2,
+ ..m1
+ //~^ ERROR type changing struct updating is experimental [E0658]
+ //~| ERROR mismatched types [E0308]
+ };
+ assert_eq!(State2, m2.state);
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr
new file mode 100644
index 000000000..2217b8c04
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr
@@ -0,0 +1,22 @@
+error[E0658]: type changing struct updating is experimental
+ --> $DIR/feature-gate.rs:22:11
+ |
+LL | ..m1
+ | ^^
+ |
+ = note: see issue #86555 <https://github.com/rust-lang/rust/issues/86555> for more information
+ = help: add `#![feature(type_changing_struct_update)]` to the crate attributes to enable
+
+error[E0308]: mismatched types
+ --> $DIR/feature-gate.rs:22:11
+ |
+LL | ..m1
+ | ^^ expected struct `State2`, found struct `State1`
+ |
+ = note: expected struct `Machine<State2>`
+ found struct `Machine<State1>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs
new file mode 100644
index 000000000..f1a54ee58
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs
@@ -0,0 +1,12 @@
+#[derive(Clone)]
+struct P<T> {
+ x: T,
+ y: f64,
+}
+
+impl<T> P<T> {
+ fn y(&self, y: f64) -> Self { P{y, .. self.clone() } }
+ //~^ mismatched types [E0308]
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
new file mode 100644
index 000000000..5957ea7c9
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-92010-trait-bound-not-satisfied.rs:8:43
+ |
+LL | fn y(&self, y: f64) -> Self { P{y, .. self.clone() } }
+ | ^^^^^^^^^^^^ expected struct `P`, found `&P<T>`
+ |
+ = note: expected struct `P<T>`
+ found reference `&P<T>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs
new file mode 100644
index 000000000..3dfbef0ee
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs
@@ -0,0 +1,31 @@
+// check-pass
+
+#![feature(type_changing_struct_update)]
+#![allow(incomplete_features)]
+
+use std::borrow::Cow;
+use std::marker::PhantomData;
+
+#[derive(Default)]
+struct NonGeneric {
+ field1: usize,
+}
+
+#[derive(Default)]
+struct Generic<T, U> {
+ field1: T,
+ field2: U,
+}
+
+#[derive(Default)]
+struct MoreGeneric<'a, const N: usize> {
+ // If only `for<const N: usize> [u32; N]: Default`...
+ field1: PhantomData<[u32; N]>,
+ field2: Cow<'a, str>,
+}
+
+fn main() {
+ let default1 = NonGeneric { ..Default::default() };
+ let default2: Generic<i32, f32> = Generic { ..Default::default() };
+ let default3: MoreGeneric<'static, 12> = MoreGeneric { ..Default::default() };
+}
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs
new file mode 100644
index 000000000..df2fef55d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs
@@ -0,0 +1,43 @@
+#![feature(type_changing_struct_update)]
+#![allow(incomplete_features)]
+
+#[derive(Clone)]
+struct Machine<'a, S> {
+ state: S,
+ lt_str: &'a str,
+ common_field: i32,
+}
+
+#[derive(Clone)]
+struct State1;
+#[derive(Clone)]
+struct State2;
+
+fn update_to_state2() {
+ let s = String::from("hello");
+ let m1: Machine<State1> = Machine {
+ state: State1,
+ lt_str: &s,
+ //~^ ERROR `s` does not live long enough [E0597]
+ // FIXME: The error here actually comes from line 34. The
+ // span of the error message should be corrected to line 34
+ common_field: 2,
+ };
+ // update lifetime
+ let m3: Machine<'static, State1> = Machine {
+ lt_str: "hello, too",
+ ..m1.clone()
+ };
+ // update lifetime and type
+ let m4: Machine<'static, State2> = Machine {
+ state: State2,
+ lt_str: "hello, again",
+ ..m1.clone()
+ };
+ // updating to `static should fail.
+ let m2: Machine<'static, State1> = Machine {
+ ..m1
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
new file mode 100644
index 000000000..5f93ad6e0
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `s` does not live long enough
+ --> $DIR/lifetime-update.rs:20:17
+ |
+LL | lt_str: &s,
+ | ^^ borrowed value does not live long enough
+...
+LL | let m2: Machine<'static, State1> = Machine {
+ | ------------------------ type annotation requires that `s` is borrowed for `'static`
+...
+LL | }
+ | - `s` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs
new file mode 100644
index 000000000..dae1241d3
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs
@@ -0,0 +1,56 @@
+#![feature(type_changing_struct_update)]
+#![allow(incomplete_features)]
+
+struct Machine<'a, S, M> {
+ state: S,
+ message: M,
+ lt_str: &'a str,
+ common_field: i32,
+}
+
+struct State1;
+struct State2;
+
+struct Message1;
+struct Message2;
+
+fn update() {
+ let m1: Machine<State1, Message1> = Machine {
+ state: State1,
+ message: Message1,
+ lt_str: "hello",
+ common_field: 2,
+ };
+ // single type update
+ let m2: Machine<State2, Message1> = Machine {
+ state: State2,
+ ..m1
+ };
+ // multiple type update
+ let m3: Machine<State2, Message2> = Machine {
+ state: State2,
+ message: Message2,
+ ..m1
+ };
+}
+
+fn fail_update() {
+ let m1: Machine<f64, f64> = Machine {
+ state: 3.2,
+ message: 6.4,
+ lt_str: "hello",
+ common_field: 2,
+ };
+ // single type update fail
+ let m2: Machine<i32, f64> = Machine {
+ ..m1
+ //~^ ERROR mismatched types [E0308]
+ };
+ // multiple type update fail
+ let m3 = Machine::<i32, i32> {
+ ..m1
+ //~^ ERROR mismatched types [E0308]
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr
new file mode 100644
index 000000000..6f31b1a96
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+ --> $DIR/type-generic-update.rs:46:11
+ |
+LL | ..m1
+ | ^^ expected `i32`, found `f64`
+ |
+ = note: expected struct `Machine<'_, i32, _>`
+ found struct `Machine<'_, f64, _>`
+
+error[E0308]: mismatched types
+ --> $DIR/type-generic-update.rs:51:11
+ |
+LL | ..m1
+ | ^^ expected `i32`, found `f64`
+ |
+ = note: expected struct `Machine<'_, i32, i32>`
+ found struct `Machine<'_, f64, f64>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs b/tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs
new file mode 100644
index 000000000..17174e22c
--- /dev/null
+++ b/tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+
+macro_rules! foo {
+ (#[$attr:meta] $x:ident) => {
+ #[$attr]
+ struct $x {
+ x: u32
+ }
+ }
+}
+
+foo! { #[derive(PartialEq, Eq)] Foo }
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+ let y = Foo { x: 1 };
+ match y {
+ FOO => { }
+ _ => { }
+ }
+}
diff --git a/tests/ui/rfcs/rfc1445/eq-allows-match.rs b/tests/ui/rfcs/rfc1445/eq-allows-match.rs
new file mode 100644
index 000000000..405a69c94
--- /dev/null
+++ b/tests/ui/rfcs/rfc1445/eq-allows-match.rs
@@ -0,0 +1,17 @@
+// run-pass
+#![allow(dead_code)]
+
+#[derive(PartialEq, Eq)]
+struct Foo {
+ x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+ let y = Foo { x: 1 };
+ match y {
+ FOO => { }
+ _ => { }
+ }
+}
diff --git a/tests/ui/rfcs/rfc1623-2.rs b/tests/ui/rfcs/rfc1623-2.rs
new file mode 100644
index 000000000..c0e13a5f5
--- /dev/null
+++ b/tests/ui/rfcs/rfc1623-2.rs
@@ -0,0 +1,99 @@
+#![allow(dead_code)]
+
+fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
+ a
+}
+
+// The incorrect case without `for<'a>` is tested for in `rfc1623-2.rs`
+static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
+ &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
+
+struct SomeStruct<'x, 'y, 'z: 'x> {
+ foo: &'x Foo<'z>,
+ bar: &'x Bar<'z>,
+ f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>,
+}
+
+// Without this, the wf-check will fail early so we'll never see the
+// error in SOME_STRUCT's body.
+unsafe impl<'x, 'y, 'z: 'x> Sync for SomeStruct<'x, 'y, 'z> {}
+
+fn id<T>(t: T) -> T {
+ t
+}
+
+static SOME_STRUCT: &SomeStruct = &SomeStruct {
+ foo: &Foo { bools: &[false, true] },
+ bar: &Bar { bools: &[true, true] },
+ f: &id,
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR implementation of `FnOnce` is not general enough
+ //~| ERROR implementation of `FnOnce` is not general enough
+};
+
+// very simple test for a 'static static with default lifetime
+static STATIC_STR: &'static str = "&'static str";
+const CONST_STR: &'static str = "&'static str";
+
+// this should be the same as without default:
+static EXPLICIT_STATIC_STR: &'static str = "&'static str";
+const EXPLICIT_CONST_STR: &'static str = "&'static str";
+
+// a function that elides to an unbound lifetime for both in- and output
+fn id_u8_slice(arg: &[u8]) -> &[u8] {
+ arg
+}
+
+// one with a function, argument elided
+static STATIC_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
+const CONST_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
+
+// this should be the same as without elision
+static STATIC_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] =
+ &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
+const CONST_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] =
+ &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
+
+// another function that elides, each to a different unbound lifetime
+fn multi_args(a: &u8, b: &u8, c: &u8) {}
+
+static STATIC_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
+const CONST_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
+
+struct Foo<'a> {
+ bools: &'a [bool],
+}
+
+static STATIC_FOO: Foo<'static> = Foo { bools: &[true, false] };
+const CONST_FOO: Foo<'static> = Foo { bools: &[true, false] };
+
+type Bar<'a> = Foo<'a>;
+
+static STATIC_BAR: Bar<'static> = Bar { bools: &[true, false] };
+const CONST_BAR: Bar<'static> = Bar { bools: &[true, false] };
+
+type Baz<'a> = fn(&'a [u8]) -> Option<u8>;
+
+fn baz(e: &[u8]) -> Option<u8> {
+ e.first().map(|x| *x)
+}
+
+static STATIC_BAZ: &'static Baz<'static> = &(baz as Baz);
+const CONST_BAZ: &'static Baz<'static> = &(baz as Baz);
+
+static BYTES: &'static [u8] = &[1, 2, 3];
+
+fn main() {
+ let x = &[1u8, 2, 3];
+ let y = x;
+
+ // this works, so lifetime < `'static` is valid
+ assert_eq!(Some(1), STATIC_BAZ(y));
+ assert_eq!(Some(1), CONST_BAZ(y));
+
+ let y = &[1u8, 2, 3];
+
+ STATIC_BAZ(BYTES); // BYTES has static lifetime
+ CONST_BAZ(y); // interestingly this does not get reported
+}
diff --git a/tests/ui/rfcs/rfc1623-2.stderr b/tests/ui/rfcs/rfc1623-2.stderr
new file mode 100644
index 000000000..d183eaaa6
--- /dev/null
+++ b/tests/ui/rfcs/rfc1623-2.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+ --> $DIR/rfc1623-2.rs:28:8
+ |
+LL | f: &id,
+ | ^^^ one type is more general than the other
+ |
+ = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
+ found trait `Fn<(&Foo<'_>,)>`
+
+error[E0308]: mismatched types
+ --> $DIR/rfc1623-2.rs:28:8
+ |
+LL | f: &id,
+ | ^^^ one type is more general than the other
+ |
+ = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
+ found trait `Fn<(&Foo<'_>,)>`
+
+error: implementation of `FnOnce` is not general enough
+ --> $DIR/rfc1623-2.rs:28:8
+ |
+LL | f: &id,
+ | ^^^ implementation of `FnOnce` is not general enough
+ |
+ = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`...
+ = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
+
+error: implementation of `FnOnce` is not general enough
+ --> $DIR/rfc1623-2.rs:28:8
+ |
+LL | f: &id,
+ | ^^^ implementation of `FnOnce` is not general enough
+ |
+ = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`...
+ = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc1623-3.rs b/tests/ui/rfcs/rfc1623-3.rs
new file mode 100644
index 000000000..26fa6fdb5
--- /dev/null
+++ b/tests/ui/rfcs/rfc1623-3.rs
@@ -0,0 +1,14 @@
+#![allow(dead_code)]
+
+fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
+ a
+}
+
+// the boundaries of elision
+static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
+//~^ ERROR missing lifetime specifier [E0106]
+ &(non_elidable as fn(&u8, &u8) -> &u8);
+ //~^ ERROR missing lifetime specifier [E0106]
+ //~| ERROR non-primitive cast
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc1623-3.stderr b/tests/ui/rfcs/rfc1623-3.stderr
new file mode 100644
index 000000000..77fc3f041
--- /dev/null
+++ b/tests/ui/rfcs/rfc1623-3.stderr
@@ -0,0 +1,35 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/rfc1623-3.rs:8:42
+ |
+LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
+ | --- --- ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the type lifetime-generic with a new `'a` lifetime
+ |
+LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
+ | +++++++ ++ ++ ++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/rfc1623-3.rs:10:39
+ |
+LL | &(non_elidable as fn(&u8, &u8) -> &u8);
+ | --- --- ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+help: consider making the type lifetime-generic with a new `'a` lifetime
+ |
+LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
+ | +++++++ ++ ++ ++
+
+error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'a, 'b> fn(&'a u8, &'b u8) -> &u8`
+ --> $DIR/rfc1623-3.rs:10:6
+ |
+LL | &(non_elidable as fn(&u8, &u8) -> &u8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0106, E0605.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/rfcs/rfc1623.rs b/tests/ui/rfcs/rfc1623.rs
new file mode 100644
index 000000000..adaf25c6b
--- /dev/null
+++ b/tests/ui/rfcs/rfc1623.rs
@@ -0,0 +1,75 @@
+// run-pass
+#![allow(unused_variables)]
+#![allow(non_upper_case_globals)]
+
+#![allow(dead_code)]
+
+// very simple test for a 'static static with default lifetime
+static STATIC_STR: &str = "&'static str";
+const CONST_STR: &str = "&'static str";
+
+// this should be the same as without default:
+static EXPLICIT_STATIC_STR: &'static str = "&'static str";
+const EXPLICIT_CONST_STR: &'static str = "&'static str";
+
+// a function that elides to an unbound lifetime for both in- and output
+fn id_u8_slice(arg: &[u8]) -> &[u8] {
+ arg
+}
+
+// one with a function, argument elided
+static STATIC_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
+const CONST_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
+
+// this should be the same as without elision
+static STATIC_NON_ELIDED_fN: &for<'a> fn(&'a [u8]) -> &'a [u8] =
+ &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
+const CONST_NON_ELIDED_fN: &for<'a> fn(&'a [u8]) -> &'a [u8] =
+ &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
+
+// another function that elides, each to a different unbound lifetime
+fn multi_args(a: &u8, b: &u8, c: &u8) {}
+
+static STATIC_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
+const CONST_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
+
+struct Foo<'a> {
+ bools: &'a [bool],
+}
+
+static STATIC_FOO: Foo = Foo { bools: &[true, false] };
+const CONST_FOO: Foo = Foo { bools: &[true, false] };
+
+type Bar<'a> = Foo<'a>;
+
+static STATIC_BAR: Bar = Bar { bools: &[true, false] };
+const CONST_BAR: Bar = Bar { bools: &[true, false] };
+
+type Baz<'a> = fn(&'a [u8]) -> Option<u8>;
+
+fn baz(e: &[u8]) -> Option<u8> {
+ e.first().map(|x| *x)
+}
+
+static STATIC_BAZ: &Baz = &(baz as Baz);
+const CONST_BAZ: &Baz = &(baz as Baz);
+
+static BYTES: &[u8] = &[1, 2, 3];
+
+fn main() {
+ // make sure that the lifetime is actually elided (and not defaulted)
+ let x = &[1u8, 2, 3];
+ STATIC_SIMPLE_FN(x);
+ CONST_SIMPLE_FN(x);
+
+ STATIC_BAZ(BYTES); // neees static lifetime
+ CONST_BAZ(BYTES);
+
+ // make sure this works with different lifetimes
+ let a = &1;
+ {
+ let b = &2;
+ let c = &3;
+ CONST_MULTI_FN(a, b, c);
+ }
+}
diff --git a/tests/ui/rfcs/rfc1717/library-override.rs b/tests/ui/rfcs/rfc1717/library-override.rs
new file mode 100644
index 000000000..014ccac31
--- /dev/null
+++ b/tests/ui/rfcs/rfc1717/library-override.rs
@@ -0,0 +1,14 @@
+// run-pass
+// ignore-wasm32-bare no libc to test ffi with
+// compile-flags: -lstatic=wronglibrary:rust_test_helpers
+
+#[link(name = "wronglibrary", kind = "dylib")]
+extern "C" {
+ pub fn rust_dbg_extern_identity_u32(x: u32) -> u32;
+}
+
+fn main() {
+ unsafe {
+ rust_dbg_extern_identity_u32(42);
+ }
+}
diff --git a/tests/ui/rfcs/rfc1857-drop-order.rs b/tests/ui/rfcs/rfc1857-drop-order.rs
new file mode 100644
index 000000000..4c4816c2f
--- /dev/null
+++ b/tests/ui/rfcs/rfc1857-drop-order.rs
@@ -0,0 +1,224 @@
+// run-pass
+// needs-unwind
+
+#![allow(dead_code, unreachable_code)]
+
+use std::cell::RefCell;
+use std::rc::Rc;
+use std::panic::{self, AssertUnwindSafe, UnwindSafe};
+
+// This struct is used to record the order in which elements are dropped
+struct PushOnDrop {
+ vec: Rc<RefCell<Vec<u32>>>,
+ val: u32
+}
+
+impl PushOnDrop {
+ fn new(val: u32, vec: Rc<RefCell<Vec<u32>>>) -> PushOnDrop {
+ PushOnDrop { vec, val }
+ }
+}
+
+impl Drop for PushOnDrop {
+ fn drop(&mut self) {
+ self.vec.borrow_mut().push(self.val)
+ }
+}
+
+impl UnwindSafe for PushOnDrop { }
+
+// Structs
+struct TestStruct {
+ x: PushOnDrop,
+ y: PushOnDrop,
+ z: PushOnDrop
+}
+
+// Tuple structs
+struct TestTupleStruct(PushOnDrop, PushOnDrop, PushOnDrop);
+
+// Enum variants
+enum TestEnum {
+ Tuple(PushOnDrop, PushOnDrop, PushOnDrop),
+ Struct { x: PushOnDrop, y: PushOnDrop, z: PushOnDrop }
+}
+
+fn test_drop_tuple() {
+ // Tuple fields are dropped in the same order they are declared
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let test_tuple = (PushOnDrop::new(1, dropped_fields.clone()),
+ PushOnDrop::new(2, dropped_fields.clone()));
+ drop(test_tuple);
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+ // Panic during construction means that fields are treated as local variables
+ // Therefore they are dropped in reverse order of initialization
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ (PushOnDrop::new(2, cloned.clone()),
+ PushOnDrop::new(1, cloned.clone()),
+ panic!("this panic is caught :D"));
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+}
+
+fn test_drop_struct() {
+ // Struct fields are dropped in the same order they are declared
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let test_struct = TestStruct {
+ x: PushOnDrop::new(1, dropped_fields.clone()),
+ y: PushOnDrop::new(2, dropped_fields.clone()),
+ z: PushOnDrop::new(3, dropped_fields.clone()),
+ };
+ drop(test_struct);
+ assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+ // The same holds for tuple structs
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let test_tuple_struct = TestTupleStruct(PushOnDrop::new(1, dropped_fields.clone()),
+ PushOnDrop::new(2, dropped_fields.clone()),
+ PushOnDrop::new(3, dropped_fields.clone()));
+ drop(test_tuple_struct);
+ assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+ // Panic during struct construction means that fields are treated as local variables
+ // Therefore they are dropped in reverse order of initialization
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ TestStruct {
+ x: PushOnDrop::new(2, cloned.clone()),
+ y: PushOnDrop::new(1, cloned.clone()),
+ z: panic!("this panic is caught :D")
+ };
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+ // Test with different initialization order
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ TestStruct {
+ y: PushOnDrop::new(2, cloned.clone()),
+ x: PushOnDrop::new(1, cloned.clone()),
+ z: panic!("this panic is caught :D")
+ };
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+ // The same holds for tuple structs
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ TestTupleStruct(PushOnDrop::new(2, cloned.clone()),
+ PushOnDrop::new(1, cloned.clone()),
+ panic!("this panic is caught :D"));
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+}
+
+fn test_drop_enum() {
+ // Enum variants are dropped in the same order they are declared
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let test_struct_enum = TestEnum::Struct {
+ x: PushOnDrop::new(1, dropped_fields.clone()),
+ y: PushOnDrop::new(2, dropped_fields.clone()),
+ z: PushOnDrop::new(3, dropped_fields.clone())
+ };
+ drop(test_struct_enum);
+ assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+ // The same holds for tuple enum variants
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let test_tuple_enum = TestEnum::Tuple(PushOnDrop::new(1, dropped_fields.clone()),
+ PushOnDrop::new(2, dropped_fields.clone()),
+ PushOnDrop::new(3, dropped_fields.clone()));
+ drop(test_tuple_enum);
+ assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+ // Panic during enum construction means that fields are treated as local variables
+ // Therefore they are dropped in reverse order of initialization
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ TestEnum::Struct {
+ x: PushOnDrop::new(2, cloned.clone()),
+ y: PushOnDrop::new(1, cloned.clone()),
+ z: panic!("this panic is caught :D")
+ };
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+ // Test with different initialization order
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ TestEnum::Struct {
+ y: PushOnDrop::new(2, cloned.clone()),
+ x: PushOnDrop::new(1, cloned.clone()),
+ z: panic!("this panic is caught :D")
+ };
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+ // The same holds for tuple enum variants
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ TestEnum::Tuple(PushOnDrop::new(2, cloned.clone()),
+ PushOnDrop::new(1, cloned.clone()),
+ panic!("this panic is caught :D"));
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+}
+
+fn test_drop_list() {
+ // Elements in a Vec are dropped in the same order they are pushed
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let xs = vec![PushOnDrop::new(1, dropped_fields.clone()),
+ PushOnDrop::new(2, dropped_fields.clone()),
+ PushOnDrop::new(3, dropped_fields.clone())];
+ drop(xs);
+ assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+ // The same holds for arrays
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let xs = [PushOnDrop::new(1, dropped_fields.clone()),
+ PushOnDrop::new(2, dropped_fields.clone()),
+ PushOnDrop::new(3, dropped_fields.clone())];
+ drop(xs);
+ assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+ // Panic during vec construction means that fields are treated as local variables
+ // Therefore they are dropped in reverse order of initialization
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ vec![
+ PushOnDrop::new(2, cloned.clone()),
+ PushOnDrop::new(1, cloned.clone()),
+ panic!("this panic is caught :D")
+ ];
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+ // The same holds for arrays
+ let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+ let cloned = AssertUnwindSafe(dropped_fields.clone());
+ panic::catch_unwind(|| {
+ [
+ PushOnDrop::new(2, cloned.clone()),
+ PushOnDrop::new(1, cloned.clone()),
+ panic!("this panic is caught :D")
+ ];
+ }).err().unwrap();
+ assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+}
+
+fn main() {
+ test_drop_tuple();
+ test_drop_struct();
+ test_drop_enum();
+ test_drop_list();
+}