diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index b75a686b81937..7111daa2ea9ab 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -14,8 +14,8 @@ use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::definitions::DefPathData; use rustc_session::parse::feature_err; +use rustc_span::symbol::kw; use rustc_span::{sym, Span}; use rustc_target::asm; use std::collections::hash_map::Entry; @@ -227,7 +227,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.create_def( parent_def_id.def_id, node_id, - DefPathData::AnonConst, + kw::Empty, DefKind::AnonConst, *op_sp, ); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5b07299d411b3..eb1a1d150270c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -13,10 +13,9 @@ use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::definitions::DefPathData; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{respan, Spanned}; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::DUMMY_SP; use rustc_span::{DesugaringKind, Span}; use thin_vec::{thin_vec, ThinVec}; @@ -376,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.create_def( parent_def_id.def_id, node_id, - DefPathData::AnonConst, + kw::Empty, DefKind::AnonConst, f.span, ); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index fbbb9d7a52ab3..f0f3e2c3c746a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -3,7 +3,6 @@ use super::ResolverAstLoweringExt; use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{FnDeclKind, LoweringContext, ParamMode}; -use hir::definitions::DefPathData; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; @@ -1367,7 +1366,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let def_id = self.create_def( self.local_def_id(parent_node_id), param_node_id, - DefPathData::TypeNs(sym::host), + sym::host, DefKind::ConstParam, span, ); @@ -1427,13 +1426,8 @@ impl<'hir> LoweringContext<'_, 'hir> { if let Some((span, hir_id, def_id)) = host_param_parts { let const_node_id = self.next_node_id(); - let anon_const = self.create_def( - def_id, - const_node_id, - DefPathData::AnonConst, - DefKind::AnonConst, - span, - ); + let anon_const = + self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span); let const_id = self.next_id(); let const_expr_id = self.next_id(); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index eb6d11a72e66e..aa8ad9784513d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -58,7 +58,6 @@ use rustc_errors::{DiagnosticArgFromDisplay, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::{ @@ -499,20 +498,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, parent: LocalDefId, node_id: ast::NodeId, - data: DefPathData, + name: Symbol, def_kind: DefKind, span: Span, ) -> LocalDefId { debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); assert!( self.opt_local_def_id(node_id).is_none(), - "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", + "adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}", node_id, - data, + def_kind, self.tcx.hir().def_key(self.local_def_id(node_id)), ); - let def_id = self.tcx.at(span).create_def(parent, data, def_kind).def_id(); + let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id(); debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); self.resolver.node_id_to_def_id.insert(node_id, def_id); @@ -809,7 +808,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let _def_id = self.create_def( self.current_hir_id_owner.def_id, param, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), + kw::UnderscoreLifetime, DefKind::LifetimeParam, ident.span, ); @@ -1227,7 +1226,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let def_id = self.create_def( parent_def_id.def_id, node_id, - DefPathData::AnonConst, + kw::Empty, DefKind::AnonConst, span, ); @@ -1465,7 +1464,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.create_def( self.current_hir_id_owner.def_id, *def_node_id, - DefPathData::TypeNs(ident.name), + ident.name, DefKind::TyParam, span, ); @@ -1619,7 +1618,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_def_id = self.create_def( self.current_hir_id_owner.def_id, opaque_ty_node_id, - DefPathData::ImplTrait, + kw::Empty, DefKind::OpaqueTy, opaque_ty_span, ); @@ -1674,7 +1673,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let duplicated_lifetime_def_id = self.create_def( opaque_ty_def_id, duplicated_lifetime_node_id, - DefPathData::LifetimeNs(lifetime.ident.name), + lifetime.ident.name, DefKind::LifetimeParam, lifetime.ident.span, ); @@ -2549,7 +2548,7 @@ impl<'hir> GenericArgsCtor<'hir> { let def_id = lcx.create_def( lcx.current_hir_id_owner.def_id, id, - DefPathData::AnonConst, + kw::Empty, DefKind::AnonConst, span, ); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 7b259055d40b5..acd85dd9a2d93 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -489,6 +489,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { #[instrument(level = "trace", skip(self))] fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> { + if place.layout.is_unsized() { + let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {}); + if matches!(tail.kind(), ty::Foreign(..)) { + // Unsized locals and, at least conceptually, even unsized arguments must be copied + // around, which requires dynamically determining their size. Therefore, we cannot + // allow `extern` types here. Consult t-opsem before removing this check. + panic!("unsized locals must not be `extern` types"); + } + } assert_eq!(place.llextra.is_some(), place.layout.is_unsized()); if place.layout.is_zst() { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 839cc4dabe3b7..8630e5623e168 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -594,7 +594,7 @@ fn push_unqualified_item_name( DefPathData::CrateRoot => { output.push_str(tcx.crate_name(def_id.krate).as_str()); } - DefPathData::ClosureExpr => { + DefPathData::Closure => { let label = coroutine_kind_label(tcx.coroutine_kind(def_id)); push_disambiguated_special_name( diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 0ab2b7ecd9c80..6661f1f81e612 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -414,6 +414,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { // value is through `undef`/`poison`, and the store itself is useless. } OperandValue::Ref(r, None, source_align) => { + assert!(dest.layout.is_sized(), "cannot directly store unsized values"); if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. let ty = bx.backend_type(dest.layout); diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 45795a7f7359a..83425dee1a8db 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -143,7 +143,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // Simple cases, which don't need DST adjustment: // * no metadata available - just log the case // * known alignment - sized types, `[T]`, `str` or a foreign type - // * packed struct - there is no alignment padding + // Note that looking at `field.align` is incorrect since that is not necessarily equal + // to the dynamic alignment of the type. match field.ty.kind() { _ if self.llextra.is_none() => { debug!( @@ -154,14 +155,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } _ if field.is_sized() => return simple(), ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(), - ty::Adt(def, _) => { - if def.repr().packed() { - // FIXME(eddyb) generalize the adjustment when we - // start supporting packing to larger alignments. - assert_eq!(self.layout.align.abi.bytes(), 1); - return simple(); - } - } _ => {} } @@ -186,7 +179,16 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { let unaligned_offset = bx.cx().const_usize(offset.bytes()); // Get the alignment of the field - let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta); + let (_, mut unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta); + + // For packed types, we need to cap alignment. + if let ty::Adt(def, _) = self.layout.ty.kind() + && let Some(packed) = def.repr().pack + { + let packed = bx.const_usize(packed.bytes()); + let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed); + unsized_align = bx.select(cmp, unsized_align, packed) + } // Bump the unaligned offset up to the appropriate alignment let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align); diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index c0a20e51482fa..04e5b550d6d9b 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -282,9 +282,7 @@ impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> { impl<'tcx> fmt::Display for FrameInfo<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { - if tcx.def_key(self.instance.def_id()).disambiguated_data.data - == DefPathData::ClosureExpr - { + if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure { write!(f, "inside closure") } else { // Note: this triggers a `good_path_delayed_bug` state, which means that if we ever @@ -299,7 +297,7 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> { impl<'tcx> FrameInfo<'tcx> { pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote { let span = self.span; - if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::ClosureExpr { + if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure { errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 } } else { let instance = format!("{}", self.instance); diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index c8977aac0fc5a..4d9e296d5441b 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -163,7 +163,17 @@ where // With custom DSTS, this *will* execute user-defined code, but the same // happens at run-time so that's okay. match self.size_and_align_of(&base_meta, &field_layout)? { - Some((_, align)) => (base_meta, offset.align_to(align)), + Some((_, align)) => { + // For packed types, we need to cap alignment. + let align = if let ty::Adt(def, _) = base.layout().ty.kind() + && let Some(packed) = def.repr().pack + { + align.min(packed) + } else { + align + }; + (base_meta, offset.align_to(align)) + } None => { // For unsized types with an extern type tail we perform no adjustments. // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index fedd380cada36..258d6710bc57f 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -1,3 +1,4 @@ +use crate::definitions::DefPathData; use crate::hir; use rustc_ast as ast; @@ -45,6 +46,7 @@ pub enum NonMacroAttrKind { } /// What kind of definition something is; e.g., `mod` vs `struct`. +/// `enum DefPathData` may need to be updated if a new variant is added here. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum DefKind { // Type namespace @@ -221,6 +223,41 @@ impl DefKind { } } + pub fn def_path_data(self, name: Symbol) -> DefPathData { + match self { + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::TyParam + | DefKind::ExternCrate => DefPathData::TypeNs(name), + DefKind::Fn + | DefKind::Const + | DefKind::ConstParam + | DefKind::Static(..) + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Field => DefPathData::ValueNs(name), + DefKind::Macro(..) => DefPathData::MacroNs(name), + DefKind::LifetimeParam => DefPathData::LifetimeNs(name), + DefKind::Ctor(..) => DefPathData::Ctor, + DefKind::Use => DefPathData::Use, + DefKind::ForeignMod => DefPathData::ForeignMod, + DefKind::AnonConst => DefPathData::AnonConst, + DefKind::InlineConst => DefPathData::AnonConst, + DefKind::OpaqueTy => DefPathData::OpaqueTy, + DefKind::GlobalAsm => DefPathData::GlobalAsm, + DefKind::Impl { .. } => DefPathData::Impl, + DefKind::Closure => DefPathData::Closure, + } + } + #[inline] pub fn is_fn_like(self) -> bool { matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 168b336e374fd..d222325475d33 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -246,6 +246,7 @@ impl DefPath { } } +/// New variants should only be added in synchronization with `enum DefKind`. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum DefPathData { // Root: these should only be used for the root nodes, because @@ -271,7 +272,7 @@ pub enum DefPathData { /// Something in the lifetime namespace. LifetimeNs(Symbol), /// A closure expression. - ClosureExpr, + Closure, // Subportions of items: /// Implicit constructor for a unit or tuple-like struct or enum variant. @@ -280,9 +281,7 @@ pub enum DefPathData { AnonConst, /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. - ImplTrait, - /// `impl Trait` generated associated type node. - ImplTraitAssocTy, + OpaqueTy, } impl Definitions { @@ -403,16 +402,17 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { + TypeNs(name) if name == kw::Empty => None, TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), - - Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst - | ImplTrait | ImplTraitAssocTy => None, + Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst + | OpaqueTy => None, } } pub fn name(&self) -> DefPathDataName { use self::DefPathData::*; match *self { + TypeNs(name) if name == kw::Empty => DefPathDataName::Anon { namespace: sym::opaque }, TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => { DefPathDataName::Named(name) } @@ -422,10 +422,10 @@ impl DefPathData { ForeignMod => DefPathDataName::Anon { namespace: kw::Extern }, Use => DefPathDataName::Anon { namespace: kw::Use }, GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm }, - ClosureExpr => DefPathDataName::Anon { namespace: sym::closure }, + Closure => DefPathDataName::Anon { namespace: sym::closure }, Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, - ImplTrait | ImplTraitAssocTy => DefPathDataName::Anon { namespace: sym::opaque }, + OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, } } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ff690db7bee6a..8e71327f82e53 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -977,7 +977,7 @@ impl<'tcx> TyCtxtAt<'tcx> { pub fn create_def( self, parent: LocalDefId, - data: hir::definitions::DefPathData, + name: Symbol, def_kind: DefKind, ) -> TyCtxtFeed<'tcx, LocalDefId> { // This function modifies `self.definitions` using a side-effect. @@ -1000,6 +1000,7 @@ impl<'tcx> TyCtxtAt<'tcx> { // This is fine because: // - those queries are `eval_always` so we won't miss their result changing; // - this write will have happened before these queries are called. + let data = def_kind.def_path_data(name); let key = self.untracked.definitions.write().create_def(parent, data); let feed = TyCtxtFeed { tcx: self.tcx, key }; diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index cebefbccc11d1..1c7a7545e2b0e 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -215,7 +215,7 @@ impl<'tcx> InstanceDef<'tcx> { }; matches!( tcx.def_key(def_id).disambiguated_data.data, - DefPathData::Ctor | DefPathData::ClosureExpr + DefPathData::Ctor | DefPathData::Closure ) } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 64ae11df5b512..5e09154789a79 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -131,7 +131,7 @@ pub trait Printer<'tcx>: Sized { match key.disambiguated_data.data { // Closures' own generics are only captures, don't print them. - DefPathData::ClosureExpr => {} + DefPathData::Closure => {} // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`. // Anon consts doesn't have their own generics, and inline consts' own // generics are their inferred types, so don't print them. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 68dd8dee87c44..25423348638a9 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1804,13 +1804,13 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { // (but also some things just print a `DefId` generally so maybe we need this?) fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace { match tcx.def_key(def_id).disambiguated_data.data { - DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => { + DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => { Namespace::TypeNS } DefPathData::ValueNs(..) | DefPathData::AnonConst - | DefPathData::ClosureExpr + | DefPathData::Closure | DefPathData::Ctor => Namespace::ValueNS, DefPathData::MacroNs(..) => Namespace::MacroNS, diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 224f3f36a3f56..647c92785e10d 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -4,9 +4,8 @@ use rustc_ast::*; use rustc_expand::expand::AstFragment; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::def_id::LocalDefId; -use rustc_hir::definitions::*; use rustc_span::hygiene::LocalExpnId; -use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; pub(crate) fn collect_definitions( @@ -30,16 +29,19 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { fn create_def( &mut self, node_id: NodeId, - data: DefPathData, + name: Symbol, def_kind: DefKind, span: Span, ) -> LocalDefId { let parent_def = self.parent_def; - debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); + debug!( + "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})", + node_id, def_kind, parent_def + ); self.resolver.create_def( parent_def, node_id, - data, + name, def_kind, self.expansion.to_expn_id(), span.with_parent(None), @@ -76,8 +78,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { self.visit_macro_invoc(field.id); } else { let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name); - let def = - self.create_def(field.id, DefPathData::ValueNs(name), DefKind::Field, field.span); + let def = self.create_def(field.id, name, DefKind::Field, field.span); self.with_parent(def, |this| visit::walk_field_def(this, field)); } } @@ -97,40 +98,36 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better let mut opt_macro_data = None; - let ty_data = DefPathData::TypeNs(i.ident.name); - let value_data = DefPathData::ValueNs(i.ident.name); - let (def_data, def_kind) = match &i.kind { - ItemKind::Impl(i) => { - (DefPathData::Impl, DefKind::Impl { of_trait: i.of_trait.is_some() }) - } - ItemKind::ForeignMod(..) => (DefPathData::ForeignMod, DefKind::ForeignMod), - ItemKind::Mod(..) => (ty_data, DefKind::Mod), - ItemKind::Trait(..) => (ty_data, DefKind::Trait), - ItemKind::TraitAlias(..) => (ty_data, DefKind::TraitAlias), - ItemKind::Enum(..) => (ty_data, DefKind::Enum), - ItemKind::Struct(..) => (ty_data, DefKind::Struct), - ItemKind::Union(..) => (ty_data, DefKind::Union), - ItemKind::ExternCrate(..) => (ty_data, DefKind::ExternCrate), - ItemKind::TyAlias(..) => (ty_data, DefKind::TyAlias), - ItemKind::Static(s) => (value_data, DefKind::Static(s.mutability)), - ItemKind::Const(..) => (value_data, DefKind::Const), - ItemKind::Fn(..) => (value_data, DefKind::Fn), + let def_kind = match &i.kind { + ItemKind::Impl(i) => DefKind::Impl { of_trait: i.of_trait.is_some() }, + ItemKind::ForeignMod(..) => DefKind::ForeignMod, + ItemKind::Mod(..) => DefKind::Mod, + ItemKind::Trait(..) => DefKind::Trait, + ItemKind::TraitAlias(..) => DefKind::TraitAlias, + ItemKind::Enum(..) => DefKind::Enum, + ItemKind::Struct(..) => DefKind::Struct, + ItemKind::Union(..) => DefKind::Union, + ItemKind::ExternCrate(..) => DefKind::ExternCrate, + ItemKind::TyAlias(..) => DefKind::TyAlias, + ItemKind::Static(s) => DefKind::Static(s.mutability), + ItemKind::Const(..) => DefKind::Const, + ItemKind::Fn(..) => DefKind::Fn, ItemKind::MacroDef(..) => { let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition()); let macro_kind = macro_data.ext.macro_kind(); opt_macro_data = Some(macro_data); - (DefPathData::MacroNs(i.ident.name), DefKind::Macro(macro_kind)) + DefKind::Macro(macro_kind) } ItemKind::MacCall(..) => { visit::walk_item(self, i); return self.visit_macro_invoc(i.id); } - ItemKind::GlobalAsm(..) => (DefPathData::GlobalAsm, DefKind::GlobalAsm), + ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, ItemKind::Use(..) => { return visit::walk_item(self, i); } }; - let def_id = self.create_def(i.id, def_data, def_kind, i.span); + let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span); if let Some(macro_data) = opt_macro_data { self.resolver.macro_map.insert(def_id.to_def_id(), macro_data); @@ -144,7 +141,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) { this.create_def( ctor_node_id, - DefPathData::Ctor, + kw::Empty, DefKind::Ctor(CtorOf::Struct, ctor_kind), i.span, ); @@ -174,12 +171,8 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { // then the closure_def will never be used, and we should avoid generating a // def-id for it. if let Some(body) = body { - let closure_def = self.create_def( - closure_id, - DefPathData::ClosureExpr, - DefKind::Closure, - span, - ); + let closure_def = + self.create_def(closure_id, kw::Empty, DefKind::Closure, span); self.with_parent(closure_def, |this| this.visit_block(body)); } return; @@ -190,21 +183,19 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { - self.create_def(id, DefPathData::Use, DefKind::Use, use_tree.span); + self.create_def(id, kw::Empty, DefKind::Use, use_tree.span); visit::walk_use_tree(self, use_tree, id); } fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { - let (def_data, def_kind) = match fi.kind { - ForeignItemKind::Static(_, mt, _) => { - (DefPathData::ValueNs(fi.ident.name), DefKind::Static(mt)) - } - ForeignItemKind::Fn(_) => (DefPathData::ValueNs(fi.ident.name), DefKind::Fn), - ForeignItemKind::TyAlias(_) => (DefPathData::TypeNs(fi.ident.name), DefKind::ForeignTy), + let def_kind = match fi.kind { + ForeignItemKind::Static(_, mt, _) => DefKind::Static(mt), + ForeignItemKind::Fn(_) => DefKind::Fn, + ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), }; - let def = self.create_def(fi.id, def_data, def_kind, fi.span); + let def = self.create_def(fi.id, fi.ident.name, def_kind, fi.span); self.with_parent(def, |this| visit::walk_foreign_item(this, fi)); } @@ -213,13 +204,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { if v.is_placeholder { return self.visit_macro_invoc(v.id); } - let def = - self.create_def(v.id, DefPathData::TypeNs(v.ident.name), DefKind::Variant, v.span); + let def = self.create_def(v.id, v.ident.name, DefKind::Variant, v.span); self.with_parent(def, |this| { if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&v.data) { this.create_def( ctor_node_id, - DefPathData::Ctor, + kw::Empty, DefKind::Ctor(CtorOf::Variant, ctor_kind), v.span, ); @@ -242,15 +232,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { self.visit_macro_invoc(param.id); return; } - let name = param.ident.name; - let (def_path_data, def_kind) = match param.kind { - GenericParamKind::Lifetime { .. } => { - (DefPathData::LifetimeNs(name), DefKind::LifetimeParam) - } - GenericParamKind::Type { .. } => (DefPathData::TypeNs(name), DefKind::TyParam), - GenericParamKind::Const { .. } => (DefPathData::ValueNs(name), DefKind::ConstParam), + let def_kind = match param.kind { + GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam, + GenericParamKind::Type { .. } => DefKind::TyParam, + GenericParamKind::Const { .. } => DefKind::ConstParam, }; - self.create_def(param.id, def_path_data, def_kind, param.ident.span); + self.create_def(param.id, param.ident.name, def_kind, param.ident.span); // impl-Trait can happen inside generic parameters, like // ``` @@ -264,14 +251,14 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { - let (def_data, def_kind) = match &i.kind { - AssocItemKind::Fn(..) => (DefPathData::ValueNs(i.ident.name), DefKind::AssocFn), - AssocItemKind::Const(..) => (DefPathData::ValueNs(i.ident.name), DefKind::AssocConst), - AssocItemKind::Type(..) => (DefPathData::TypeNs(i.ident.name), DefKind::AssocTy), + let def_kind = match &i.kind { + AssocItemKind::Fn(..) => DefKind::AssocFn, + AssocItemKind::Const(..) => DefKind::AssocConst, + AssocItemKind::Type(..) => DefKind::AssocTy, AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), }; - let def = self.create_def(i.id, def_data, def_kind, i.span); + let def = self.create_def(i.id, i.ident.name, def_kind, i.span); self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt)); } @@ -283,12 +270,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - let def = self.create_def( - constant.id, - DefPathData::AnonConst, - DefKind::AnonConst, - constant.value.span, - ); + let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); self.with_parent(def, |this| visit::walk_anon_const(this, constant)); } @@ -298,25 +280,21 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ExprKind::Closure(ref closure) => { // Async closures desugar to closures inside of closures, so // we must create two defs. - let closure_def = - self.create_def(expr.id, DefPathData::ClosureExpr, DefKind::Closure, expr.span); + let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span); match closure.asyncness { - Async::Yes { closure_id, .. } => self.create_def( - closure_id, - DefPathData::ClosureExpr, - DefKind::Closure, - expr.span, - ), + Async::Yes { closure_id, .. } => { + self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span) + } Async::No => closure_def, } } ExprKind::Gen(_, _, _) => { - self.create_def(expr.id, DefPathData::ClosureExpr, DefKind::Closure, expr.span) + self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) } ExprKind::ConstBlock(ref constant) => { let def = self.create_def( constant.id, - DefPathData::AnonConst, + kw::Empty, DefKind::InlineConst, constant.value.span, ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 208391cc0199f..70e0eb12c01da 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -45,7 +45,6 @@ use rustc_hir::def::NonMacroAttrKind; use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::definitions::DefPathData; use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; @@ -1212,11 +1211,12 @@ impl<'tcx> Resolver<'_, 'tcx> { &mut self, parent: LocalDefId, node_id: ast::NodeId, - data: DefPathData, + name: Symbol, def_kind: DefKind, expn_id: ExpnId, span: Span, ) -> LocalDefId { + let data = def_kind.def_path_data(name); assert!( !self.node_id_to_def_id.contains_key(&node_id), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 1fd8542b2a642..18ca347de97f1 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -379,14 +379,13 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { hir::definitions::DefPathData::ForeignMod => "F", // Not specified in v0's hir::definitions::DefPathData::TypeNs(..) => "t", hir::definitions::DefPathData::ValueNs(..) => "v", - hir::definitions::DefPathData::ClosureExpr => "C", + hir::definitions::DefPathData::Closure => "C", hir::definitions::DefPathData::Ctor => "c", hir::definitions::DefPathData::AnonConst => "k", - hir::definitions::DefPathData::ImplTrait => "i", + hir::definitions::DefPathData::OpaqueTy => "i", hir::definitions::DefPathData::CrateRoot | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm - | hir::definitions::DefPathData::ImplTraitAssocTy | hir::definitions::DefPathData::MacroNs(..) | hir::definitions::DefPathData::LifetimeNs(..) => { bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 88989806997e6..e002e345ae689 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -770,17 +770,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { // Uppercase categories are more stable than lowercase ones. DefPathData::TypeNs(_) => 't', DefPathData::ValueNs(_) => 'v', - DefPathData::ClosureExpr => 'C', + DefPathData::Closure => 'C', DefPathData::Ctor => 'c', DefPathData::AnonConst => 'k', - DefPathData::ImplTrait => 'i', + DefPathData::OpaqueTy => 'i', // These should never show up as `path_append` arguments. DefPathData::CrateRoot | DefPathData::Use | DefPathData::GlobalAsm | DefPathData::Impl - | DefPathData::ImplTraitAssocTy | DefPathData::MacroNs(_) | DefPathData::LifetimeNs(_) => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index d753aa8618e84..41db8059cbee3 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -55,3 +55,6 @@ trait_selection_trait_has_no_impls = this trait has no implementations, consider trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} + +trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}` + .help = expect either a generic argument name or {"`{Self}`"} as format argument diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index ba019c4ff6fe5..fbe6e2bd5b892 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -321,7 +321,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } #[derive(Clone, Debug)] -pub struct OnUnimplementedFormatString(Symbol, Span); +pub struct OnUnimplementedFormatString { + symbol: Symbol, + span: Span, + is_diagnostic_namespace_variant: bool, +} #[derive(Debug)] pub struct OnUnimplementedDirective { @@ -401,6 +405,14 @@ impl IgnoredDiagnosticOption { } } +#[derive(LintDiagnostic)] +#[diag(trait_selection_unknown_format_parameter_for_on_unimplemented_attr)] +#[help] +pub struct UnknownFormatParameterForOnUnimplementedAttr { + argument_name: Symbol, + trait_name: Symbol, +} + impl<'tcx> OnUnimplementedDirective { fn parse( tcx: TyCtxt<'tcx>, @@ -414,8 +426,14 @@ impl<'tcx> OnUnimplementedDirective { let mut item_iter = items.iter(); let parse_value = |value_str, value_span| { - OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span, value_span) - .map(Some) + OnUnimplementedFormatString::try_parse( + tcx, + item_def_id, + value_str, + value_span, + is_diagnostic_namespace_variant, + ) + .map(Some) }; let condition = if is_root { @@ -552,15 +570,15 @@ impl<'tcx> OnUnimplementedDirective { IgnoredDiagnosticOption::maybe_emit_warning( tcx, item_def_id, - directive.message.as_ref().map(|f| f.1), - aggr.message.as_ref().map(|f| f.1), + directive.message.as_ref().map(|f| f.span), + aggr.message.as_ref().map(|f| f.span), "message", ); IgnoredDiagnosticOption::maybe_emit_warning( tcx, item_def_id, - directive.label.as_ref().map(|f| f.1), - aggr.label.as_ref().map(|f| f.1), + directive.label.as_ref().map(|f| f.span), + aggr.label.as_ref().map(|f| f.span), "label", ); IgnoredDiagnosticOption::maybe_emit_warning( @@ -573,8 +591,8 @@ impl<'tcx> OnUnimplementedDirective { IgnoredDiagnosticOption::maybe_emit_warning( tcx, item_def_id, - directive.parent_label.as_ref().map(|f| f.1), - aggr.parent_label.as_ref().map(|f| f.1), + directive.parent_label.as_ref().map(|f| f.span), + aggr.parent_label.as_ref().map(|f| f.span), "parent_label", ); IgnoredDiagnosticOption::maybe_emit_warning( @@ -634,7 +652,7 @@ impl<'tcx> OnUnimplementedDirective { item_def_id, value, attr.span, - attr.span, + is_diagnostic_namespace_variant, )?), notes: Vec::new(), parent_label: None, @@ -713,7 +731,12 @@ impl<'tcx> OnUnimplementedDirective { // `with_no_visible_paths` is also used when generating the options, // so we need to match it here. ty::print::with_no_visible_paths!( - OnUnimplementedFormatString(v, cfg.span).format( + OnUnimplementedFormatString { + symbol: v, + span: cfg.span, + is_diagnostic_namespace_variant: false + } + .format( tcx, trait_ref, &options_map @@ -761,20 +784,19 @@ impl<'tcx> OnUnimplementedFormatString { tcx: TyCtxt<'tcx>, item_def_id: DefId, from: Symbol, - err_sp: Span, value_span: Span, + is_diagnostic_namespace_variant: bool, ) -> Result { - let result = OnUnimplementedFormatString(from, value_span); - result.verify(tcx, item_def_id, err_sp)?; + let result = OnUnimplementedFormatString { + symbol: from, + span: value_span, + is_diagnostic_namespace_variant, + }; + result.verify(tcx, item_def_id)?; Ok(result) } - fn verify( - &self, - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - span: Span, - ) -> Result<(), ErrorGuaranteed> { + fn verify(&self, tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<(), ErrorGuaranteed> { let trait_def_id = if tcx.is_trait(item_def_id) { item_def_id } else { @@ -783,7 +805,7 @@ impl<'tcx> OnUnimplementedFormatString { }; let trait_name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(item_def_id); - let s = self.0.as_str(); + let s = self.symbol.as_str(); let parser = Parser::new(s, None, None, false, ParseMode::Format); let mut result = Ok(()); for token in parser { @@ -793,24 +815,40 @@ impl<'tcx> OnUnimplementedFormatString { Position::ArgumentNamed(s) => { match Symbol::intern(s) { // `{ThisTraitsName}` is allowed - s if s == trait_name => (), - s if ALLOWED_FORMAT_SYMBOLS.contains(&s) => (), + s if s == trait_name && !self.is_diagnostic_namespace_variant => (), + s if ALLOWED_FORMAT_SYMBOLS.contains(&s) + && !self.is_diagnostic_namespace_variant => + { + () + } // So is `{A}` if A is a type parameter s if generics.params.iter().any(|param| param.name == s) => (), s => { - result = Err(struct_span_err!( - tcx.sess, - span, - E0230, - "there is no parameter `{}` on {}", - s, - if trait_def_id == item_def_id { - format!("trait `{trait_name}`") - } else { - "impl".to_string() - } - ) - .emit()); + if self.is_diagnostic_namespace_variant { + tcx.emit_spanned_lint( + UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, + tcx.local_def_id_to_hir_id(item_def_id.expect_local()), + self.span, + UnknownFormatParameterForOnUnimplementedAttr { + argument_name: s, + trait_name, + }, + ); + } else { + result = Err(struct_span_err!( + tcx.sess, + self.span, + E0230, + "there is no parameter `{}` on {}", + s, + if trait_def_id == item_def_id { + format!("trait `{trait_name}`") + } else { + "impl".to_string() + } + ) + .emit()); + } } } } @@ -818,7 +856,7 @@ impl<'tcx> OnUnimplementedFormatString { Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => { let reported = struct_span_err!( tcx.sess, - span, + self.span, E0231, "only named substitution parameters are allowed" ) @@ -857,37 +895,42 @@ impl<'tcx> OnUnimplementedFormatString { .collect::>(); let empty_string = String::new(); - let s = self.0.as_str(); + let s = self.symbol.as_str(); let parser = Parser::new(s, None, None, false, ParseMode::Format); let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string); parser .map(|p| match p { - Piece::String(s) => s, + Piece::String(s) => s.to_owned(), Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => { - let s = Symbol::intern(s); + Position::ArgumentNamed(arg) => { + let s = Symbol::intern(arg); match generic_map.get(&s) { - Some(val) => val, - None if s == name => &trait_str, + Some(val) => val.to_string(), + None if self.is_diagnostic_namespace_variant => { + format!("{{{arg}}}") + } + None if s == name => trait_str.clone(), None => { if let Some(val) = options.get(&s) { - val + val.clone() } else if s == sym::from_desugaring { // don't break messages using these two arguments incorrectly - &empty_string - } else if s == sym::ItemContext { - item_context + String::new() + } else if s == sym::ItemContext + && !self.is_diagnostic_namespace_variant + { + item_context.clone() } else if s == sym::integral { - "{integral}" + String::from("{integral}") } else if s == sym::integer_ { - "{integer}" + String::from("{integer}") } else if s == sym::float { - "{float}" + String::from("{float}") } else { bug!( "broken on_unimplemented {:?} for {:?}: \ no argument matching {:?}", - self.0, + self.symbol, trait_ref, s ) @@ -895,7 +938,7 @@ impl<'tcx> OnUnimplementedFormatString { } } } - _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0), + _ => bug!("broken on_unimplemented {:?} - bad format arg", self.symbol), }, }) .collect() diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index c6ff7e2a9ef40..b28e3d5c41236 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -424,11 +424,23 @@ fn fn_abi_sanity_check<'tcx>( } PassMode::Indirect { meta_attrs: None, .. } => { // No metadata, must be sized. + // Conceptually, unsized arguments must be copied around, which requires dynamically + // determining their size, which we cannot do without metadata. Consult + // t-opsem before removing this check. assert!(arg.layout.is_sized()); } PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => { // With metadata. Must be unsized and not on the stack. assert!(arg.layout.is_unsized() && !on_stack); + // Also, must not be `extern` type. + let tail = cx.tcx.struct_tail_with_normalize(arg.layout.ty, |ty| ty, || {}); + if matches!(tail.kind(), ty::Foreign(..)) { + // These types do not have metadata, so having `meta_attrs` is bogus. + // Conceptually, unsized arguments must be copied around, which requires dynamically + // determining their size. Therefore, we cannot allow `extern` types here. Consult + // t-opsem before removing this check. + panic!("unsized arguments must not be `extern` types"); + } } } } diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 82cd0cc50d21a..7a81570e55b85 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; -use rustc_hir::definitions::DefPathData; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt}; @@ -254,8 +253,7 @@ fn associated_type_for_impl_trait_in_trait( assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait); let span = tcx.def_span(opaque_ty_def_id); - let trait_assoc_ty = - tcx.at(span).create_def(trait_def_id, DefPathData::ImplTraitAssocTy, DefKind::AssocTy); + let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy); let local_def_id = trait_assoc_ty.def_id(); let def_id = local_def_id.to_def_id(); @@ -356,8 +354,7 @@ fn associated_type_for_impl_trait_in_impl( hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), hir::FnRetTy::Return(ty) => ty.span, }; - let impl_assoc_ty = - tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy, DefKind::AssocTy); + let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, kw::Empty, DefKind::AssocTy); let local_def_id = impl_assoc_ty.def_id(); let def_id = local_def_id.to_def_id(); diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5957f9fd44395..dec9f194863ef 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1045,11 +1045,11 @@ impl [T] { /// # Examples /// /// ``` - /// let slice = ['r', 'u', 's', 't']; - /// let mut iter = slice.windows(2); - /// assert_eq!(iter.next().unwrap(), &['r', 'u']); - /// assert_eq!(iter.next().unwrap(), &['u', 's']); - /// assert_eq!(iter.next().unwrap(), &['s', 't']); + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.windows(3); + /// assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']); + /// assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']); /// assert!(iter.next().is_none()); /// ``` /// diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs new file mode 100644 index 0000000000000..e58fe60b5f6ed --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs @@ -0,0 +1,35 @@ +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed, C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed, C)] +struct PackedUnsized { + f: u8, + d: [u32], +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation does *not* think there is + // any padding in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 4*4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); +} } diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs new file mode 100644 index 0000000000000..910b5d94320d0 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs @@ -0,0 +1,38 @@ +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed(4))] +struct Slice([u32]); + +#[repr(packed(2), C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed(2), C)] +struct PackedUnsized { + f: u8, + d: Slice, +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation correctly adds exact 1 byte of padding + // in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); +} } diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs new file mode 100644 index 0000000000000..eb985c062f3dd --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs @@ -0,0 +1,67 @@ +#![feature(diagnostic_namespace)] + +#[diagnostic::on_unimplemented( + on(_Self = "&str"), + //~^WARN malformed `on_unimplemented` attribute + //~|WARN malformed `on_unimplemented` attribute + message = "trait has `{Self}` and `{T}` as params", + label = "trait has `{Self}` and `{T}` as params", + note = "trait has `{Self}` and `{T}` as params", + parent_label = "in this scope", + //~^WARN malformed `on_unimplemented` attribute + //~|WARN malformed `on_unimplemented` attribute + append_const_msg + //~^WARN malformed `on_unimplemented` attribute + //~|WARN malformed `on_unimplemented` attribute +)] +trait Foo {} + +#[diagnostic::on_unimplemented = "Message"] +//~^WARN malformed `on_unimplemented` attribute +//~|WARN malformed `on_unimplemented` attribute +trait Bar {} + +#[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] +//~^WARN #[diagnostic::on_unimplemented]` can only be applied to trait definitions +impl Bar for i32 {} + +// cannot use special rustc_on_unimplement symbols +// in the format string +#[diagnostic::on_unimplemented( + message = "{from_desugaring}{direct}{cause}{integral}{integer}", + //~^WARN there is no parameter `from_desugaring` on trait `Baz` + //~|WARN there is no parameter `from_desugaring` on trait `Baz` + //~|WARN there is no parameter `direct` on trait `Baz` + //~|WARN there is no parameter `direct` on trait `Baz` + //~|WARN there is no parameter `cause` on trait `Baz` + //~|WARN there is no parameter `cause` on trait `Baz` + //~|WARN there is no parameter `integral` on trait `Baz` + //~|WARN there is no parameter `integral` on trait `Baz` + //~|WARN there is no parameter `integer` on trait `Baz` + //~|WARN there is no parameter `integer` on trait `Baz` + label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + //~^WARN there is no parameter `float` on trait `Baz` + //~|WARN there is no parameter `float` on trait `Baz` + //~|WARN there is no parameter `_Self` on trait `Baz` + //~|WARN there is no parameter `_Self` on trait `Baz` + //~|WARN there is no parameter `crate_local` on trait `Baz` + //~|WARN there is no parameter `crate_local` on trait `Baz` + //~|WARN there is no parameter `Trait` on trait `Baz` + //~|WARN there is no parameter `Trait` on trait `Baz` + //~|WARN there is no parameter `ItemContext` on trait `Baz` + //~|WARN there is no parameter `ItemContext` on trait `Baz` +)] +trait Baz {} + +fn takes_foo(_: impl Foo) {} +fn takes_bar(_: impl Bar) {} +fn takes_baz(_: impl Baz) {} + +fn main() { + takes_foo(()); + //~^ERROR trait has `()` and `i32` as params + takes_bar(()); + //~^ERROR the trait bound `(): Bar` is not satisfied + takes_baz(()); + //~^ERROR {from_desugaring}{direct}{cause}{integral}{integer} +} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr new file mode 100644 index 0000000000000..75a701f0b5f65 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr @@ -0,0 +1,305 @@ +warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1 + | +LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + | +LL | on(_Self = "&str"), + | ^^^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + | +LL | parent_label = "in this scope", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + | +LL | append_const_msg + | ^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + | +LL | #[diagnostic::on_unimplemented = "Message"] + | ^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + +warning: there is no parameter `from_desugaring` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `direct` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `cause` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `integral` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `integer` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `float` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `_Self` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `crate_local` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `Trait` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `ItemContext` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + | +LL | on(_Self = "&str"), + | ^^^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + | +LL | parent_label = "in this scope", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + | +LL | append_const_msg + | ^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: trait has `()` and `i32` as params + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15 + | +LL | takes_foo(()); + | --------- ^^ trait has `()` and `i32` as params + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is not implemented for `()` + = note: trait has `()` and `i32` as params +help: this trait has no implementations, consider adding one + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1 + | +LL | trait Foo {} + | ^^^^^^^^^^^^ +note: required by a bound in `takes_foo` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22 + | +LL | fn takes_foo(_: impl Foo) {} + | ^^^^^^^^ required by this bound in `takes_foo` + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + | +LL | #[diagnostic::on_unimplemented = "Message"] + | ^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 + | +LL | takes_bar(()); + | --------- ^^ the trait `Bar` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the trait `Bar` is implemented for `i32` +note: required by a bound in `takes_bar` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22 + | +LL | fn takes_bar(_: impl Bar) {} + | ^^^ required by this bound in `takes_bar` + +warning: there is no parameter `from_desugaring` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `direct` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `cause` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `integral` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `integer` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `float` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `_Self` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `crate_local` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `Trait` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `ItemContext` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer} + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15 + | +LL | takes_baz(()); + | --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext} + | | + | required by a bound introduced by this call + | + = help: the trait `Baz` is not implemented for `()` +help: this trait has no implementations, consider adding one + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1 + | +LL | trait Baz {} + | ^^^^^^^^^ +note: required by a bound in `takes_baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22 + | +LL | fn takes_baz(_: impl Baz) {} + | ^^^ required by this bound in `takes_baz` + +error: aborting due to 3 previous errors; 29 warnings emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs index 346d8373f7398..12fe988170ac1 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs @@ -28,10 +28,16 @@ trait Doom {} //~|WARN missing options for `on_unimplemented` attribute trait Whatever {} +#[diagnostic::on_unimplemented(message = "{DoesNotExist}")] +//~^WARN there is no parameter `DoesNotExist` on trait `Test` +//~|WARN there is no parameter `DoesNotExist` on trait `Test` +trait Test {} + fn take_foo(_: impl Foo) {} fn take_baz(_: impl Baz) {} fn take_boom(_: impl Boom) {} fn take_whatever(_: impl Whatever) {} +fn take_test(_: impl Test) {} fn main() { take_foo(1_i32); @@ -42,4 +48,6 @@ fn main() { //~^ERROR Boom take_whatever(1_i32); //~^ERROR the trait bound `i32: Whatever` is not satisfied + take_test(()); + //~^ERROR {DoesNotExist} } diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr index 162ddd79fbbd9..11263580b15e2 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr @@ -46,6 +46,14 @@ LL | #[diagnostic::on_unimplemented] | = help: at least one of the `message`, `note` and `label` options are expected +warning: there is no parameter `DoesNotExist` on trait `Test` + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + | +LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + warning: malformed `on_unimplemented` attribute --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32 | @@ -56,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 | LL | take_foo(1_i32); | -------- ^^^^^ the trait `Foo` is not implemented for `i32` @@ -69,7 +77,7 @@ help: this trait has no implementations, consider adding one LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `take_foo` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21 | LL | fn take_foo(_: impl Foo) {} | ^^^ required by this bound in `take_foo` @@ -84,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14 | LL | take_baz(1_i32); | -------- ^^^^^ the trait `Baz` is not implemented for `i32` @@ -97,7 +105,7 @@ help: this trait has no implementations, consider adding one LL | trait Baz {} | ^^^^^^^^^ note: required by a bound in `take_baz` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21 | LL | fn take_baz(_: impl Baz) {} | ^^^ required by this bound in `take_baz` @@ -112,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:15 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15 | LL | take_boom(1_i32); | --------- ^^^^^ the trait `Boom` is not implemented for `i32` @@ -125,7 +133,7 @@ help: this trait has no implementations, consider adding one LL | trait Boom {} | ^^^^^^^^^^ note: required by a bound in `take_boom` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:33:22 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 | LL | fn take_boom(_: impl Boom) {} | ^^^^ required by this bound in `take_boom` @@ -140,7 +148,7 @@ LL | #[diagnostic::on_unimplemented] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Whatever` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:19 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19 | LL | take_whatever(1_i32); | ------------- ^^^^^ the trait `Whatever` is not implemented for `i32` @@ -153,11 +161,39 @@ help: this trait has no implementations, consider adding one LL | trait Whatever {} | ^^^^^^^^^^^^^^ note: required by a bound in `take_whatever` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:26 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26 | LL | fn take_whatever(_: impl Whatever) {} | ^^^^^^^^ required by this bound in `take_whatever` -error: aborting due to 4 previous errors; 10 warnings emitted +warning: there is no parameter `DoesNotExist` on trait `Test` + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + | +LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: {DoesNotExist} + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15 + | +LL | take_test(()); + | --------- ^^ the trait `Test` is not implemented for `()` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1 + | +LL | trait Test {} + | ^^^^^^^^^^ +note: required by a bound in `take_test` + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22 + | +LL | fn take_test(_: impl Test) {} + | ^^^^ required by this bound in `take_test` + +error: aborting due to 5 previous errors; 12 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/packed/issue-118537-field-offset-ice.rs b/tests/ui/packed/issue-118537-field-offset-ice.rs new file mode 100644 index 0000000000000..657aec640032b --- /dev/null +++ b/tests/ui/packed/issue-118537-field-offset-ice.rs @@ -0,0 +1,39 @@ +// run-pass +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed(4))] +struct Slice([u32]); + +#[repr(packed(2), C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed(2), C)] +struct PackedUnsized { + f: u8, + d: Slice, +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation correctly adds exact 1 byte of padding + // in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); +} } diff --git a/tests/ui/packed/issue-118537-field-offset.rs b/tests/ui/packed/issue-118537-field-offset.rs new file mode 100644 index 0000000000000..cd17f7679470e --- /dev/null +++ b/tests/ui/packed/issue-118537-field-offset.rs @@ -0,0 +1,36 @@ +// run-pass +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed, C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed, C)] +struct PackedUnsized { + f: u8, + d: [u32], +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation does *not* think there is + // any padding in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 4*4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); +} }