From 763bc13ccce4b81ec623d4e8c0a34f77d0401f0f Mon Sep 17 00:00:00 2001 From: Piotr Kubaj Date: Thu, 22 Jul 2021 17:29:33 +0200 Subject: [PATCH 01/10] Add support for powerpc-unknown-freebsd --- compiler/rustc_target/src/spec/mod.rs | 1 + .../src/spec/powerpc_unknown_freebsd.rs | 27 +++++++++++++++++++ src/bootstrap/native.rs | 9 +++++++ src/doc/rustc/src/platform-support.md | 1 + 4 files changed, 38 insertions(+) create mode 100644 compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0185132ee36..ad84e07edfb 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -802,6 +802,7 @@ supported_targets! { ("armv6-unknown-freebsd", armv6_unknown_freebsd), ("armv7-unknown-freebsd", armv7_unknown_freebsd), ("i686-unknown-freebsd", i686_unknown_freebsd), + ("powerpc-unknown-freebsd", powerpc_unknown_freebsd), ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd), ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd), ("x86_64-unknown-freebsd", x86_64_unknown_freebsd), diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs new file mode 100644 index 00000000000..e11318027d5 --- /dev/null +++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs @@ -0,0 +1,27 @@ +use crate::abi::Endian; +use crate::spec::{LinkerFlavor, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + let mut base = super::freebsd_base::opts(); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string()); + // Extra hint to linker that we are generating secure-PLT code. + base.pre_link_args + .entry(LinkerFlavor::Gcc) + .or_default() + .push("--target=powerpc-unknown-freebsd13.0".to_string()); + base.max_atomic_width = Some(32); + + Target { + llvm_target: "powerpc-unknown-freebsd13.0".to_string(), + pointer_width: 32, + data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), + arch: "powerpc".to_string(), + options: TargetOptions { + endian: Endian::Big, + features: "+secure-plt".to_string(), + relocation_model: RelocModel::Pic, + mcount: "_mcount".to_string(), + ..base + }, + } +} diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 1be414b29a1..b8a1513f2a6 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -118,6 +118,10 @@ impl Step for Llvm { let idx = target.triple.find('-').unwrap(); format!("riscv{}{}", &target.triple[5..7], &target.triple[idx..]) + } else if self.target.starts_with("powerpc") && self.target.ends_with("freebsd") { + // FreeBSD 13 had incompatible ABI changes on all PowerPC platforms. + // Set the version suffix to 13.0 so the correct target details are used. + format!("{}{}", self.target, "13.0") } else { target.to_string() }; @@ -277,6 +281,11 @@ impl Step for Llvm { } } + // Workaround for ppc32 lld limitation + if target == "powerpc-unknown-freebsd" { + cfg.define("CMAKE_EXE_LINKER_FLAGS", "-fuse-ld=bfd"); + } + // https://llvm.org/docs/HowToCrossCompileLLVM.html if target != builder.config.build { builder.ensure(Llvm { target: builder.config.build }); diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 885010b039e..90ef48798dd 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -249,6 +249,7 @@ target | std | host | notes `powerpc-wrs-vxworks` | ? | | `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2) `powerpc64le-unknown-freebsd` | | | PPC64LE FreeBSD +`powerpc-unknown-freebsd` | | | PowerPC FreeBSD `powerpc64-unknown-linux-musl` | ? | | `powerpc64-wrs-vxworks` | ? | | `powerpc64le-unknown-linux-musl` | ? | | From b6badee1400b60b84623a3eaa65ba668ff1aa251 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Wed, 21 Jul 2021 14:42:20 +0200 Subject: [PATCH 02/10] Fix span when suggesting to add an associated type bound --- compiler/rustc_middle/src/ty/error.rs | 65 ++++++++++++++++++--------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 96aae3bd70c..f1c7c1ea852 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -628,6 +628,7 @@ impl Trait for X { assoc_substs, ty, msg, + false, ) { return true; } @@ -646,6 +647,7 @@ impl Trait for X { assoc_substs, ty, msg, + false, ); } } @@ -771,13 +773,24 @@ fn foo(&self) -> Self::T { String::new() } ) -> bool { let assoc = self.associated_item(proj_ty.item_def_id); if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { - self.constrain_associated_type_structured_suggestion( + let opaque_local_def_id = def_id.expect_local(); + let opaque_hir_id = self.hir().local_def_id_to_hir_id(opaque_local_def_id); + let opaque_hir_ty = match &self.hir().expect_item(opaque_hir_id).kind { + hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty, + _ => bug!("The HirId comes from a `ty::Opaque`"), + }; + + let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self); + + self.constrain_generic_bound_associated_type_structured_suggestion( db, - self.def_span(def_id), - &assoc, - proj_ty.trait_ref_and_own_substs(self).1, + &trait_ref, + opaque_hir_ty.bounds, + assoc, + assoc_substs, ty, - &msg, + msg, + true, ) } else { false @@ -899,6 +912,11 @@ fn foo(&self) -> Self::T { String::new() } /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref` /// requirement, provide a structured suggestion to constrain it to a given type `ty`. + /// + /// `is_bound_surely_present` indicates whether we know the bound we're looking for is + /// inside `bounds`. If that's the case then we can consider `bounds` containing only one + /// trait bound as the one we're looking for. This can help in cases where the associated + /// type is defined on a supertrait of the one present in the bounds. fn constrain_generic_bound_associated_type_structured_suggestion( self, db: &mut DiagnosticBuilder<'_>, @@ -908,23 +926,30 @@ fn foo(&self) -> Self::T { String::new() } assoc_substs: &[ty::GenericArg<'tcx>], ty: Ty<'tcx>, msg: &str, + is_bound_surely_present: bool, ) -> bool { // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. - bounds.iter().any(|bound| match bound { - hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => { - // Relate the type param against `T` in `::Foo`. - ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id) - && self.constrain_associated_type_structured_suggestion( - db, - ptr.span, - assoc, - assoc_substs, - ty, - msg, - ) - } - _ => false, - }) + + let trait_bounds = bounds.iter().filter_map(|bound| match bound { + hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr), + _ => None, + }); + + let matching_trait_bounds = trait_bounds + .clone() + .filter(|ptr| ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id)) + .collect::>(); + + let span = match &matching_trait_bounds[..] { + &[ptr] => ptr.span, + &[] if is_bound_surely_present => match &trait_bounds.collect::>()[..] { + &[ptr] => ptr.span, + _ => return false, + }, + _ => return false, + }; + + self.constrain_associated_type_structured_suggestion(db, span, assoc, assoc_substs, ty, msg) } /// Given a span corresponding to a bound, provide a structured suggestion to set an From d1bc9413858b334b6cdaf345bd6b50cb9aa4cec2 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Wed, 21 Jul 2021 14:42:32 +0200 Subject: [PATCH 03/10] Add regression test --- src/test/ui/associated-types/issue-87261.rs | 99 ++++++++ .../ui/associated-types/issue-87261.stderr | 238 ++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 src/test/ui/associated-types/issue-87261.rs create mode 100644 src/test/ui/associated-types/issue-87261.stderr diff --git a/src/test/ui/associated-types/issue-87261.rs b/src/test/ui/associated-types/issue-87261.rs new file mode 100644 index 00000000000..a70f771e482 --- /dev/null +++ b/src/test/ui/associated-types/issue-87261.rs @@ -0,0 +1,99 @@ +trait Foo {} + +trait Trait { + type Associated; +} +trait DerivedTrait: Trait {} +trait GenericTrait { + type Associated; +} + +struct Impl; +impl Foo for Impl {} +impl Trait for Impl { + type Associated = (); +} +impl DerivedTrait for Impl {} +impl GenericTrait for Impl { + type Associated = (); +} + +fn returns_opaque() -> impl Trait + 'static { + Impl +} +fn returns_opaque_derived() -> impl DerivedTrait + 'static { + Impl +} +fn returns_opaque_foo() -> impl Trait + Foo { + Impl +} +fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo { + Impl +} +fn returns_opaque_generic() -> impl GenericTrait<()> + 'static { + Impl +} +fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo { + Impl +} +fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait { + Impl +} + +fn accepts_trait>(_: T) {} +fn accepts_generic_trait>(_: T) {} + +fn check_generics(a: A, b: B, c: C, d: D, e: E, f: F, g: G) +where + A: Trait + 'static, + B: DerivedTrait + 'static, + C: Trait + Foo, + D: DerivedTrait + Foo, + E: GenericTrait<()> + 'static, + F: GenericTrait<()> + Foo, + G: GenericTrait<()> + GenericTrait, +{ + accepts_trait(a); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(b); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(c); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(d); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_generic_trait(e); + //~^ ERROR type mismatch resolving `>::Associated == ()` + + accepts_generic_trait(f); + //~^ ERROR type mismatch resolving `>::Associated == ()` + + accepts_generic_trait(g); + //~^ ERROR type mismatch resolving `>::Associated == ()` +} + +fn main() { + accepts_trait(returns_opaque()); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(returns_opaque_derived()); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(returns_opaque_foo()); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(returns_opaque_derived_foo()); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_generic_trait(returns_opaque_generic()); + //~^ ERROR type mismatch resolving ` as GenericTrait<()>>::Associated == ()` + + accepts_generic_trait(returns_opaque_generic_foo()); + //~^ ERROR type mismatch resolving `+Foo as GenericTrait<()>>::Associated == ()` + + accepts_generic_trait(returns_opaque_generic_duplicate()); + //~^ ERROR type mismatch resolving `+GenericTrait as GenericTrait<()>>::Associated == ()` +} diff --git a/src/test/ui/associated-types/issue-87261.stderr b/src/test/ui/associated-types/issue-87261.stderr new file mode 100644 index 00000000000..0725acfe537 --- /dev/null +++ b/src/test/ui/associated-types/issue-87261.stderr @@ -0,0 +1,238 @@ +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:56:5 + | +LL | fn accepts_trait>(_: T) {} + | --------------- required by this bound in `accepts_trait` +... +LL | accepts_trait(a); + | ^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Associated` +help: consider constraining the associated type `::Associated` to `()` + | +LL | A: Trait + 'static, + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:59:5 + | +LL | fn accepts_trait>(_: T) {} + | --------------- required by this bound in `accepts_trait` +... +LL | accepts_trait(b); + | ^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Associated` + = help: consider constraining the associated type `::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:62:5 + | +LL | fn accepts_trait>(_: T) {} + | --------------- required by this bound in `accepts_trait` +... +LL | accepts_trait(c); + | ^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Associated` +help: consider constraining the associated type `::Associated` to `()` + | +LL | C: Trait + Foo, + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:65:5 + | +LL | fn accepts_trait>(_: T) {} + | --------------- required by this bound in `accepts_trait` +... +LL | accepts_trait(d); + | ^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Associated` + = help: consider constraining the associated type `::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0271]: type mismatch resolving `>::Associated == ()` + --> $DIR/issue-87261.rs:68:5 + | +LL | fn accepts_generic_trait>(_: T) {} + | --------------- required by this bound in `accepts_generic_trait` +... +LL | accepts_generic_trait(e); + | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `>::Associated` +help: consider constraining the associated type `>::Associated` to `()` + | +LL | E: GenericTrait<(), Associated = ()> + 'static, + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `>::Associated == ()` + --> $DIR/issue-87261.rs:71:5 + | +LL | fn accepts_generic_trait>(_: T) {} + | --------------- required by this bound in `accepts_generic_trait` +... +LL | accepts_generic_trait(f); + | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `>::Associated` +help: consider constraining the associated type `>::Associated` to `()` + | +LL | F: GenericTrait<(), Associated = ()> + Foo, + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `>::Associated == ()` + --> $DIR/issue-87261.rs:74:5 + | +LL | fn accepts_generic_trait>(_: T) {} + | --------------- required by this bound in `accepts_generic_trait` +... +LL | accepts_generic_trait(g); + | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `>::Associated` + = help: consider constraining the associated type `>::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:79:5 + | +LL | fn returns_opaque() -> impl Trait + 'static { + | -------------------- the found opaque type +... +LL | fn accepts_trait>(_: T) {} + | --------------- required by this bound in `accepts_trait` +... +LL | accepts_trait(returns_opaque()); + | ^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Associated` +help: consider constraining the associated type `::Associated` to `()` + | +LL | fn returns_opaque() -> impl Trait + 'static { + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:82:5 + | +LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static { + | --------------------------- the found opaque type +... +LL | fn accepts_trait>(_: T) {} + | --------------- required by this bound in `accepts_trait` +... +LL | accepts_trait(returns_opaque_derived()); + | ^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Associated` +help: consider constraining the associated type `::Associated` to `()` + | +LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static { + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:85:5 + | +LL | fn returns_opaque_foo() -> impl Trait + Foo { + | ---------------- the found opaque type +... +LL | fn accepts_trait>(_: T) {} + | --------------- required by this bound in `accepts_trait` +... +LL | accepts_trait(returns_opaque_foo()); + | ^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Associated` +help: consider constraining the associated type `::Associated` to `()` + | +LL | fn returns_opaque_foo() -> impl Trait + Foo { + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:88:5 + | +LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo { + | ----------------------- the found opaque type +... +LL | fn accepts_trait>(_: T) {} + | --------------- required by this bound in `accepts_trait` +... +LL | accepts_trait(returns_opaque_derived_foo()); + | ^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Associated` + = help: consider constraining the associated type `::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0271]: type mismatch resolving ` as GenericTrait<()>>::Associated == ()` + --> $DIR/issue-87261.rs:91:5 + | +LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static { + | ------------------------------- the found opaque type +... +LL | fn accepts_generic_trait>(_: T) {} + | --------------- required by this bound in `accepts_generic_trait` +... +LL | accepts_generic_trait(returns_opaque_generic()); + | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type ` as GenericTrait<()>>::Associated` +help: consider constraining the associated type ` as GenericTrait<()>>::Associated` to `()` + | +LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static { + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `+Foo as GenericTrait<()>>::Associated == ()` + --> $DIR/issue-87261.rs:94:5 + | +LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo { + | --------------------------- the found opaque type +... +LL | fn accepts_generic_trait>(_: T) {} + | --------------- required by this bound in `accepts_generic_trait` +... +LL | accepts_generic_trait(returns_opaque_generic_foo()); + | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `+Foo as GenericTrait<()>>::Associated` +help: consider constraining the associated type `+Foo as GenericTrait<()>>::Associated` to `()` + | +LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + Foo { + | ^^^^^^^^^^^^^^^^^ + +error[E0271]: type mismatch resolving `+GenericTrait as GenericTrait<()>>::Associated == ()` + --> $DIR/issue-87261.rs:97:5 + | +LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait { + | ---------------------------------------- the found opaque type +... +LL | fn accepts_generic_trait>(_: T) {} + | --------------- required by this bound in `accepts_generic_trait` +... +LL | accepts_generic_trait(returns_opaque_generic_duplicate()); + | ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `+GenericTrait as GenericTrait<()>>::Associated` + = help: consider constraining the associated type `+GenericTrait as GenericTrait<()>>::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0271`. From c5dda05e4e47f8435400c27e31f198f88147dd9e Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 23 Jul 2021 15:26:12 +0200 Subject: [PATCH 04/10] Implement `AssignToDroppingUnionField` in THIR unsafeck --- .../rustc_mir_build/src/check_unsafety.rs | 48 ++++++++++++------- src/test/ui/union/union-unsafe.rs | 4 +- src/test/ui/union/union-unsafe.thir.stderr | 18 ++++++- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 82e19c05527..21534290d12 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 $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`. From 04634e88a35d8989966c181e326e41ed1973d35e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 23 Jul 2021 19:04:07 +0200 Subject: [PATCH 05/10] Mark `format_args_nl` as `#[doc(hidden)]` --- library/core/src/macros/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3ca8f27c79a..07ee589e29f 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -845,6 +845,7 @@ pub(crate) mod builtin { language use and is subject to change" )] #[allow_internal_unstable(fmt_internals)] + #[doc(hidden)] #[rustc_builtin_macro] #[macro_export] macro_rules! format_args_nl { From 74f01a4bbe441816aa5de489ca87f77d3474af37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Nogueira=20Rolim?= <34201958+ericonr@users.noreply.github.com> Date: Fri, 23 Jul 2021 02:32:55 -0300 Subject: [PATCH 06/10] Fix parameter names in std::env documentation. The function parameters were renamed, but the documentation wasn't. --- library/std/src/env.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 64f88c1aba6..5709d97d643 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 /// From a2ae1912954bf6e21c706258348735218ceb1ab4 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 22 Jul 2021 17:40:01 -0500 Subject: [PATCH 07/10] Rename `known_attrs` to `expanded_inert_attrs` and move to rustc_expand There's no need for this to be (untracked) global state. --- compiler/rustc_expand/src/base.rs | 6 ++++++ compiler/rustc_expand/src/expand.rs | 4 ++-- compiler/rustc_session/src/session.rs | 10 ---------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 8c6aef80635..3d5bc770c4f 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,6 +1,7 @@ use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; +use rustc_ast::attr::MarkedAttrs; use rustc_ast::ptr::P; use rustc_ast::token::{self, Nonterminal}; use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream}; @@ -951,6 +952,10 @@ pub struct ExtCtxt<'a> { /// /// `Ident` is the module name. pub(super) extern_mod_loaded: OnExternModLoaded<'a>, + /// When we 'expand' an inert attribute, we leave it + /// in the AST, but insert it here so that we know + /// not to expand it again. + pub(super) expanded_inert_attrs: MarkedAttrs, } impl<'a> ExtCtxt<'a> { @@ -977,6 +982,7 @@ impl<'a> ExtCtxt<'a> { }, force_mode: false, expansions: FxHashMap::default(), + expanded_inert_attrs: MarkedAttrs::new(), } } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index dcd871c9d20..a9250bf9787 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -754,7 +754,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } SyntaxExtensionKind::NonMacroAttr { mark_used } => { - self.cx.sess.mark_attr_known(&attr); + self.cx.expanded_inert_attrs.mark(&attr); if *mark_used { self.cx.sess.mark_attr_used(&attr); } @@ -1040,7 +1040,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { item.visit_attrs(|attrs| { attr = attrs .iter() - .position(|a| !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a)) + .position(|a| !self.cx.expanded_inert_attrs.is_marked(a) && !is_builtin_attr(a)) .map(|attr_pos| { let attr = attrs.remove(attr_pos); let following_derives = attrs[attr_pos..] diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 86d495c3353..369af437c43 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -219,7 +219,6 @@ pub struct Session { /// Set of enabled features for the current target. pub target_features: FxHashSet, - known_attrs: Lock, used_attrs: Lock, /// `Span`s for `if` conditions that we have suggested turning into `if let`. @@ -1076,14 +1075,6 @@ impl Session { == config::InstrumentCoverage::ExceptUnusedFunctions } - pub fn mark_attr_known(&self, attr: &Attribute) { - self.known_attrs.lock().mark(attr) - } - - pub fn is_attr_known(&self, attr: &Attribute) -> bool { - self.known_attrs.lock().is_marked(attr) - } - pub fn mark_attr_used(&self, attr: &Attribute) { self.used_attrs.lock().mark(attr) } @@ -1389,7 +1380,6 @@ pub fn build_session( miri_unleashed_features: Lock::new(Default::default()), asm_arch, target_features: FxHashSet::default(), - known_attrs: Lock::new(MarkedAttrs::new()), used_attrs: Lock::new(MarkedAttrs::new()), if_let_suggestions: Default::default(), }; From 30b619771d41a9fb0914b5064050bb1aa202439a Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 23 Jul 2021 17:35:18 -0700 Subject: [PATCH 08/10] IEEE 754 is not an RFC --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 35e5627e61f..6eb70dee395 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -44,7 +44,7 @@ Libraries - [`leading_zeros`, and `trailing_zeros` are now available on all `NonZero` integer types.][84082] - [`{f32, f64}::from_str` now parse and print special values - (`NaN`, `-0`) according to IEEE RFC 754.][78618] + (`NaN`, `-0`) according to IEEE 754.][78618] - [You can now index into slices using `(Bound, Bound)`.][77704] - [Add the `BITS` associated constant to all numeric types.][82565] From 17f7536fb220fc53cd0af2de46528070cfab012c Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 22 Jul 2021 02:04:05 +0000 Subject: [PATCH 09/10] Remove detection of rustup and cargo in 'missing extern crate' diagnostics Previously, this would change the test output when RUSTUP_HOME was set: ``` ---- [ui] ui/issues/issue-49851/compiler-builtins-error.rs stdout ---- diff of stderr: 1 error[E0463]: can't find crate for `core` 2 | 3 = note: the `thumbv7em-none-eabihf` target may not be installed + = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf` 4 5 error: aborting due to previous error 6 ``` Originally, I fixed it by explicitly unsetting RUSTUP_HOME in compiletest. Then I realized that almost no one has RUSTUP_HOME set, since rustup doesn't set it itself; although it does set RUST_RECURSION_COUNT whenever it launches a proxy. Then it was pointed out that this runtime check doesn't really make sense and it's fine to make it unconditional. --- compiler/rustc_metadata/src/locator.rs | 7 +++++-- src/test/ui/crate-loading/missing-std.rs | 1 - src/test/ui/crate-loading/missing-std.stderr | 2 +- src/test/ui/issues/issue-37131.stderr | 2 ++ .../ui/issues/issue-49851/compiler-builtins-error.stderr | 2 ++ 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 028104fd6b5..4936b22c7b9 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/src/test/ui/crate-loading/missing-std.rs b/src/test/ui/crate-loading/missing-std.rs index de4ccc18560..1a34c21ba54 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 e61486fdc6f..25808efdfa6 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 660a6935f36..b45574f0c49 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 7e23e0fd747..d963c07ea91 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 From 7879a59ac72e2c53659358bcaa3b7c32e06047f7 Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Sat, 24 Jul 2021 11:27:42 +0200 Subject: [PATCH 10/10] DOC: remove unnecessary feature crate attribute from example code --- library/core/src/mem/maybe_uninit.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 5122421ea8c..d3ebc1cebb6 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -461,7 +461,6 @@ impl 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; ///