about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_expand/src/expand.rs2
-rw-r--r--library/core/src/intrinsics/mod.rs1
-rw-r--r--library/core/src/sync/atomic.rs3
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs87
-rw-r--r--src/tools/tidy/src/issues.txt3
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/ui/coercion/struct-coerce-vec-to-slice.rs20
-rw-r--r--tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs16
-rw-r--r--tests/ui/issues/issue-28777.rs22
-rw-r--r--tests/ui/issues/issue-31260.rs15
-rw-r--r--tests/ui/issues/issue-9382.rs37
-rw-r--r--tests/ui/lint/inert-attr-macro.rs7
-rw-r--r--tests/ui/lint/inert-attr-macro.stderr14
-rw-r--r--tests/ui/parser/operator-precedence-braces-exprs.rs28
-rw-r--r--tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs17
-rw-r--r--tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr21
-rw-r--r--triagebot.toml17
17 files changed, 226 insertions, 86 deletions
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 87f01be26c2..e2a55752850 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1941,7 +1941,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                 let attr_name = attr.ident().unwrap().name;
                 // `#[cfg]` and `#[cfg_attr]` are special - they are
                 // eagerly evaluated.
-                if attr_name != sym::cfg && attr_name != sym::cfg_attr {
+                if attr_name != sym::cfg && attr_name != sym::cfg_attr_trace {
                     self.cx.sess.psess.buffer_lint(
                         UNUSED_ATTRIBUTES,
                         attr.span,
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index cf03c07b6a5..81e59a1f349 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3002,6 +3002,7 @@ pub const fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discrimina
 
 /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the
 /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs.
+/// Returns `1` if unwinding occurred and `catch_fn` was called; returns `0` otherwise.
 ///
 /// `catch_fn` must not unwind.
 ///
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 88bee622031..9b1b13e7129 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -469,6 +469,7 @@ impl AtomicBool {
     ///
     /// [valid]: crate::ptr#safety
     /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+    #[inline]
     #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
     pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
@@ -1389,6 +1390,7 @@ impl<T> AtomicPtr<T> {
     ///
     /// [valid]: crate::ptr#safety
     /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+    #[inline]
     #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
     pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
@@ -2525,6 +2527,7 @@ macro_rules! atomic_int {
             ///
             /// [valid]: crate::ptr#safety
             /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+            #[inline]
             #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
             #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
             pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 0ecccdc8812..4bd0cedd44c 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -585,6 +585,7 @@ mod imp {
     target_os = "openbsd",
     target_os = "solaris",
     target_os = "illumos",
+    target_os = "cygwin",
 )))]
 mod imp {
     pub unsafe fn init() {}
@@ -597,3 +598,89 @@ mod imp {
 
     pub unsafe fn drop_handler(_data: *mut libc::c_void) {}
 }
+
+#[cfg(target_os = "cygwin")]
+mod imp {
+    mod c {
+        pub type PVECTORED_EXCEPTION_HANDLER =
+            Option<unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32>;
+        pub type NTSTATUS = i32;
+        pub type BOOL = i32;
+
+        unsafe extern "system" {
+            pub fn AddVectoredExceptionHandler(
+                first: u32,
+                handler: PVECTORED_EXCEPTION_HANDLER,
+            ) -> *mut core::ffi::c_void;
+            pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL;
+        }
+
+        pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _;
+        pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32;
+
+        #[repr(C)]
+        #[derive(Clone, Copy)]
+        pub struct EXCEPTION_POINTERS {
+            pub ExceptionRecord: *mut EXCEPTION_RECORD,
+            // We don't need this field here
+            // pub Context: *mut CONTEXT,
+        }
+        #[repr(C)]
+        #[derive(Clone, Copy)]
+        pub struct EXCEPTION_RECORD {
+            pub ExceptionCode: NTSTATUS,
+            pub ExceptionFlags: u32,
+            pub ExceptionRecord: *mut EXCEPTION_RECORD,
+            pub ExceptionAddress: *mut core::ffi::c_void,
+            pub NumberParameters: u32,
+            pub ExceptionInformation: [usize; 15],
+        }
+    }
+
+    /// Reserve stack space for use in stack overflow exceptions.
+    fn reserve_stack() {
+        let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) };
+        // Reserving stack space is not critical so we allow it to fail in the released build of libstd.
+        // We still use debug assert here so that CI will test that we haven't made a mistake calling the function.
+        debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling");
+    }
+
+    unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 {
+        // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid.
+        unsafe {
+            let rec = &(*(*ExceptionInfo).ExceptionRecord);
+            let code = rec.ExceptionCode;
+
+            if code == c::EXCEPTION_STACK_OVERFLOW {
+                crate::thread::with_current_name(|name| {
+                    let name = name.unwrap_or("<unknown>");
+                    rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
+                });
+            }
+            c::EXCEPTION_CONTINUE_SEARCH
+        }
+    }
+
+    pub unsafe fn init() {
+        // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling.
+        unsafe {
+            let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler));
+            // Similar to the above, adding the stack overflow handler is allowed to fail
+            // but a debug assert is used so CI will still test that it normally works.
+            debug_assert!(!result.is_null(), "failed to install exception handler");
+        }
+        // Set the thread stack guarantee for the main thread.
+        reserve_stack();
+    }
+
+    pub unsafe fn cleanup() {}
+
+    pub unsafe fn make_handler(main_thread: bool) -> super::Handler {
+        if !main_thread {
+            reserve_stack();
+        }
+        super::Handler::null()
+    }
+
+    pub unsafe fn drop_handler(_data: *mut libc::c_void) {}
+}
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 2b9ae195478..4a929a376d7 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -2000,7 +2000,6 @@ ui/issues/issue-28586.rs
 ui/issues/issue-28600.rs
 ui/issues/issue-28625.rs
 ui/issues/issue-28776.rs
