Auto merge of #138831 - matthiaskrgr:rollup-3t0dqiz, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #138609 (Add stack overflow handler for cygwin) - #138639 (Clean UI tests 2 of n) - #138773 (catch_unwind intrinsic: document return value) - #138782 (test(ui): add tuple-struct-where-clause-suggestion ui test for #91520) - #138794 (expand: Do not report `cfg_attr` traces on macros as unused attributes) - #138801 (triagebot: add autolabel rules for D-* and L-*) - #138804 (Allow inlining for `Atomic*::from_ptr`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
b48576b4db
17 changed files with 226 additions and 86 deletions
|
@ -1941,7 +1941,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
let attr_name = attr.ident().unwrap().name;
|
let attr_name = attr.ident().unwrap().name;
|
||||||
// `#[cfg]` and `#[cfg_attr]` are special - they are
|
// `#[cfg]` and `#[cfg_attr]` are special - they are
|
||||||
// eagerly evaluated.
|
// 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(
|
self.cx.sess.psess.buffer_lint(
|
||||||
UNUSED_ATTRIBUTES,
|
UNUSED_ATTRIBUTES,
|
||||||
attr.span,
|
attr.span,
|
||||||
|
|
|
@ -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
|
/// 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.
|
/// 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.
|
/// `catch_fn` must not unwind.
|
||||||
///
|
///
|
||||||
|
|
|
@ -469,6 +469,7 @@ impl AtomicBool {
|
||||||
///
|
///
|
||||||
/// [valid]: crate::ptr#safety
|
/// [valid]: crate::ptr#safety
|
||||||
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
|
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
|
||||||
|
#[inline]
|
||||||
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
|
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
|
||||||
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.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 {
|
pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
|
||||||
|
@ -1389,6 +1390,7 @@ impl<T> AtomicPtr<T> {
|
||||||
///
|
///
|
||||||
/// [valid]: crate::ptr#safety
|
/// [valid]: crate::ptr#safety
|
||||||
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
|
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
|
||||||
|
#[inline]
|
||||||
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
|
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
|
||||||
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.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> {
|
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
|
/// [valid]: crate::ptr#safety
|
||||||
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
|
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
|
||||||
|
#[inline]
|
||||||
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
|
#[stable(feature = "atomic_from_ptr", since = "1.75.0")]
|
||||||
#[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.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 {
|
pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
|
||||||
|
|
|
@ -585,6 +585,7 @@ mod imp {
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
target_os = "solaris",
|
target_os = "solaris",
|
||||||
target_os = "illumos",
|
target_os = "illumos",
|
||||||
|
target_os = "cygwin",
|
||||||
)))]
|
)))]
|
||||||
mod imp {
|
mod imp {
|
||||||
pub unsafe fn init() {}
|
pub unsafe fn init() {}
|
||||||
|
@ -597,3 +598,89 @@ mod imp {
|
||||||
|
|
||||||
pub unsafe fn drop_handler(_data: *mut libc::c_void) {}
|
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) {}
|
||||||
|
}
|
||||||
|
|
|
@ -2000,7 +2000,6 @@ ui/issues/issue-28586.rs
|
||||||
ui/issues/issue-28600.rs
|
ui/issues/issue-28600.rs
|
||||||
ui/issues/issue-28625.rs
|
ui/issues/issue-28625.rs
|
||||||
ui/issues/issue-28776.rs
|
ui/issues/issue-28776.rs
|
||||||
ui/issues/issue-28777.rs
|
|
||||||
ui/issues/issue-28828.rs
|
ui/issues/issue-28828.rs
|
||||||
ui/issues/issue-28839.rs
|
ui/issues/issue-28839.rs
|
||||||
ui/issues/issue-28936.rs
|
ui/issues/issue-28936.rs
|
||||||
|
@ -2063,7 +2062,6 @@ ui/issues/issue-3091.rs
|
||||||
ui/issues/issue-31011.rs
|
ui/issues/issue-31011.rs
|
||||||
ui/issues/issue-3109.rs
|
ui/issues/issue-3109.rs
|
||||||
ui/issues/issue-3121.rs
|
ui/issues/issue-3121.rs
|
||||||
ui/issues/issue-31260.rs
|
|
||||||
ui/issues/issue-31267-additional.rs
|
ui/issues/issue-31267-additional.rs
|
||||||
ui/issues/issue-31267.rs
|
ui/issues/issue-31267.rs
|
||||||
ui/issues/issue-31299.rs
|
ui/issues/issue-31299.rs
|
||||||
|
@ -2608,7 +2606,6 @@ ui/issues/issue-9243.rs
|
||||||
ui/issues/issue-9249.rs
|
ui/issues/issue-9249.rs
|
||||||
ui/issues/issue-9259.rs
|
ui/issues/issue-9259.rs
|
||||||
ui/issues/issue-92741.rs
|
ui/issues/issue-92741.rs
|
||||||
ui/issues/issue-9382.rs
|
|
||||||
ui/issues/issue-9446.rs
|
ui/issues/issue-9446.rs
|
||||||
ui/issues/issue-9719.rs
|
ui/issues/issue-9719.rs
|
||||||
ui/issues/issue-9725.rs
|
ui/issues/issue-9725.rs
|
||||||
|
|
|
@ -17,7 +17,7 @@ use ignore::Walk;
|
||||||
const ENTRY_LIMIT: u32 = 901;
|
const ENTRY_LIMIT: u32 = 901;
|
||||||
// FIXME: The following limits should be reduced eventually.
|
// 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] = &[
|
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||||
"rs", // test source files
|
"rs", // test source files
|
||||||
|
|
20
tests/ui/coercion/struct-coerce-vec-to-slice.rs
Normal file
20
tests/ui/coercion/struct-coerce-vec-to-slice.rs
Normal file
|
@ -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 };
|
||||||
|
}
|
|
@ -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() {}
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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() {}
|
|
|
@ -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,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(cfg_boolean_literals)]
|
||||||
#![warn(unused)]
|
#![warn(unused)]
|
||||||
|
|
||||||
macro_rules! foo {
|
macro_rules! foo {
|
||||||
|
@ -17,4 +18,10 @@ fn main() {
|
||||||
// This does work, since the attribute is on a parent
|
// This does work, since the attribute is on a parent
|
||||||
// of the macro invocation.
|
// of the macro invocation.
|
||||||
#[allow(warnings)] { #[inline] foo!(); }
|
#[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!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
warning: unused attribute `inline`
|
warning: unused attribute `inline`
|
||||||
--> $DIR/inert-attr-macro.rs:10:5
|
--> $DIR/inert-attr-macro.rs:11:5
|
||||||
|
|
|
|
||||||
LL | #[inline] foo!();
|
LL | #[inline] foo!();
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `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!();
|
LL | #[inline] foo!();
|
||||||
| ^^^
|
| ^^^
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/inert-attr-macro.rs:3:9
|
--> $DIR/inert-attr-macro.rs:4:9
|
||||||
|
|
|
|
||||||
LL | #![warn(unused)]
|
LL | #![warn(unused)]
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
= note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
|
= note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
|
||||||
|
|
||||||
warning: unused attribute `allow`
|
warning: unused attribute `allow`
|
||||||
--> $DIR/inert-attr-macro.rs:14:5
|
--> $DIR/inert-attr-macro.rs:15:5
|
||||||
|
|
|
|
||||||
LL | #[allow(warnings)] #[inline] foo!();
|
LL | #[allow(warnings)] #[inline] foo!();
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `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!();
|
LL | #[allow(warnings)] #[inline] foo!();
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
warning: unused attribute `inline`
|
warning: unused attribute `inline`
|
||||||
--> $DIR/inert-attr-macro.rs:14:24
|
--> $DIR/inert-attr-macro.rs:15:24
|
||||||
|
|
|
|
||||||
LL | #[allow(warnings)] #[inline] foo!();
|
LL | #[allow(warnings)] #[inline] foo!();
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `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!();
|
LL | #[allow(warnings)] #[inline] foo!();
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
28
tests/ui/parser/operator-precedence-braces-exprs.rs
Normal file
28
tests/ui/parser/operator-precedence-braces-exprs.rs
Normal file
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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`.
|
|
@ -307,6 +307,23 @@ exclude_labels = [
|
||||||
"T-*",
|
"T-*",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
trigger_labels = [
|
||||||
|
"D-*",
|
||||||
|
"A-diagnostics",
|
||||||
|
]
|
||||||
|
|
||||||
|
[autolabel."A-diagnostics"]
|
||||||
|
|
||||||
|
trigger_labels = [
|
||||||
|
"D-*",
|
||||||
|
]
|
||||||
|
|
||||||
|
[autolabel."A-lints"]
|
||||||
|
|
||||||
|
trigger_labels = [
|
||||||
|
"L-*",
|
||||||
|
]
|
||||||
|
|
||||||
[autolabel."T-libs"]
|
[autolabel."T-libs"]
|
||||||
trigger_files = [
|
trigger_files = [
|
||||||
"library/alloc",
|
"library/alloc",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue