diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index dcd871c9d2050..03d2105e5cca5 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -12,7 +12,7 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs}; +use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs, MacCall}; use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; @@ -26,7 +26,7 @@ use rustc_parse::parser::{ AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma, }; use rustc_parse::validate_attr; -use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; +use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; use rustc_session::Limit; @@ -1070,7 +1070,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // Detect use of feature-gated or invalid attributes on macro invocations // since they will not be detected after macro expansion. - fn check_attributes(&mut self, attrs: &[ast::Attribute]) { + fn check_attributes(&mut self, attrs: &[ast::Attribute], call: &MacCall) { let features = self.cx.ecfg.features.unwrap(); let mut attrs = attrs.iter().peekable(); let mut span: Option = None; @@ -1085,14 +1085,31 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { continue; } - if attr.doc_str().is_some() { + if attr.is_doc_comment() { self.cx.sess.parse_sess.buffer_lint_with_diagnostic( &UNUSED_DOC_COMMENTS, current_span, - ast::CRATE_NODE_ID, + self.cx.current_expansion.lint_node_id, "unused doc comment", BuiltinLintDiagnostics::UnusedDocComment(attr.span), ); + } else if rustc_attr::is_builtin_attr(attr) { + 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 { + self.cx.sess.parse_sess.buffer_lint_with_diagnostic( + &UNUSED_ATTRIBUTES, + attr.span, + self.cx.current_expansion.lint_node_id, + &format!("unused attribute `{}`", attr_name), + BuiltinLintDiagnostics::UnusedBuiltinAttribute { + attr_name, + macro_name: pprust::path_to_string(&call.path), + invoc_span: call.path.span, + }, + ); + } } } } @@ -1152,7 +1169,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } if let ast::ExprKind::MacCall(mac) = expr.kind { - self.check_attributes(&expr.attrs); + self.check_attributes(&expr.attrs, &mac); self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner() } else { assign_id!(self, &mut expr.id, || { @@ -1253,7 +1270,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } if let ast::ExprKind::MacCall(mac) = expr.kind { - self.check_attributes(&expr.attrs); + self.check_attributes(&expr.attrs, &mac); self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr) .make_opt_expr() .map(|expr| expr.into_inner()) @@ -1296,7 +1313,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { if let StmtKind::MacCall(mac) = stmt.kind { let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner(); - self.check_attributes(&attrs); + self.check_attributes(&attrs, &mac); let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts(); @@ -1344,9 +1361,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let span = item.span; match item.kind { - ast::ItemKind::MacCall(..) => { + ast::ItemKind::MacCall(ref mac) => { + self.check_attributes(&attrs, &mac); item.attrs = attrs; - self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { ItemKind::MacCall(mac) => { self.collect_bang(mac, span, AstFragmentKind::Items).make_items() @@ -1455,8 +1472,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } match item.kind { - ast::AssocItemKind::MacCall(..) => { - self.check_attributes(&item.attrs); + ast::AssocItemKind::MacCall(ref mac) => { + self.check_attributes(&item.attrs, &mac); item.and_then(|item| match item.kind { ast::AssocItemKind::MacCall(mac) => self .collect_bang(mac, item.span, AstFragmentKind::TraitItems) @@ -1480,8 +1497,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } match item.kind { - ast::AssocItemKind::MacCall(..) => { - self.check_attributes(&item.attrs); + ast::AssocItemKind::MacCall(ref mac) => { + self.check_attributes(&item.attrs, &mac); item.and_then(|item| match item.kind { ast::AssocItemKind::MacCall(mac) => self .collect_bang(mac, item.span, AstFragmentKind::ImplItems) @@ -1526,8 +1543,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } match foreign_item.kind { - ast::ForeignItemKind::MacCall(..) => { - self.check_attributes(&foreign_item.attrs); + ast::ForeignItemKind::MacCall(ref mac) => { + self.check_attributes(&foreign_item.attrs, &mac); foreign_item.and_then(|item| match item.kind { ast::ForeignItemKind::MacCall(mac) => self .collect_bang(mac, item.span, AstFragmentKind::ForeignItems) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index f448acd24fc55..31ce77375e539 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -734,6 +734,16 @@ pub trait LintContext: Sized { Applicability::MachineApplicable, ); } + BuiltinLintDiagnostics::UnusedBuiltinAttribute { + attr_name, + macro_name, + invoc_span + } => { + db.span_note( + invoc_span, + &format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`") + ); + } } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c9478016140b7..1786f1e70343a 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -32,6 +32,7 @@ #![feature(box_syntax)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] +#![feature(format_args_capture)] #![feature(iter_order_by)] #![feature(iter_zip)] #![feature(never_type)] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 4190e769976e9..ec17e7a6b0373 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -296,6 +296,7 @@ pub enum BuiltinLintDiagnostics { DeprecatedMacro(Option, Span), MissingAbi(Span, Abi), UnusedDocComment(Span), + UnusedBuiltinAttribute { attr_name: Symbol, macro_name: String, invoc_span: Span }, PatternsInFnsWithoutBody(Span, Ident), LegacyDeriveHelpers(Span), ExternDepSpec(String, ExternDepSpec), diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 028104fd6b505..4936b22c7b983 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1080,7 +1080,10 @@ impl CrateError { locator.triple )); } - if missing_core && std::env::var("RUSTUP_HOME").is_ok() { + // NOTE: this suggests using rustup, even though the user may not have it installed. + // That's because they could choose to install it; or this may give them a hint which + // target they need to install from their distro. + if missing_core { err.help(&format!( "consider downloading the target with `rustup target add {}`", locator.triple @@ -1097,7 +1100,7 @@ impl CrateError { current_crate )); } - if sess.is_nightly_build() && std::env::var("CARGO").is_ok() { + if sess.is_nightly_build() { err.help("consider building the standard library from source with `cargo build -Zbuild-std`"); } } else if Some(crate_name) diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 82e19c0552720..21534290d1291 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -5,7 +5,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; -use rustc_middle::ty::{self, ParamEnv, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; use rustc_span::def_id::{DefId, LocalDefId}; @@ -27,7 +27,9 @@ struct UnsafetyVisitor<'a, 'tcx> { /// The `#[target_feature]` attributes of the body. Used for checking /// calls to functions with `#[target_feature]` (RFC 2396). body_target_features: &'tcx Vec, - in_possible_lhs_union_assign: bool, + /// When inside the LHS of an assignment to a field, this is the type + /// of the LHS and the span of the assignment expression. + assignment_info: Option<(Ty<'tcx>, Span)>, in_union_destructure: bool, param_env: ParamEnv<'tcx>, inside_adt: bool, @@ -287,7 +289,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } fn visit_expr(&mut self, expr: &Expr<'tcx>) { - // could we be in a the LHS of an assignment of a union? + // could we be in the LHS of an assignment to a field? match expr.kind { ExprKind::Field { .. } | ExprKind::VarRef { .. } @@ -329,7 +331,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } | ExprKind::LogicalOp { .. } - | ExprKind::Use { .. } => self.in_possible_lhs_union_assign = false, + | ExprKind::Use { .. } => { + // We don't need to save the old value and restore it + // because all the place expressions can't have more + // than one child. + self.assignment_info = None; + } }; match expr.kind { ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => { @@ -409,11 +416,21 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { self.safety_context = closure_visitor.safety_context; } ExprKind::Field { lhs, .. } => { - // assigning to union field is okay for AccessToUnionField - if let ty::Adt(adt_def, _) = &self.thir[lhs].ty.kind() { + let lhs = &self.thir[lhs]; + if let ty::Adt(adt_def, _) = lhs.ty.kind() { if adt_def.is_union() { - if self.in_possible_lhs_union_assign { - // FIXME: trigger AssignToDroppingUnionField unsafety if needed + if let Some((assigned_ty, assignment_span)) = self.assignment_info { + // To avoid semver hazard, we only consider `Copy` and `ManuallyDrop` non-dropping. + if !(assigned_ty + .ty_adt_def() + .map_or(false, |adt| adt.is_manually_drop()) + || assigned_ty + .is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env)) + { + self.requires_unsafe(assignment_span, AssignToDroppingUnionField); + } else { + // write to non-drop union field, safe + } } else { self.requires_unsafe(expr.span, AccessToUnionField); } @@ -421,9 +438,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } ExprKind::Assign { lhs, rhs } | ExprKind::AssignOp { lhs, rhs, .. } => { + let lhs = &self.thir[lhs]; // First, check whether we are mutating a layout constrained field let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx); - visit::walk_expr(&mut visitor, &self.thir[lhs]); + visit::walk_expr(&mut visitor, lhs); if visitor.found { self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField); } @@ -431,10 +449,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { // Second, check for accesses to union fields // don't have any special handling for AssignOp since it causes a read *and* write to lhs if matches!(expr.kind, ExprKind::Assign { .. }) { - // assigning to a union is safe, check here so it doesn't get treated as a read later - self.in_possible_lhs_union_assign = true; - visit::walk_expr(self, &self.thir()[lhs]); - self.in_possible_lhs_union_assign = false; + self.assignment_info = Some((lhs.ty, expr.span)); + visit::walk_expr(self, lhs); + self.assignment_info = None; visit::walk_expr(self, &self.thir()[rhs]); return; // we have already visited everything by now } @@ -506,12 +523,9 @@ enum UnsafeOpKind { UseOfMutableStatic, UseOfExternStatic, DerefOfRawPointer, - #[allow(dead_code)] // FIXME AssignToDroppingUnionField, AccessToUnionField, - #[allow(dead_code)] // FIXME MutationOfLayoutConstrainedField, - #[allow(dead_code)] // FIXME BorrowOfLayoutConstrainedField, CallToFunctionWith, } @@ -619,7 +633,7 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam MaybeUninit { /// With `write`, we can avoid the need to write through a raw pointer: /// /// ```rust - /// #![feature(maybe_uninit_extra)] /// use core::pin::Pin; /// use core::mem::MaybeUninit; /// diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 64f88c1aba68e..5709d97d6430f 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -294,7 +294,7 @@ impl Error for VarError { } } -/// Sets the environment variable `k` to the value `v` for the currently running +/// Sets the environment variable `key` to the value `value` for the currently running /// process. /// /// Note that while concurrent access to environment variables is safe in Rust, @@ -310,9 +310,8 @@ impl Error for VarError { /// /// # Panics /// -/// This function may panic if `key` is empty, contains an ASCII equals sign -/// `'='` or the NUL character `'\0'`, or when the value contains the NUL -/// character. +/// This function may panic if `key` is empty, contains an ASCII equals sign `'='` +/// or the NUL character `'\0'`, or when `value` contains the NUL character. /// /// # Examples /// diff --git a/src/test/ui/crate-loading/missing-std.rs b/src/test/ui/crate-loading/missing-std.rs index de4ccc185608c..1a34c21ba5413 100644 --- a/src/test/ui/crate-loading/missing-std.rs +++ b/src/test/ui/crate-loading/missing-std.rs @@ -1,7 +1,6 @@ // compile-flags: --target x86_64-unknown-uefi // needs-llvm-components: x86 // rustc-env:CARGO=/usr/bin/cargo -// rustc-env:RUSTUP_HOME=/home/bors/.rustup #![no_core] extern crate core; //~^ ERROR can't find crate for `core` diff --git a/src/test/ui/crate-loading/missing-std.stderr b/src/test/ui/crate-loading/missing-std.stderr index e61486fdc6ffd..25808efdfa699 100644 --- a/src/test/ui/crate-loading/missing-std.stderr +++ b/src/test/ui/crate-loading/missing-std.stderr @@ -1,5 +1,5 @@ error[E0463]: can't find crate for `core` - --> $DIR/missing-std.rs:6:1 + --> $DIR/missing-std.rs:5:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ can't find crate diff --git a/src/test/ui/issues/issue-37131.stderr b/src/test/ui/issues/issue-37131.stderr index 660a6935f36cb..b45574f0c49af 100644 --- a/src/test/ui/issues/issue-37131.stderr +++ b/src/test/ui/issues/issue-37131.stderr @@ -1,6 +1,8 @@ error[E0463]: can't find crate for `std` | = note: the `thumbv6m-none-eabi` target may not be installed + = help: consider downloading the target with `rustup target add thumbv6m-none-eabi` + = help: consider building the standard library from source with `cargo build -Zbuild-std` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-49851/compiler-builtins-error.stderr b/src/test/ui/issues/issue-49851/compiler-builtins-error.stderr index 7e23e0fd747fb..d963c07ea9175 100644 --- a/src/test/ui/issues/issue-49851/compiler-builtins-error.stderr +++ b/src/test/ui/issues/issue-49851/compiler-builtins-error.stderr @@ -1,6 +1,8 @@ error[E0463]: can't find crate for `core` | = note: the `thumbv7em-none-eabihf` target may not be installed + = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf` + = help: consider building the standard library from source with `cargo build -Zbuild-std` error: aborting due to previous error diff --git a/src/test/ui/lint/inert-attr-macro.rs b/src/test/ui/lint/inert-attr-macro.rs new file mode 100644 index 0000000000000..dc0bb8ac26593 --- /dev/null +++ b/src/test/ui/lint/inert-attr-macro.rs @@ -0,0 +1,20 @@ +// check-pass + +#![warn(unused)] + +macro_rules! foo { + () => {} +} + +fn main() { + #[inline] foo!(); //~ WARN unused attribute `inline` + + // This does nothing, since `#[allow(warnings)]` is itself + // an inert attribute on a macro call + #[allow(warnings)] #[inline] foo!(); //~ WARN unused attribute `allow` + //~^ WARN unused attribute `inline` + + // This does work, since the attribute is on a parent + // of the macro invocation. + #[allow(warnings)] { #[inline] foo!(); } +} diff --git a/src/test/ui/lint/inert-attr-macro.stderr b/src/test/ui/lint/inert-attr-macro.stderr new file mode 100644 index 0000000000000..3b3aa5d0bc04d --- /dev/null +++ b/src/test/ui/lint/inert-attr-macro.stderr @@ -0,0 +1,44 @@ +warning: unused attribute `inline` + --> $DIR/inert-attr-macro.rs:10:5 + | +LL | #[inline] foo!(); + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/inert-attr-macro.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]` +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 + | +LL | #[inline] foo!(); + | ^^^ + +warning: unused attribute `allow` + --> $DIR/inert-attr-macro.rs:14: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 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^ + +warning: unused attribute `inline` + --> $DIR/inert-attr-macro.rs:14: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 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^ + +warning: 3 warnings emitted + diff --git a/src/test/ui/repr/repr-no-niche.rs b/src/test/ui/repr/repr-no-niche.rs index a7f0d509af521..2e6064aeb0074 100644 --- a/src/test/ui/repr/repr-no-niche.rs +++ b/src/test/ui/repr/repr-no-niche.rs @@ -73,8 +73,7 @@ mod enum_inline { // general; this test is relying on that.) two_fifty_six_variant_enum!(Visible2, N8); - #[repr(no_niche)] - two_fifty_six_variant_enum!(Cloaked2, N8); + two_fifty_six_variant_enum!(#[repr(no_niche)] Cloaked2, N8); } mod enum_param { @@ -96,8 +95,7 @@ mod enum_param { // here as above (assuming `T` is instantiated with `NonZeroU8`). two_fifty_six_variant_enum!(Visible2); - #[repr(no_niche)] - two_fifty_six_variant_enum!(Cloaked2); + two_fifty_six_variant_enum!(#[repr(no_niche)] Cloaked2); } fn main() { @@ -157,8 +155,8 @@ fn main() { } macro two_fifty_six_variant_enum { - ($name:ident<$param:ident>) => { - #[derive(Debug)] + ($(#[$attr:meta])* $name:ident<$param:ident>) => { + #[derive(Debug)] $(#[$attr])* pub enum $name<$param> { _V00($param, u16), _V01(u16, $param), _V02($param, u16), _V03(u16, $param), _V04($param, u16), _V05(u16, $param), _V06($param, u16), _V07(u16, $param), @@ -242,8 +240,8 @@ macro two_fifty_six_variant_enum { } }, - ($name:ident, $param:ty) => { - #[derive(Debug)] + ($(#[$attr:meta])* $name:ident, $param:ty) => { + #[derive(Debug)] $(#[$attr])* pub enum $name { _V00($param, u16), _V01(u16, $param), _V02($param, u16), _V03(u16, $param), _V04($param, u16), _V05(u16, $param), _V06($param, u16), _V07(u16, $param), diff --git a/src/test/ui/union/union-unsafe.rs b/src/test/ui/union/union-unsafe.rs index e8414903d548f..3cb3a18cb7544 100644 --- a/src/test/ui/union/union-unsafe.rs +++ b/src/test/ui/union/union-unsafe.rs @@ -36,8 +36,8 @@ fn deref_union_field(mut u: URef) { fn assign_noncopy_union_field(mut u: URefCell) { // FIXME(thir-unsafeck) - u.a = (RefCell::new(0), 1); //[mir]~ ERROR assignment to union field that might need dropping - u.a.0 = RefCell::new(0); //[mir]~ ERROR assignment to union field that might need dropping + u.a = (RefCell::new(0), 1); //~ ERROR assignment to union field that might need dropping + u.a.0 = RefCell::new(0); //~ ERROR assignment to union field that might need dropping u.a.1 = 1; // OK } diff --git a/src/test/ui/union/union-unsafe.thir.stderr b/src/test/ui/union/union-unsafe.thir.stderr index 51f19879c8195..e88642b0ff7ad 100644 --- a/src/test/ui/union/union-unsafe.thir.stderr +++ b/src/test/ui/union/union-unsafe.thir.stderr @@ -6,6 +6,22 @@ LL | *(u.p) = 13; | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior +error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:39:5 + | +LL | u.a = (RefCell::new(0), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping + | + = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized + +error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:40:5 + | +LL | u.a.0 = RefCell::new(0); + | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping + | + = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized + error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/union-unsafe.rs:47:6 | @@ -70,6 +86,6 @@ LL | *u3.a = String::from("new"); | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error: aborting due to 9 previous errors +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0133`.