diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/expand.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/locator.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/error.rs | 65 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/check_unsafety.rs | 48 | ||||
| -rw-r--r-- | compiler/rustc_session/src/session.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/mod.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs | 27 |
8 files changed, 117 insertions, 51 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 03d2105e5cc..c72b1b33dbc 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_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/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<T> Trait<T> for X { assoc_substs, ty, msg, + false, ) { return true; } @@ -646,6 +647,7 @@ impl<T> Trait<T> 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 `<A as T>::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::<Vec<_>>(); + + let span = match &matching_trait_bounds[..] { + &[ptr] => ptr.span, + &[] if is_bound_surely_present => match &trait_bounds.collect::<Vec<_>>()[..] { + &[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 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<Symbol>, - 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<LocalD hir_context: hir_id, body_unsafety, body_target_features, - in_possible_lhs_union_assign: false, + assignment_info: None, in_union_destructure: false, param_env: tcx.param_env(def.did), inside_adt: false, 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<Symbol>, - known_attrs: Lock<MarkedAttrs>, used_attrs: Lock<MarkedAttrs>, /// `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(), }; 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 + }, + } +} |
