Skip to content

Rollup of 4 pull requests #87980

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 13, 2021
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
@@ -1136,6 +1136,11 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
};
ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
};

black_box, (c a) {
// FIXME implement black_box semantics
ret.write_cvalue(fx, a);
};
}

if let Some((_, dest)) = destination {
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
@@ -425,7 +425,7 @@ impl AsmMethods for CodegenCx<'ll, 'tcx> {
}
}

fn inline_asm_call(
pub(crate) fn inline_asm_call(
bx: &mut Builder<'a, 'll, 'tcx>,
asm: &str,
cons: &str,
26 changes: 26 additions & 0 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ use crate::type_of::LayoutLlvmExt;
use crate::va_arg::emit_va_arg;
use crate::value::Value;

use rustc_ast as ast;
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
@@ -327,6 +328,31 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
}
}

sym::black_box => {
args[0].val.store(self, result);

// We need to "use" the argument in some way LLVM can't introspect, and on
// targets that support it we can typically leverage inline assembly to do
// this. LLVM's interpretation of inline assembly is that it's, well, a black
// box. This isn't the greatest implementation since it probably deoptimizes
// more than we want, but it's so far good enough.
crate::asm::inline_asm_call(
self,
"",
"r,~{memory}",
&[result.llval],
self.type_void(),
true,
false,
ast::LlvmAsmDialect::Att,
&[span],
)
.unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`"));

// We have copied the value to `result` already.
return;
}

_ if name_str.starts_with("simd_") => {
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
Ok(llval) => llval,
15 changes: 13 additions & 2 deletions compiler/rustc_lint/src/non_fmt_panic.rs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ use crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_errors::{pluralize, Applicability};
use rustc_hir as hir;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_parse_format::{ParseMode, Parser, Piece};
use rustc_session::lint::FutureIncompatibilityReason;
@@ -75,6 +76,11 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc

let (span, panic, symbol_str) = panic_call(cx, f);

if in_external_macro(cx.sess(), span) {
// Nothing that can be done about it in the current crate.
return;
}

// Find the span of the argument to `panic!()`, before expansion in the
// case of `panic!(some_macro!())`.
// We don't use source_callsite(), because this `panic!(..)` might itself
@@ -152,6 +158,13 @@ fn check_panic_str<'tcx>(
return;
}

let (span, _, _) = panic_call(cx, f);

if in_external_macro(cx.sess(), span) && in_external_macro(cx.sess(), arg.span) {
// Nothing that can be done about it in the current crate.
return;
}

let fmt_span = arg.span.source_callsite();

let (snippet, style) = match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
@@ -167,8 +180,6 @@ fn check_panic_str<'tcx>(
Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
let n_arguments = (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();

let (span, _, _) = panic_call(cx, f);

if n_arguments > 0 && fmt_parser.errors.is_empty() {
let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
[] => vec![fmt_span],
24 changes: 8 additions & 16 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
@@ -112,9 +112,6 @@ impl IntegerExt for Integer {
let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128));
let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));

let mut min_from_extern = None;
let min_default = I8;

if let Some(ity) = repr.int {
let discr = Integer::from_attr(&tcx, ity);
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
@@ -128,19 +125,14 @@ impl IntegerExt for Integer {
return (discr, ity.is_signed());
}

if repr.c() {
match &tcx.sess.target.arch[..] {
"hexagon" => min_from_extern = Some(I8),
// WARNING: the ARM EABI has two variants; the one corresponding
// to `at_least == I32` appears to be used on Linux and NetBSD,
// but some systems may use the variant corresponding to no
// lower bound. However, we don't run on those yet...?
"arm" => min_from_extern = Some(I32),
_ => min_from_extern = Some(I32),
}
}

let at_least = min_from_extern.unwrap_or(min_default);
let at_least = if repr.c() {
// This is usually I32, however it can be different on some platforms,
// notably hexagon and arm-none/thumb-none
tcx.data_layout().c_enum_min_size
} else {
// repr(Rust) enums try to be as small as possible
I8
};

// If there are no negative values, we can use the unsigned fit.
if min >= 0 {
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -465,7 +465,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
);
self.copy_op(&self.operand_index(&args[0], index)?, dest)?;
}
sym::likely | sym::unlikely => {
sym::likely | sym::unlikely | sym::black_box => {
// These just return their argument
self.copy_op(&args[0], dest)?;
}
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -335,6 +335,7 @@ symbols! {
bitreverse,
bitxor,
bitxor_assign,
black_box,
block,
bool,
borrowck_graphviz_format,
17 changes: 17 additions & 0 deletions compiler/rustc_target/src/abi/mod.rs
Original file line number Diff line number Diff line change
@@ -36,6 +36,9 @@ pub struct TargetDataLayout {
pub vector_align: Vec<(Size, AbiAndPrefAlign)>,

pub instruction_address_space: AddressSpace,

/// Minimum size of #[repr(C)] enums (default I32 bits)
pub c_enum_min_size: Integer,
}

impl Default for TargetDataLayout {
@@ -60,6 +63,7 @@ impl Default for TargetDataLayout {
(Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
],
instruction_address_space: AddressSpace::DATA,
c_enum_min_size: Integer::I32,
}
}
}
@@ -173,6 +177,8 @@ impl TargetDataLayout {
));
}

dl.c_enum_min_size = Integer::from_size(Size::from_bits(target.c_enum_min_bits))?;

Ok(dl)
}

@@ -610,6 +616,17 @@ impl Integer {
}
I8
}

fn from_size(size: Size) -> Result<Self, String> {
match size.bits() {
8 => Ok(Integer::I8),
16 => Ok(Integer::I16),
32 => Ok(Integer::I32),
64 => Ok(Integer::I64),
128 => Ok(Integer::I128),
_ => Err(format!("rust does not support integers with {} bits", size.bits())),
}
}
}

/// Fundamental unit of memory access and layout.
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@ pub fn target() -> Target {
panic_strategy: PanicStrategy::Abort,
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
c_enum_min_bits: 8,
..Default::default()
},
}
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
Original file line number Diff line number Diff line change
@@ -21,6 +21,8 @@ pub fn target() -> Target {
features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
c_enum_min_bits: 8,
..Default::default()
},
}
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/armv7a_none_eabi.rs
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ pub fn target() -> Target {
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
emit_debug_gdb_scripts: false,
c_enum_min_bits: 8,
..Default::default()
};
Target {
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
Original file line number Diff line number Diff line change
@@ -19,6 +19,8 @@ pub fn target() -> Target {
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
c_enum_min_bits: 8,
..Default::default()
};
Target {
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/armv7r_none_eabi.rs
Original file line number Diff line number Diff line change
@@ -19,6 +19,8 @@ pub fn target() -> Target {
panic_strategy: PanicStrategy::Abort,
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
c_enum_min_bits: 8,
..Default::default()
},
}
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@ pub fn target() -> Target {
features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
c_enum_min_bits: 8,
..Default::default()
},
}
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,8 @@ pub fn target() -> Target {
base.dynamic_linking = true;
base.executables = true;

base.c_enum_min_bits = 8;

Target {
llvm_target: "hexagon-unknown-linux-musl".to_string(),
pointer_width: 32,
12 changes: 12 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
@@ -1336,6 +1336,9 @@ pub struct TargetOptions {

/// If present it's a default value to use for adjusting the C ABI.
pub default_adjusted_cabi: Option<Abi>,

/// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
pub c_enum_min_bits: u64,
}

impl Default for TargetOptions {
@@ -1440,6 +1443,7 @@ impl Default for TargetOptions {
split_debuginfo: SplitDebuginfo::Off,
supported_sanitizers: SanitizerSet::empty(),
default_adjusted_cabi: None,
c_enum_min_bits: 32,
}
}
}
@@ -1604,6 +1608,12 @@ impl Target {
base.$key_name = s;
}
} );
($key_name:ident, u64) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
base.$key_name = s;
}
} );
($key_name:ident, Option<u32>) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
@@ -2017,6 +2027,7 @@ impl Target {
key!(split_debuginfo, SplitDebuginfo)?;
key!(supported_sanitizers, SanitizerSet)?;
key!(default_adjusted_cabi, Option<Abi>)?;
key!(c_enum_min_bits, u64);

if base.is_builtin {
// This can cause unfortunate ICEs later down the line.
@@ -2255,6 +2266,7 @@ impl ToJson for Target {
target_option_val!(has_thumb_interworking);
target_option_val!(split_debuginfo);
target_option_val!(supported_sanitizers);
target_option_val!(c_enum_min_bits);

if let Some(abi) = self.default_adjusted_cabi {
d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json());
3 changes: 3 additions & 0 deletions compiler/rustc_target/src/spec/thumb_base.rs
Original file line number Diff line number Diff line change
@@ -53,6 +53,9 @@ pub fn opts() -> TargetOptions {
// LLVM is eager to trash the link register when calling `noreturn` functions, which
// breaks debugging. Preserve LR by default to prevent that from happening.
frame_pointer: FramePointer::Always,
// ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
// but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
c_enum_min_bits: 8,
..Default::default()
}
}
3 changes: 3 additions & 0 deletions compiler/rustc_typeck/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -102,6 +102,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
| sym::maxnumf64
| sym::type_name
| sym::forget
| sym::black_box
| sym::variant_count => hir::Unsafety::Normal,
_ => hir::Unsafety::Unsafe,
}
@@ -387,6 +388,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
(1, vec![param_ty; 2], tcx.types.bool)
}

sym::black_box => (1, vec![param(0)], param(0)),

other => {
tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
return;
13 changes: 11 additions & 2 deletions compiler/rustc_typeck/src/check/upvar.rs
Original file line number Diff line number Diff line change
@@ -649,11 +649,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
Ok(s) => {
let trimmed = s.trim_start();
let mut lines = trimmed.lines();
let line1 = lines.next().unwrap_or_default();

// If the closure contains a block then replace the opening brace
// with "{ let _ = (..); "
let sugg = if let Some('{') = trimmed.chars().next() {
format!("{{ {}; {}", migration_string, &trimmed[1..])
let sugg = if line1.trim_end() == "{" {
// This is a multi-line closure with just a `{` on the first line,
// so we put the `let` on its own line.
// We take the indentation from the next non-empty line.
let line2 = lines.filter(|line| !line.is_empty()).next().unwrap_or_default();
let indent = line2.split_once(|c: char| !c.is_whitespace()).unwrap_or_default().0;
format!("{{\n{}{};{}", indent, migration_string, &trimmed[line1.len()..])
} else if line1.starts_with('{') {
format!("{{ {}; {}", migration_string, &trimmed[1..].trim_start())
} else {
format!("{{ {}; {} }}", migration_string, s)
};
20 changes: 8 additions & 12 deletions library/core/src/hint.rs
Original file line number Diff line number Diff line change
@@ -152,23 +152,19 @@ pub fn spin_loop() {
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
///
/// [`std::convert::identity`]: crate::convert::identity
#[cfg_attr(not(miri), inline)]
#[cfg_attr(miri, inline(never))]
#[inline]
#[unstable(feature = "bench_black_box", issue = "64102")]
#[cfg_attr(miri, allow(unused_mut))]
#[cfg_attr(not(bootstrap), allow(unused_mut))]
pub fn black_box<T>(mut dummy: T) -> T {
// We need to "use" the argument in some way LLVM can't introspect, and on
// targets that support it we can typically leverage inline assembly to do
// this. LLVM's interpretation of inline assembly is that it's, well, a black
// box. This isn't the greatest implementation since it probably deoptimizes
// more than we want, but it's so far good enough.

#[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
#[cfg(bootstrap)]
// SAFETY: the inline assembly is a no-op.
unsafe {
// FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
dummy
}

dummy
#[cfg(not(bootstrap))]
{
crate::intrinsics::black_box(dummy)
}
}
6 changes: 6 additions & 0 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1933,6 +1933,12 @@ extern "rust-intrinsic" {
/// which is UB if any of their inputs are `undef`.)
#[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")]
pub fn raw_eq<T>(a: &T, b: &T) -> bool;

/// See documentation of [`std::hint::black_box`] for details.
///
/// [`std::hint::black_box`]: crate::hint::black_box
#[cfg(not(bootstrap))]
pub fn black_box<T>(dummy: T) -> T;
}

// Some functions are defined here because they accidentally got made
3 changes: 3 additions & 0 deletions src/test/ui/auxiliary/fancy-panic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#[macro_export]
macro_rules! fancy_panic {
() => {
panic!("{}");
};
($msg:expr) => {
panic!($msg)
};
Original file line number Diff line number Diff line change
@@ -55,7 +55,8 @@ impl Clone for U {

fn test_clone_trait() {
let f = U(S(String::from("Hello World")), T(0));
let c = || { let _ = &f;
let c = || {
let _ = &f;
//~^ ERROR: `Clone` trait implementation for closure and drop order
//~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
//~| NOTE: for more information, see
Original file line number Diff line number Diff line change
@@ -58,12 +58,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f` to be fully captured
|
LL ~ let c = || { let _ = &f;
LL ~ let c = || {
LL + let _ = &f;
LL +
LL +
LL +
LL +
LL + let f_1 = f.1;
...

error: aborting due to 3 previous errors
Original file line number Diff line number Diff line change
@@ -12,7 +12,8 @@ fn test1_all_need_migration() {
let t1 = (String::new(), String::new());
let t2 = (String::new(), String::new());

let c = || { let _ = (&t, &t1, &t2);
let c = || {
let _ = (&t, &t1, &t2);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
@@ -38,7 +39,8 @@ fn test2_only_precise_paths_need_migration() {
let t1 = (String::new(), String::new());
let t2 = (String::new(), String::new());

let c = || { let _ = (&t, &t1);
let c = || {
let _ = (&t, &t1);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
@@ -59,7 +61,8 @@ fn test2_only_precise_paths_need_migration() {
fn test3_only_by_value_need_migration() {
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -80,7 +83,8 @@ fn test4_only_non_copy_types_need_migration() {
// `t1` is Copy because all of its elements are Copy
let t1 = (0i32, 0i32);

let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -101,7 +105,8 @@ fn test5_only_drop_types_need_migration() {
// `s` doesn't implement Drop or any elements within it, and doesn't need migration
let s = S(0i32, 0i32);

let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -119,7 +124,8 @@ fn test5_only_drop_types_need_migration() {
fn test6_move_closures_non_copy_types_might_need_migration() {
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
let c = move || { let _ = (&t1, &t);
let c = move || {
let _ = (&t1, &t);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
@@ -139,7 +145,8 @@ fn test6_move_closures_non_copy_types_might_need_migration() {
fn test7_drop_non_drop_aggregate_need_migration() {
let t = (String::new(), String::new(), 0i32);

let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
Original file line number Diff line number Diff line change
@@ -28,12 +28,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
LL ~ let c = || { let _ = (&t, &t1, &t2);
LL ~ let c = || {
LL + let _ = (&t, &t1, &t2);
LL +
LL +
LL +
LL +
LL + let _t = t.0;
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -57,12 +57,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1` to be fully captured
|
LL ~ let c = || { let _ = (&t, &t1);
LL ~ let c = || {
LL + let _ = (&t, &t1);
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -80,12 +80,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -103,12 +103,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -126,12 +126,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -154,12 +154,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t1`, `t` to be fully captured
|
LL ~ let c = move || { let _ = (&t1, &t);
LL ~ let c = move || {
LL + let _ = (&t1, &t);
LL +
LL +
LL +
LL + println!("{} {}", t1.1, t.1);
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -177,12 +177,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: aborting due to 7 previous errors
Original file line number Diff line number Diff line change
@@ -34,7 +34,8 @@ impl<T> Drop for GenericStruct<T> {
fn significant_drop_needs_migration() {
let t = (SigDrop {}, SigDrop {});

let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -54,7 +55,8 @@ fn generic_struct_with_significant_drop_needs_migration() {
let t = Wrapper(GenericStruct(SigDrop {}, SigDrop {}), 5);

// move is used to force i32 to be copied instead of being a ref
let c = move || { let _ = &t;
let c = move || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
Original file line number Diff line number Diff line change
@@ -18,12 +18,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -41,12 +41,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = move || { let _ = &t;
LL ~ let c = move || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.1;
LL +
...

error: aborting due to 2 previous errors
Original file line number Diff line number Diff line change
@@ -16,7 +16,8 @@ impl Drop for Foo {

fn closure_contains_block() {
let t = (Foo(0), Foo(0));
let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
Original file line number Diff line number Diff line change
@@ -18,12 +18,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
Original file line number Diff line number Diff line change
@@ -17,7 +17,8 @@ where
F: FnOnce(),
{
let f = panic::AssertUnwindSafe(f);
let result = panic::catch_unwind(move || { let _ = &f;
let result = panic::catch_unwind(move || {
let _ = &f;
//~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
//~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
//~| NOTE: for more information, see
Original file line number Diff line number Diff line change
@@ -15,12 +15,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f` to be fully captured
|
LL ~ let result = panic::catch_unwind(move || { let _ = &f;
LL ~ let result = panic::catch_unwind(move || {
LL + let _ = &f;
LL +
LL +
LL +
LL +
LL + f.0()
...

error: aborting due to previous error
Original file line number Diff line number Diff line change
@@ -20,7 +20,8 @@ impl Clone for U {
fn test_multi_issues() {
let f1 = U(S(String::from("foo")), T(0));
let f2 = U(S(String::from("bar")), T(0));
let c = || { let _ = (&f1, &f2);
let c = || {
let _ = (&f1, &f2);
//~^ ERROR: `Clone` trait implementation for closure and drop order
//~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
@@ -39,7 +40,8 @@ fn test_multi_issues() {

fn test_capturing_all_disjoint_fields_individually() {
let f1 = U(S(String::from("foo")), T(0));
let c = || { let _ = &f1;
let c = || {
let _ = &f1;
//~^ ERROR: `Clone` trait implementation for closure
//~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
@@ -64,7 +66,8 @@ impl Clone for U1 {

fn test_capturing_several_disjoint_fields_individually_1() {
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
let c = || { let _ = &f1;
let c = || {
let _ = &f1;
//~^ ERROR: `Clone` trait implementation for closure
//~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
@@ -83,7 +86,8 @@ fn test_capturing_several_disjoint_fields_individually_1() {

fn test_capturing_several_disjoint_fields_individually_2() {
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
let c = || { let _ = &f1;
let c = || {
let _ = &f1;
//~^ ERROR: `Clone` trait implementation for closure and drop order
//~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
Original file line number Diff line number Diff line change
@@ -21,12 +21,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1`, `f2` to be fully captured
|
LL ~ let c = || { let _ = (&f1, &f2);
LL ~ let c = || {
LL + let _ = (&f1, &f2);
LL +
LL +
LL +
LL +
LL + let _f_1 = f1.0;
...

error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
@@ -41,12 +41,12 @@ LL | let _f_1 = f1.0;
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1` to be fully captured
|
LL ~ let c = || { let _ = &f1;
LL ~ let c = || {
LL + let _ = &f1;
LL +
LL +
LL +
LL +
LL + let _f_1 = f1.0;
...

error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
@@ -67,8 +67,8 @@ LL | let _f_2 = f1.2;
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1` to be fully captured
|
LL ~ let c = || { let _ = &f1;
LL +
LL ~ let c = || {
LL + let _ = &f1;
LL +
LL +
LL +
@@ -96,12 +96,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1` to be fully captured
|
LL ~ let c = || { let _ = &f1;
LL ~ let c = || {
LL + let _ = &f1;
LL +
LL +
LL +
LL +
LL + let _f_0 = f1.0;
...

error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
Original file line number Diff line number Diff line change
@@ -17,7 +17,8 @@ struct ConstainsDropField(Foo, Foo);
fn test_precise_analysis_drop_paths_not_captured_by_move() {
let t = ConstainsDropField(Foo(10), Foo(20));

let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -42,7 +43,8 @@ struct U(T, T);
fn test_precise_analysis_long_path_missing() {
let u = U(T(S, S), T(S, S));

let c = || { let _ = &u;
let c = || {
let _ = &u;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `u` to be fully captured
Original file line number Diff line number Diff line change
@@ -18,12 +18,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -51,12 +51,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `u` to be fully captured
|
LL ~ let c = || { let _ = &u;
LL ~ let c = || {
LL + let _ = &u;
LL +
LL +
LL +
LL + let _x = u.0.0;
LL +
...

error: aborting due to 2 previous errors
Original file line number Diff line number Diff line change
@@ -22,7 +22,8 @@ fn test1_all_need_migration() {
let t1 = (Foo(0), Foo(0));
let t2 = (Foo(0), Foo(0));

let c = || { let _ = (&t, &t1, &t2);
let c = || {
let _ = (&t, &t1, &t2);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
@@ -47,7 +48,8 @@ fn test2_only_precise_paths_need_migration() {
let t1 = (Foo(0), Foo(0));
let t2 = (Foo(0), Foo(0));

let c = || { let _ = (&t, &t1);
let c = || {
let _ = (&t, &t1);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
@@ -68,7 +70,8 @@ fn test2_only_precise_paths_need_migration() {
fn test3_only_by_value_need_migration() {
let t = (Foo(0), Foo(0));
let t1 = (Foo(0), Foo(0));
let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -88,7 +91,8 @@ fn test3_only_by_value_need_migration() {
fn test4_type_contains_drop_need_migration() {
let t = ConstainsDropField(Foo(0), Foo(0));

let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -106,7 +110,8 @@ fn test4_type_contains_drop_need_migration() {
fn test5_drop_non_drop_aggregate_need_migration() {
let t = (Foo(0), Foo(0), 0i32);

let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -122,7 +127,8 @@ fn test5_drop_non_drop_aggregate_need_migration() {
fn test6_significant_insignificant_drop_aggregate_need_migration() {
let t = (Foo(0), String::new());

let c = || { let _ = &t;
let c = || {
let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -140,7 +146,8 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
let t = (Foo(0), Foo(0));
let t1 = (Foo(0), Foo(0), Foo(0));

let c = move || { let _ = (&t1, &t);
let c = move || {
let _ = (&t1, &t);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
@@ -160,7 +167,8 @@ fn test8_drop_order_and_blocks() {
let tuple =
(String::from("foo"), String::from("bar"));
{
let c = || { let _ = &tuple;
let c = || {
let _ = &tuple;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `tuple` to be fully captured
@@ -178,7 +186,8 @@ fn test9_drop_order_and_nested_closures() {
let tuple =
(String::from("foo"), String::from("bar"));
let b = || {
let c = || { let _ = &tuple;
let c = || {
let _ = &tuple;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `tuple` to be fully captured
Original file line number Diff line number Diff line change
@@ -28,12 +28,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
LL ~ let c = || { let _ = (&t, &t1, &t2);
LL ~ let c = || {
LL + let _ = (&t, &t1, &t2);
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -57,12 +57,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1` to be fully captured
|
LL ~ let c = || { let _ = (&t, &t1);
LL ~ let c = || {
LL + let _ = (&t, &t1);
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -80,12 +80,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -103,12 +103,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -126,12 +126,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -149,12 +149,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || { let _ = &t;
LL ~ let c = || {
LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.1;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -177,12 +177,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t1`, `t` to be fully captured
|
LL ~ let c = move || { let _ = (&t1, &t);
LL ~ let c = move || {
LL + let _ = (&t1, &t);
LL +
LL +
LL +
LL + println!("{:?} {:?}", t1.1, t.1);
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -200,12 +200,12 @@ LL | }
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `tuple` to be fully captured
|
LL ~ let c = || { let _ = &tuple;
LL ~ let c = || {
LL + let _ = &tuple;
LL +
LL +
LL +
LL + tuple.0;
LL +
...

error: changes to closure capture in Rust 2021 will affect drop order
@@ -223,12 +223,12 @@ LL | };
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `tuple` to be fully captured
|
LL ~ let c = || { let _ = &tuple;
LL ~ let c = || {
LL + let _ = &tuple;
LL +
LL +
LL +
LL + tuple.0;
LL +
...

error: aborting due to 9 previous errors
34 changes: 34 additions & 0 deletions src/test/ui/layout/thumb-enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// compile-flags: --target thumbv8m.main-none-eabihf
// needs-llvm-components: arm
//
// Verify that thumb targets implement the repr(C) for enums correctly.
//
// See #87917
#![feature(never_type, rustc_attrs, no_core, lang_items)]
#![crate_type = "lib"]
#![no_core]

#[lang="sized"]
trait Sized {}

#[rustc_layout(debug)]
#[repr(C)]
enum A { Apple } //~ ERROR: layout_of

#[rustc_layout(debug)]
#[repr(C)]
enum B { Banana = 255, } //~ ERROR: layout_of

#[rustc_layout(debug)]
#[repr(C)]
enum C { Chaenomeles = 256, } //~ ERROR: layout_of

#[rustc_layout(debug)]
#[repr(C)]
enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of

const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator!

#[rustc_layout(debug)]
#[repr(C)]
enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of
442 changes: 442 additions & 0 deletions src/test/ui/layout/thumb-enum.stderr

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/test/ui/non-fmt-panic.rs
Original file line number Diff line number Diff line change
@@ -26,8 +26,8 @@ fn main() {
fancy_panic::fancy_panic!("test {} 123");
//~^ WARN panic message contains an unused formatting placeholder

fancy_panic::fancy_panic!(S);
//~^ WARN panic message is not a string literal
fancy_panic::fancy_panic!(); // OK
fancy_panic::fancy_panic!(S); // OK

macro_rules! a {
() => { 123 };
11 changes: 1 addition & 10 deletions src/test/ui/non-fmt-panic.stderr
Original file line number Diff line number Diff line change
@@ -180,15 +180,6 @@ LL | fancy_panic::fancy_panic!("test {} 123");
|
= note: this message is not used as a format string when given without arguments, but will be in Rust 2021

warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:29:31
|
LL | fancy_panic::fancy_panic!(S);
| ^
|
= note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>

warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:36:12
|
@@ -285,5 +276,5 @@ help: or use std::panic::panic_any instead
LL | std::panic::panic_any(123);
| ~~~~~~~~~~~~~~~~~~~~~~ ~

warning: 20 warnings emitted
warning: 19 warnings emitted

2 changes: 1 addition & 1 deletion src/test/ui/sanitize/memory.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
// run-fail
// error-pattern: MemorySanitizer: use-of-uninitialized-value
// error-pattern: Uninitialized value was created by an allocation
// error-pattern: in the stack frame of function 'random'
// error-pattern: in the stack frame of function 'main'
//
// This test case intentionally limits the usage of the std,
// since it will be linked with an uninstrumented version of it.