-ui/issues/issue-28777.rs
 ui/issues/issue-28828.rs
 ui/issues/issue-28839.rs
 ui/issues/issue-28936.rs
@@ -2063,7 +2062,6 @@ ui/issues/issue-3091.rs
 ui/issues/issue-31011.rs
 ui/issues/issue-3109.rs
 ui/issues/issue-3121.rs
-ui/issues/issue-31260.rs
 ui/issues/issue-31267-additional.rs
 ui/issues/issue-31267.rs
 ui/issues/issue-31299.rs
@@ -2608,7 +2606,6 @@ ui/issues/issue-9243.rs
 ui/issues/issue-9249.rs
 ui/issues/issue-9259.rs
 ui/issues/issue-92741.rs
-ui/issues/issue-9382.rs
 ui/issues/issue-9446.rs
 ui/issues/issue-9719.rs
 ui/issues/issue-9725.rs
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index fe51231c481..61728d0553f 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -17,7 +17,7 @@ use ignore::Walk;
 const ENTRY_LIMIT: u32 = 901;
 // FIXME: The following limits should be reduced eventually.
 
-const ISSUES_ENTRY_LIMIT: u32 = 1634;
+const ISSUES_ENTRY_LIMIT: u32 = 1631;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/tests/ui/coercion/struct-coerce-vec-to-slice.rs b/tests/ui/coercion/struct-coerce-vec-to-slice.rs
new file mode 100644
index 00000000000..9ef20ac4ea6
--- /dev/null
+++ b/tests/ui/coercion/struct-coerce-vec-to-slice.rs
@@ -0,0 +1,20 @@
+//! Regression test that ensures struct field literals can be coerced into slice and `Box` types
+
+//@ check-pass
+
+struct Thing1<'a> {
+    baz: &'a [Box<isize>],
+    bar: Box<u64>,
+}
+
+struct Thing2<'a> {
+    baz: &'a [Box<isize>],
+    bar: u64,
+}
+
+pub fn main() {
+    let _a = Thing1 { baz: &[], bar: Box::new(32) };
+    let _b = Thing1 { baz: &Vec::new(), bar: Box::new(32) };
+    let _c = Thing2 { baz: &[], bar: 32 };
+    let _d = Thing2 { baz: &Vec::new(), bar: 32 };
+}
diff --git a/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs b/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs
new file mode 100644
index 00000000000..0b8ec7dc07a
--- /dev/null
+++ b/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs
@@ -0,0 +1,16 @@
+//! Regression test to check that literal expressions in a struct field can be coerced to the
+//! expected field type, including block expressions.
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/31260>
+
+//@ check-pass
+
+pub struct Struct<K: 'static> {
+    pub field: K,
+}
+
+static STRUCT: Struct<&'static [u8]> = Struct { field: { &[1] } };
+
+static STRUCT2: Struct<&'static [u8]> = Struct { field: &[1] };
+
+fn main() {}
diff --git a/tests/ui/issues/issue-28777.rs b/tests/ui/issues/issue-28777.rs
deleted file mode 100644
index f67e11e3694..00000000000
--- a/tests/ui/issues/issue-28777.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//@ run-pass
-#![allow(unused_braces)]
-fn main() {
-    let v1 = { 1 + {2} * {3} };
-    let v2 =   1 + {2} * {3}  ;
-
-    assert_eq!(7, v1);
-    assert_eq!(7, v2);
-
-    let v3;
-    v3 = { 1 + {2} * {3} };
-    let v4;
-    v4 = 1 + {2} * {3};
-    assert_eq!(7, v3);
-    assert_eq!(7, v4);
-
-    let v5 = { 1 + {2} * 3 };
-    assert_eq!(7, v5);
-
-    let v9 = { 1 + if 1 > 2 {1} else {2} * {3} };
-    assert_eq!(7, v9);
-}
diff --git a/tests/ui/issues/issue-31260.rs b/tests/ui/issues/issue-31260.rs
deleted file mode 100644
index 5e9fffb195c..00000000000
--- a/tests/ui/issues/issue-31260.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ check-pass
-#![allow(dead_code)]
-pub struct Struct<K: 'static> {
-    pub field: K,
-}
-
-static STRUCT: Struct<&'static [u8]> = Struct {
-    field: {&[1]}
-};
-
-static STRUCT2: Struct<&'static [u8]> = Struct {
-    field: &[1]
-};
-
-fn main() {}
diff --git a/tests/ui/issues/issue-9382.rs b/tests/ui/issues/issue-9382.rs
deleted file mode 100644
index 27f9ab57743..00000000000
--- a/tests/ui/issues/issue-9382.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-
-// Tests for a previous bug that occurred due to an interaction
-// between struct field initialization and the auto-coercion
-// from a vector to a slice. The drop glue was being invoked on
-// the temporary slice with a wrong type, triggering an LLVM assert.
-
-
-struct Thing1<'a> {
-    baz: &'a [Box<isize>],
-    bar: Box<u64>,
-}
-
-struct Thing2<'a> {
-    baz: &'a [Box<isize>],
-    bar: u64,
-}
-
-pub fn main() {
-    let _t1_fixed = Thing1 {
-        baz: &[],
-        bar: Box::new(32),
-    };
-    Thing1 {
-        baz: &Vec::new(),
-        bar: Box::new(32),
-    };
-    let _t2_fixed = Thing2 {
-        baz: &[],
-        bar: 32,
-    };
-    Thing2 {
-        baz: &Vec::new(),
-        bar: 32,
-    };
-}
diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs
index 90303a1fc3d..5d4133d6c77 100644
--- a/tests/ui/lint/inert-attr-macro.rs
+++ b/tests/ui/lint/inert-attr-macro.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 
+#![feature(cfg_boolean_literals)]
 #![warn(unused)]
 
 macro_rules! foo {
@@ -17,4 +18,10 @@ fn main() {
     // This does work, since the attribute is on a parent
     // of the macro invocation.
     #[allow(warnings)] { #[inline] foo!(); }
+
+    // Ok, `cfg` and `cfg_attr` are expanded eagerly and do not warn.
+    #[cfg(true)] foo!();
+    #[cfg(false)] foo!();
+    #[cfg_attr(true, cfg(true))] foo!();
+    #[cfg_attr(false, nonexistent)] foo!();
 }
diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr
index 5ccb4ffe792..b85b0319e71 100644
--- a/tests/ui/lint/inert-attr-macro.stderr
+++ b/tests/ui/lint/inert-attr-macro.stderr
@@ -1,41 +1,41 @@
 warning: unused attribute `inline`
-  --> $DIR/inert-attr-macro.rs:10:5
+  --> $DIR/inert-attr-macro.rs:11:5
    |
 LL |     #[inline] foo!();
    |     ^^^^^^^^^
    |
 note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:10:15
+  --> $DIR/inert-attr-macro.rs:11:15
    |
 LL |     #[inline] foo!();
    |               ^^^
 note: the lint level is defined here
-  --> $DIR/inert-attr-macro.rs:3:9
+  --> $DIR/inert-attr-macro.rs:4:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
 
 warning: unused attribute `allow`
-  --> $DIR/inert-attr-macro.rs:14:5
+  --> $DIR/inert-attr-macro.rs:15:5
    |
 LL |     #[allow(warnings)] #[inline] foo!();
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:14:34
+  --> $DIR/inert-attr-macro.rs:15:34
    |
 LL |     #[allow(warnings)] #[inline] foo!();
    |                                  ^^^
 
 warning: unused attribute `inline`
-  --> $DIR/inert-attr-macro.rs:14:24
+  --> $DIR/inert-attr-macro.rs:15:24
    |
 LL |     #[allow(warnings)] #[inline] foo!();
    |                        ^^^^^^^^^
    |
 note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:14:34
+  --> $DIR/inert-attr-macro.rs:15:34
    |
 LL |     #[allow(warnings)] #[inline] foo!();
    |                                  ^^^
diff --git a/tests/ui/parser/operator-precedence-braces-exprs.rs b/tests/ui/parser/operator-precedence-braces-exprs.rs
new file mode 100644
index 00000000000..d6f44ef879c
--- /dev/null
+++ b/tests/ui/parser/operator-precedence-braces-exprs.rs
@@ -0,0 +1,28 @@
+//! Regression test for ensuring that operator precedence is correctly handled in the presence of
+//! braces
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/28777>
+
+//@ run-pass
+
+#[allow(unused_braces)]
+fn main() {
+    let v1 = { 1 + { 2 } * { 3 } };
+    let v2 = 1 + { 2 } * { 3 };
+
+    assert_eq!(7, v1);
+    assert_eq!(7, v2);
+
+    let v3;
+    v3 = { 1 + { 2 } * { 3 } };
+    let v4;
+    v4 = 1 + { 2 } * { 3 };
+    assert_eq!(7, v3);
+    assert_eq!(7, v4);
+
+    let v5 = { 1 + { 2 } * 3 };
+    assert_eq!(7, v5);
+
+    let v9 = { 1 + if 1 > 2 { 1 } else { 2 } * { 3 } };
+    assert_eq!(7, v9);
+}
diff --git a/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs
new file mode 100644
index 00000000000..b7086325d5f
--- /dev/null
+++ b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs
@@ -0,0 +1,17 @@
+// Verify that the `where` clause suggestion is in the correct place
+// Previously, the suggestion to add `where` clause was placed inside the derive
+// like `#[derive(Clone where Inner<T>: Clone)]`
+// instead of `struct Outer<T>(Inner<T>) where Inner<T>: Clone`
+
+#![crate_type = "lib"]
+
+struct Inner<T>(T);
+//~^ HELP consider annotating `Inner<T>` with `#[derive(Clone)]`
+impl Clone for Inner<()> {
+    fn clone(&self) -> Self { todo!() }
+}
+
+#[derive(Clone)]
+struct Outer<T>(Inner<T>);
+//~^ ERROR the trait bound `Inner<T>: Clone` is not satisfied [E0277]
+//~| HELP consider introducing a `where` clause
diff --git a/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr
new file mode 100644
index 00000000000..577b090ce1b
--- /dev/null
+++ b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Inner<T>: Clone` is not satisfied
+  --> $DIR/tuple-struct-where-clause-suggestion-91520.rs:15:17
+   |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+LL | struct Outer<T>(Inner<T>);
+   |                 ^^^^^^^^ the trait `Clone` is not implemented for `Inner<T>`
+   |
+help: consider annotating `Inner<T>` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct Inner<T>(T);
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | struct Outer<T>(Inner<T>) where Inner<T>: Clone;
+   |                           +++++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/triagebot.toml b/triagebot.toml
index 53cdd8b585b..7215cd84719 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -307,6 +307,23 @@ exclude_labels = [
     "T-*",
 ]
 
+trigger_labels = [
+    "D-*",
+    "A-diagnostics",
+]
+
+[autolabel."A-diagnostics"]
+
+trigger_labels = [
+    "D-*",
+]
+
+[autolabel."A-lints"]
+
+trigger_labels = [
+    "L-*",
+]
+
 [autolabel."T-libs"]
 trigger_files = [
     "library/alloc",