diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 7857ccb613bf8..915dd3d9eda15 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -36,17 +36,17 @@ impl ArgAttributeExt for ArgAttribute { where F: FnMut(llvm::Attribute), { - for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg) + for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, InReg) } } pub trait ArgAttributesExt { - fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>); - fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>); + fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value); + fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value); } impl ArgAttributesExt for ArgAttributes { - fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) { + fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -61,14 +61,20 @@ impl ArgAttributesExt for ArgAttributes { if let Some(align) = self.pointee_align { llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32); } - if regular.contains(ArgAttribute::ByVal) { - llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap()); - } regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); + match self.arg_ext { + ArgExtension::None => {} + ArgExtension::Zext => { + llvm::Attribute::ZExt.apply_llfn(idx, llfn); + } + ArgExtension::Sext => { + llvm::Attribute::SExt.apply_llfn(idx, llfn); + } + } } } - fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) { + fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -91,10 +97,16 @@ impl ArgAttributesExt for ArgAttributes { align.bytes() as u32, ); } - if regular.contains(ArgAttribute::ByVal) { - llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap()); - } regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); + match self.arg_ext { + ArgExtension::None => {} + ArgExtension::Zext => { + llvm::Attribute::ZExt.apply_callsite(idx, callsite); + } + ArgExtension::Sext => { + llvm::Attribute::SExt.apply_callsite(idx, callsite); + } + } } } } @@ -146,7 +158,7 @@ impl LlvmType for CastTarget { .prefix .iter() .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind, size: self.prefix_chunk }.llvm_type(cx)) + option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.llvm_type(cx)) }) .chain((0..rest_count).map(|_| rest_ll_unit)) .collect(); @@ -267,10 +279,12 @@ impl ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { PassMode::Pair(..) => { OperandValue::Pair(next(), next()).store(bx, dst); } - PassMode::Indirect(_, Some(_)) => { + PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst); } - PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => { + PassMode::Direct(_) + | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } + | PassMode::Cast(_) => { let next_arg = next(); self.store(bx, next_arg, dst); } @@ -315,14 +329,14 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 } ).sum(); let mut llargument_tys = Vec::with_capacity( - if let PassMode::Indirect(..) = self.ret.mode { 1 } else { 0 } + args_capacity, + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 } + args_capacity, ); let llreturn_ty = match self.ret.mode { PassMode::Ignore => cx.type_void(), PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx), PassMode::Cast(cast) => cast.llvm_type(cx), - PassMode::Indirect(..) => { + PassMode::Indirect { .. } => { llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx))); cx.type_void() } @@ -342,7 +356,7 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } - PassMode::Indirect(_, Some(_)) => { + PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { let ptr_ty = cx.tcx.mk_mut_ptr(arg.layout.ty); let ptr_layout = cx.layout_of(ptr_ty); llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true)); @@ -350,7 +364,9 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { continue; } PassMode::Cast(cast) => cast.llvm_type(cx), - PassMode::Indirect(_, None) => cx.type_ptr_to(arg.memory_ty(cx)), + PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { + cx.type_ptr_to(arg.memory_ty(cx)) + } }; llargument_tys.push(llarg_ty); } @@ -402,35 +418,54 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } let mut i = 0; - let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| { - attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty); + let mut apply = |attrs: &ArgAttributes| { + attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), llfn); i += 1; + i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None); + attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, llfn); + } + PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { + assert!(!on_stack); + let i = apply(attrs); + llvm::Attribute::StructRet.apply_llfn(llvm::AttributePlace::Argument(i), llfn); } - PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))), _ => {} } for arg in &self.args { if arg.pad.is_some() { - apply(&ArgAttributes::new(), None); + apply(&ArgAttributes::new()); } match arg.mode { PassMode::Ignore => {} - PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => { - apply(attrs, Some(arg.layout.llvm_type(cx))) + PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => { + let i = apply(attrs); + unsafe { + llvm::LLVMRustAddByValAttr( + llfn, + llvm::AttributePlace::Argument(i).as_uint(), + arg.layout.llvm_type(cx), + ); + } } - PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { - apply(attrs, None); - apply(extra_attrs, None); + PassMode::Direct(ref attrs) + | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => { + apply(attrs); + } + PassMode::Indirect { ref attrs, extra_attrs: Some(ref extra_attrs), on_stack } => { + assert!(!on_stack); + apply(attrs); + apply(extra_attrs); } PassMode::Pair(ref a, ref b) => { - apply(a, None); - apply(b, None); + apply(a); + apply(b); + } + PassMode::Cast(_) => { + apply(&ArgAttributes::new()); } - PassMode::Cast(_) => apply(&ArgAttributes::new(), None), } } } @@ -439,15 +474,21 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite. let mut i = 0; - let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| { - attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty); + let mut apply = |attrs: &ArgAttributes| { + attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), callsite); i += 1; + i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None); + attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, callsite); + } + PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { + assert!(!on_stack); + let i = apply(attrs); + llvm::Attribute::StructRet + .apply_callsite(llvm::AttributePlace::Argument(i), callsite); } - PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))), _ => {} } if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi { @@ -465,22 +506,39 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } for arg in &self.args { if arg.pad.is_some() { - apply(&ArgAttributes::new(), None); + apply(&ArgAttributes::new()); } match arg.mode { PassMode::Ignore => {} - PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => { - apply(attrs, Some(arg.layout.llvm_type(bx))) + PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => { + let i = apply(attrs); + unsafe { + llvm::LLVMRustAddByValCallSiteAttr( + callsite, + llvm::AttributePlace::Argument(i).as_uint(), + arg.layout.llvm_type(bx), + ); + } } - PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { - apply(attrs, None); - apply(extra_attrs, None); + PassMode::Direct(ref attrs) + | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => { + apply(attrs); + } + PassMode::Indirect { + ref attrs, + extra_attrs: Some(ref extra_attrs), + on_stack: _, + } => { + apply(attrs); + apply(extra_attrs); } PassMode::Pair(ref a, ref b) => { - apply(a, None); - apply(b, None); + apply(a); + apply(b); + } + PassMode::Cast(_) => { + apply(&ArgAttributes::new()); } - PassMode::Cast(_) => apply(&ArgAttributes::new(), None), } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index ee40095883ded..fd20709f5d80f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -255,7 +255,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } let llval = match self.fn_abi.ret.mode { - PassMode::Ignore | PassMode::Indirect(..) => { + PassMode::Ignore | PassMode::Indirect { .. } => { bx.ret_void(); return; } @@ -1101,7 +1101,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Force by-ref if we have to load through a cast pointer. let (mut llval, align, by_ref) = match op.val { Immediate(_) | Pair(..) => match arg.mode { - PassMode::Indirect(..) | PassMode::Cast(_) => { + PassMode::Indirect { .. } | PassMode::Cast(_) => { let scratch = PlaceRef::alloca(bx, arg.layout); op.val.store(bx, scratch); (scratch.llval, scratch.align, true) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index c544761255534..e49e456792b0d 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1286,6 +1286,7 @@ pub fn init_env_logger(env: &str) { } let filter = tracing_subscriber::EnvFilter::from_env(env); let layer = tracing_tree::HierarchicalLayer::default() + .with_writer(io::stderr) .with_indent_lines(true) .with_ansi(true) .with_targets(true) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a1df1a63fc58d..19340dd51de14 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -947,7 +947,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - self.root.tables.ty.get(self, id).unwrap().decode((self, tcx)) + self.root + .tables + .ty + .get(self, id) + .unwrap_or_else(|| panic!("Not a type: {:?}", id)) + .decode((self, tcx)) } fn get_stability(&self, id: DefIndex) -> Option { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 5626c864fe175..fa0711193df48 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -15,7 +15,7 @@ use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ - ArgAbi, ArgAttribute, ArgAttributes, Conv, FnAbi, PassMode, Reg, RegKind, + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, }; use rustc_target::abi::*; use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy}; @@ -2619,7 +2619,7 @@ where is_return: bool| { // Booleans are always an i1 that needs to be zero-extended. if scalar.is_bool() { - attrs.set(ArgAttribute::ZExt); + attrs.ext(ArgExtension::Zext); return; } @@ -2801,9 +2801,6 @@ where for arg in &mut self.args { fixup(arg, false); } - if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode { - attrs.set(ArgAttribute::StructRet); - } return; } diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index d3b6d706337ed..f666a89ca56de 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -75,13 +75,35 @@ crate fn eval_nullary_intrinsic<'tcx>( ensure_monomorphic_enough(tcx, tp_ty)?; ConstValue::from_u64(tcx.type_id_hash(tp_ty)) } - sym::variant_count => { - if let ty::Adt(ref adt, _) = tp_ty.kind() { - ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx) - } else { - ConstValue::from_machine_usize(0u64, &tcx) - } - } + sym::variant_count => match tp_ty.kind() { + ty::Adt(ref adt, _) => ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx), + ty::Projection(_) + | ty::Opaque(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) + | ty::Infer(_) => throw_inval!(TooGeneric), + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_) + | ty::Dynamic(_, _) + | ty::Closure(_, _) + | ty::Generator(_, _, _) + | ty::GeneratorWitness(_) + | ty::Never + | ty::Tuple(_) + | ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx), + }, other => bug!("`{}` is not a zero arg intrinsic", other), }) } diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs index 3a1fa0018c104..aa5835686a291 100644 --- a/compiler/rustc_mir/src/shim.rs +++ b/compiler/rustc_mir/src/shim.rs @@ -308,10 +308,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - match self_ty.kind() { _ if is_copy => builder.copy_shim(), - ty::Array(ty, len) => { - let len = len.eval_usize(tcx, param_env); - builder.array_shim(dest, src, ty, len) - } + ty::Array(ty, len) => builder.array_shim(dest, src, ty, len), ty::Closure(_, substs) => { builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys()) } @@ -485,7 +482,13 @@ impl CloneShimBuilder<'tcx> { } } - fn array_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, ty: Ty<'tcx>, len: u64) { + fn array_shim( + &mut self, + dest: Place<'tcx>, + src: Place<'tcx>, + ty: Ty<'tcx>, + len: &'tcx ty::Const<'tcx>, + ) { let tcx = self.tcx; let span = self.span; @@ -503,7 +506,11 @@ impl CloneShimBuilder<'tcx> { ))), self.make_statement(StatementKind::Assign(box ( end, - Rvalue::Use(Operand::Constant(self.make_usize(len))), + Rvalue::Use(Operand::Constant(box Constant { + span: self.span, + user_ty: None, + literal: len, + })), ))), ]; self.block(inits, TerminatorKind::Goto { target: BasicBlock::new(1) }, false); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index c1d3210b61768..5fed500390b68 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -33,11 +33,11 @@ pub struct QueryInfo { pub(crate) type QueryMap = FxHashMap, QueryJobInfo>; -/// A value uniquely identifiying an active query job within a shard in the query cache. +/// A value uniquely identifying an active query job within a shard in the query cache. #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct QueryShardJobId(pub NonZeroU32); -/// A value uniquely identifiying an active query job. +/// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct QueryJobId { /// Which job within a shard is this @@ -536,7 +536,7 @@ fn remove_cycle( }; // We unwrap `waiter` here since there must always be one - // edge which is resumeable / waited using a query latch + // edge which is resumable / waited using a query latch let (waitee_query, waiter_idx) = waiter.unwrap(); // Extract the waiter we want to resume diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 917dd104d1496..a630c84142b4d 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -1,4 +1,4 @@ -use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { @@ -7,7 +7,7 @@ fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { if let abi::Int(i, signed) = scalar.value { if !signed && i.size().bits() == 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { - attrs.set(ArgAttribute::SExt); + attrs.ext(ArgExtension::Sext); return; } } @@ -137,7 +137,7 @@ where let rest_size = size - Size::from_bytes(8) * prefix_index as u64; arg.cast_to(CastTarget { prefix, - prefix_chunk: Size::from_bytes(8), + prefix_chunk_size: Size::from_bytes(8), rest: Uniform { unit: Reg::i64(), total: rest_size }, }); } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 429a3375cd893..5de9a8dfa7ac1 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -36,9 +36,12 @@ pub enum PassMode { /// a single uniform or a pair of registers. Cast(CastTarget), /// Pass the argument indirectly via a hidden pointer. - /// The second value, if any, is for the extra data (vtable or length) + /// The `extra_attrs` value, if any, is for the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. - Indirect(ArgAttributes, Option), + /// `on_stack` defines that the the value should be passed at a fixed + /// stack offset in accordance to the ABI rather than passed using a + /// pointer. This corresponds to the `byval` LLVM argument attribute. + Indirect { attrs: ArgAttributes, extra_attrs: Option, on_stack: bool }, } // Hack to disable non_upper_case_globals only for the bitflags! and not for the rest @@ -52,24 +55,31 @@ mod attr_impl { bitflags::bitflags! { #[derive(Default)] pub struct ArgAttribute: u16 { - const ByVal = 1 << 0; const NoAlias = 1 << 1; const NoCapture = 1 << 2; const NonNull = 1 << 3; const ReadOnly = 1 << 4; - const SExt = 1 << 5; - const StructRet = 1 << 6; - const ZExt = 1 << 7; const InReg = 1 << 8; } } } +/// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum +/// defines if this extension should be zero-extension or sign-extension when necssary. When it is +/// not necesary to extend the argument, this enum is ignored. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum ArgExtension { + None, + Zext, + Sext, +} + /// A compact representation of LLVM attributes (at least those relevant for this module) /// that can be manipulated without interacting with LLVM's Attribute machinery. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct ArgAttributes { pub regular: ArgAttribute, + pub arg_ext: ArgExtension, /// The minimum size of the pointee, guaranteed to be valid for the duration of the whole call /// (corresponding to LLVM's dereferenceable and dereferenceable_or_null attributes). pub pointee_size: Size, @@ -80,11 +90,18 @@ impl ArgAttributes { pub fn new() -> Self { ArgAttributes { regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, pointee_size: Size::ZERO, pointee_align: None, } } + pub fn ext(&mut self, ext: ArgExtension) -> &mut Self { + assert!(self.arg_ext == ArgExtension::None || self.arg_ext == ext); + self.arg_ext = ext; + self + } + pub fn set(&mut self, attr: ArgAttribute) -> &mut Self { self.regular |= attr; self @@ -180,7 +197,7 @@ impl Uniform { #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct CastTarget { pub prefix: [Option; 8], - pub prefix_chunk: Size, + pub prefix_chunk_size: Size, pub rest: Uniform, } @@ -192,7 +209,7 @@ impl From for CastTarget { impl From for CastTarget { fn from(uniform: Uniform) -> CastTarget { - CastTarget { prefix: [None; 8], prefix_chunk: Size::ZERO, rest: uniform } + CastTarget { prefix: [None; 8], prefix_chunk_size: Size::ZERO, rest: uniform } } } @@ -200,13 +217,13 @@ impl CastTarget { pub fn pair(a: Reg, b: Reg) -> CastTarget { CastTarget { prefix: [Some(a.kind), None, None, None, None, None, None, None], - prefix_chunk: a.size, + prefix_chunk_size: a.size, rest: Uniform::from(b), } } pub fn size(&self, cx: &C) -> Size { - (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64) + (self.prefix_chunk_size * self.prefix.iter().filter(|x| x.is_some()).count() as u64) .align_to(self.rest.align(cx)) + self.rest.total } @@ -214,7 +231,7 @@ impl CastTarget { pub fn align(&self, cx: &C) -> Align { self.prefix .iter() - .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk }.align(cx))) + .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk_size }.align(cx))) .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)), |acc, align| { acc.max(align) }) @@ -438,14 +455,14 @@ impl<'a, Ty> ArgAbi<'a, Ty> { let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new()); - self.mode = PassMode::Indirect(attrs, extra_attrs); + self.mode = PassMode::Indirect { attrs, extra_attrs, on_stack: false }; } pub fn make_indirect_byval(&mut self) { self.make_indirect(); match self.mode { - PassMode::Indirect(ref mut attrs, _) => { - attrs.set(ArgAttribute::ByVal); + PassMode::Indirect { attrs: _, extra_attrs: _, ref mut on_stack } => { + *on_stack = true; } _ => unreachable!(), } @@ -457,7 +474,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> { if let abi::Int(i, signed) = scalar.value { if i.size().bits() < bits { if let PassMode::Direct(ref mut attrs) = self.mode { - attrs.set(if signed { ArgAttribute::SExt } else { ArgAttribute::ZExt }); + if signed { + attrs.ext(ArgExtension::Sext) + } else { + attrs.ext(ArgExtension::Zext) + }; } } } @@ -474,15 +495,15 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } pub fn is_indirect(&self) -> bool { - matches!(self.mode, PassMode::Indirect(..)) + matches!(self.mode, PassMode::Indirect {..}) } pub fn is_sized_indirect(&self) -> bool { - matches!(self.mode, PassMode::Indirect(_, None)) + matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ }) } pub fn is_unsized_indirect(&self) -> bool { - matches!(self.mode, PassMode::Indirect(_, Some(_))) + matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ }) } pub fn is_ignore(&self) -> bool { @@ -591,10 +612,6 @@ impl<'a, Ty> FnAbi<'a, Ty> { a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), } - if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode { - attrs.set(ArgAttribute::StructRet); - } - Ok(()) } } diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index 782c661c31fdb..1ab881dd13d1c 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -4,7 +4,7 @@ // Reference: Clang RISC-V ELF psABI lowering code // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773 -use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::{ self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods, }; @@ -308,7 +308,7 @@ fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { // 32-bit integers are always sign-extended if i.size().bits() == 32 && xlen > 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { - attrs.set(ArgAttribute::SExt); + attrs.ext(ArgExtension::Sext); return; } } diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index 07bf1e94c617e..713b4100a3335 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -92,9 +92,14 @@ where for arg in &mut fn_abi.args { let attrs = match arg.mode { - PassMode::Ignore | PassMode::Indirect(_, None) => continue, + PassMode::Ignore + | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { + continue; + } PassMode::Direct(ref mut attrs) => attrs, - PassMode::Pair(..) | PassMode::Indirect(_, Some(_)) | PassMode::Cast(_) => { + PassMode::Pair(..) + | PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } + | PassMode::Cast(_) => { unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode) } }; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 1512235da6a81..b9490c44f4b25 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -62,6 +62,13 @@ //! T` obtained from [`Box::::into_raw`] may be deallocated using the //! [`Global`] allocator with [`Layout::for_value(&*value)`]. //! +//! For zero-sized values, the `Box` pointer still has to be [valid] for reads +//! and writes and sufficiently aligned. In particular, casting any aligned +//! non-zero integer literal to a raw pointer produces a valid pointer, but a +//! pointer pointing into previously allocated memory that since got freed is +//! not valid. The recommended way to build a Box to a ZST if `Box::new` cannot +//! be used is to use [`ptr::NonNull::dangling`]. +//! //! So long as `T: Sized`, a `Box` is guaranteed to be represented //! as a single pointer and is also ABI-compatible with C pointers //! (i.e. the C type `T*`). This means that if you have extern "C" @@ -125,6 +132,7 @@ //! [`Global`]: crate::alloc::Global //! [`Layout`]: crate::alloc::Layout //! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value +//! [valid]: ptr#safety #![stable(feature = "rust1", since = "1.0.0")] @@ -530,7 +538,10 @@ impl Box { /// memory problems. For example, a double-free may occur if the /// function is called twice on the same raw pointer. /// + /// The safety conditions are described in the [memory layout] section. + /// /// # Examples + /// /// Recreate a `Box` which was previously converted to a raw pointer /// using [`Box::into_raw`]: /// ``` diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 9de2758767e3e..27d49529a5ec2 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -16,12 +16,16 @@ //! provided at this point are very minimal: //! //! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst]. -//! * All pointers (except for the null pointer) are valid for all operations of -//! [size zero][zst]. //! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer //! be *dereferenceable*: the memory range of the given size starting at the pointer must all be //! within the bounds of a single allocated object. Note that in Rust, //! every (stack-allocated) variable is considered a separate allocated object. +//! * Even for operations of [size zero][zst], the pointer must not be pointing to deallocated +//! memory, i.e., deallocation makes pointers invalid even for zero-sized operations. However, +//! casting any non-zero integer *literal* to a pointer is valid for zero-sized accesses, even if +//! some memory happens to exist at that address and gets deallocated. This corresponds to writing +//! your own allocator: allocating zero-sized objects is not very hard. The canonical way to +//! obtain a pointer that is valid for zero-sized accesses is [`NonNull::dangling`]. //! * All accesses performed by functions in this module are *non-atomic* in the sense //! of [atomic operations] used to synchronize between threads. This means it is //! undefined behavior to perform two concurrent accesses to the same location from different diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9d84089eb405c..d58a88957df22 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -231,21 +231,14 @@ impl Clean for doctree::Module<'_> { let mut items: Vec = vec![]; items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx))); items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); - items.extend(self.structs.iter().map(|x| x.clean(cx))); - items.extend(self.unions.iter().map(|x| x.clean(cx))); - items.extend(self.enums.iter().map(|x| x.clean(cx))); items.extend(self.fns.iter().map(|x| x.clean(cx))); items.extend(self.foreigns.iter().map(|x| x.clean(cx))); items.extend(self.mods.iter().map(|x| x.clean(cx))); - items.extend(self.typedefs.iter().map(|x| x.clean(cx))); - items.extend(self.opaque_tys.iter().map(|x| x.clean(cx))); - items.extend(self.statics.iter().map(|x| x.clean(cx))); - items.extend(self.constants.iter().map(|x| x.clean(cx))); + items.extend(self.items.iter().map(|x| x.clean(cx))); items.extend(self.traits.iter().map(|x| x.clean(cx))); items.extend(self.impls.iter().flat_map(|x| x.clean(cx))); items.extend(self.macros.iter().map(|x| x.clean(cx))); items.extend(self.proc_macros.iter().map(|x| x.clean(cx))); - items.extend(self.trait_aliases.iter().map(|x| x.clean(cx))); // determine if we should display the inner contents or // the outer `mod` item for the source code. @@ -1020,20 +1013,6 @@ impl Clean for doctree::Trait<'_> { } } -impl Clean for doctree::TraitAlias<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - TraitAliasItem(TraitAlias { - generics: self.generics.clean(cx), - bounds: self.bounds.clean(cx), - }), - cx, - ) - } -} - impl Clean for hir::IsAuto { fn clean(&self, _: &DocContext<'_>) -> bool { match *self { @@ -1777,38 +1756,6 @@ impl Clean for ty::Visibility { } } -impl Clean for doctree::Struct<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - StructItem(Struct { - struct_type: self.struct_type, - generics: self.generics.clean(cx), - fields: self.fields.clean(cx), - fields_stripped: false, - }), - cx, - ) - } -} - -impl Clean for doctree::Union<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - UnionItem(Union { - struct_type: self.struct_type, - generics: self.generics.clean(cx), - fields: self.fields.clean(cx), - fields_stripped: false, - }), - cx, - ) - } -} - impl Clean for rustc_hir::VariantData<'_> { fn clean(&self, cx: &DocContext<'_>) -> VariantStruct { VariantStruct { @@ -1819,21 +1766,6 @@ impl Clean for rustc_hir::VariantData<'_> { } } -impl Clean for doctree::Enum<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - EnumItem(Enum { - variants: self.variants.iter().map(|v| v.clean(cx)).collect(), - generics: self.generics.clean(cx), - variants_stripped: false, - }), - cx, - ) - } -} - impl Clean for doctree::Variant<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let what_rustc_thinks = Item::from_hir_id_and_parts( @@ -1981,33 +1913,6 @@ impl Clean for Symbol { } } -impl Clean for doctree::Typedef<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - let type_ = self.ty.clean(cx); - let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false), - cx, - ) - } -} - -impl Clean for doctree::OpaqueTy<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - OpaqueTyItem(OpaqueTy { - bounds: self.opaque_ty.bounds.clean(cx), - generics: self.opaque_ty.generics.clean(cx), - }), - cx, - ) - } -} - impl Clean for hir::BareFnTy<'_> { fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, || { @@ -2017,37 +1922,75 @@ impl Clean for hir::BareFnTy<'_> { } } -impl Clean for doctree::Static<'_> { +impl Clean for (&hir::Item<'_>, Option) { fn clean(&self, cx: &DocContext<'_>) -> Item { - debug!("cleaning static {}: {:?}", self.name.clean(cx), self); - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - StaticItem(Static { - type_: self.type_.clean(cx), - mutability: self.mutability, - expr: print_const_expr(cx, self.expr), + use hir::ItemKind; + + let (item, renamed) = self; + let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id(); + let name = match renamed { + Some(ident) => ident.name, + None => cx.tcx.hir().name(item.hir_id), + }; + let kind = match item.kind { + ItemKind::Static(ty, mutability, body_id) => StaticItem(Static { + type_: ty.clean(cx), + mutability, + expr: print_const_expr(cx, body_id), }), - cx, - ) + ItemKind::Const(ty, body_id) => ConstantItem(Constant { + type_: ty.clean(cx), + expr: print_const_expr(cx, body_id), + value: print_evaluated_const(cx, def_id), + is_literal: is_literal_expr(cx, body_id.hir_id), + }), + ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { + bounds: ty.bounds.clean(cx), + generics: ty.generics.clean(cx), + }), + ItemKind::TyAlias(ty, ref generics) => { + let rustdoc_ty = ty.clean(cx); + let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did)); + TypedefItem( + Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type }, + false, + ) + } + ItemKind::Enum(ref def, ref generics) => EnumItem(Enum { + variants: def.variants.iter().map(|v| v.clean(cx)).collect(), + generics: generics.clean(cx), + variants_stripped: false, + }), + ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias { + generics: generics.clean(cx), + bounds: bounds.clean(cx), + }), + ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union { + struct_type: doctree::struct_type_from_def(&variant_data), + generics: generics.clean(cx), + fields: variant_data.fields().clean(cx), + fields_stripped: false, + }), + ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct { + struct_type: doctree::struct_type_from_def(&variant_data), + generics: generics.clean(cx), + fields: variant_data.fields().clean(cx), + fields_stripped: false, + }), + _ => unreachable!("not yet converted"), + }; + + Item::from_def_id_and_parts(def_id, Some(name), kind, cx) } } -impl Clean for doctree::Constant<'_> { +impl Clean for hir::Variant<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { - let def_id = cx.tcx.hir().local_def_id(self.id).to_def_id(); - - Item::from_def_id_and_parts( - def_id, - Some(self.name), - ConstantItem(Constant { - type_: self.type_.clean(cx), - expr: print_const_expr(cx, self.expr), - value: print_evaluated_const(cx, def_id), - is_literal: is_literal_expr(cx, self.expr.hir_id), - }), - cx, - ) + let kind = VariantItem(Variant { kind: self.data.clean(cx) }); + let what_rustc_thinks = + Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx); + // don't show `pub` for variants, which are always public + Item { visibility: Inherited, ..what_rustc_thinks } } } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index bd9262191356f..d56328cc2aa08 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -4,7 +4,7 @@ crate use self::StructType::*; use rustc_ast as ast; use rustc_span::hygiene::MacroKind; -use rustc_span::{self, Span, Symbol}; +use rustc_span::{self, symbol::Ident, Span, Symbol}; use rustc_hir as hir; use rustc_hir::def_id::CrateNum; @@ -17,22 +17,16 @@ crate struct Module<'hir> { crate where_inner: Span, crate extern_crates: Vec>, crate imports: Vec>, - crate structs: Vec>, - crate unions: Vec>, - crate enums: Vec>, crate fns: Vec>, crate mods: Vec>, crate id: hir::HirId, - crate typedefs: Vec>, - crate opaque_tys: Vec>, - crate statics: Vec>, - crate constants: Vec>, + // (item, renamed) + crate items: Vec<(&'hir hir::Item<'hir>, Option)>, crate traits: Vec>, crate impls: Vec>, crate foreigns: Vec>, crate macros: Vec, crate proc_macros: Vec, - crate trait_aliases: Vec>, crate is_crate: bool, } @@ -46,21 +40,14 @@ impl Module<'hir> { attrs, extern_crates: Vec::new(), imports: Vec::new(), - structs: Vec::new(), - unions: Vec::new(), - enums: Vec::new(), fns: Vec::new(), mods: Vec::new(), - typedefs: Vec::new(), - opaque_tys: Vec::new(), - statics: Vec::new(), - constants: Vec::new(), + items: Vec::new(), traits: Vec::new(), impls: Vec::new(), foreigns: Vec::new(), macros: Vec::new(), proc_macros: Vec::new(), - trait_aliases: Vec::new(), is_crate: false, } } @@ -76,29 +63,6 @@ crate enum StructType { Unit, } -crate struct Struct<'hir> { - crate id: hir::HirId, - crate struct_type: StructType, - crate name: Symbol, - crate generics: &'hir hir::Generics<'hir>, - crate fields: &'hir [hir::StructField<'hir>], -} - -crate struct Union<'hir> { - crate id: hir::HirId, - crate struct_type: StructType, - crate name: Symbol, - crate generics: &'hir hir::Generics<'hir>, - crate fields: &'hir [hir::StructField<'hir>], -} - -crate struct Enum<'hir> { - crate variants: Vec>, - crate generics: &'hir hir::Generics<'hir>, - crate id: hir::HirId, - crate name: Symbol, -} - crate struct Variant<'hir> { crate name: Symbol, crate id: hir::HirId, @@ -114,38 +78,6 @@ crate struct Function<'hir> { crate body: hir::BodyId, } -crate struct Typedef<'hir> { - crate ty: &'hir hir::Ty<'hir>, - crate gen: &'hir hir::Generics<'hir>, - crate name: Symbol, - crate id: hir::HirId, -} - -crate struct OpaqueTy<'hir> { - crate opaque_ty: &'hir hir::OpaqueTy<'hir>, - crate name: Symbol, - crate id: hir::HirId, -} - -#[derive(Debug)] -crate struct Static<'hir> { - crate type_: &'hir hir::Ty<'hir>, - crate mutability: hir::Mutability, - crate expr: hir::BodyId, - crate name: Symbol, - crate attrs: &'hir [ast::Attribute], - crate vis: &'hir hir::Visibility<'hir>, - crate id: hir::HirId, - crate span: Span, -} - -crate struct Constant<'hir> { - crate type_: &'hir hir::Ty<'hir>, - crate expr: hir::BodyId, - crate name: Symbol, - crate id: hir::HirId, -} - crate struct Trait<'hir> { crate is_auto: hir::IsAuto, crate unsafety: hir::Unsafety, @@ -157,13 +89,6 @@ crate struct Trait<'hir> { crate id: hir::HirId, } -crate struct TraitAlias<'hir> { - crate name: Symbol, - crate generics: &'hir hir::Generics<'hir>, - crate bounds: &'hir [hir::GenericBound<'hir>], - crate id: hir::HirId, -} - #[derive(Debug)] crate struct Impl<'hir> { crate unsafety: hir::Unsafety, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 895414b1d7e4c..fd09ba04b3db9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -492,7 +492,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { Res::PrimTy(prim) => Some( self.resolve_primitive_associated_item(prim, ns, module_id, item_name, item_str), ), - Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias, did) => { + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::TyAlias + | DefKind::ForeignTy, + did, + ) => { debug!("looking for associated item named {} for item {:?}", item_name, did); // Checks if item_name belongs to `impl SomeItem` let assoc_item = cx diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 76fae11291805..c55e5f7690c14 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -82,50 +82,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { module } - fn visit_variant_data( - &mut self, - item: &'tcx hir::Item<'_>, - name: Symbol, - sd: &'tcx hir::VariantData<'_>, - generics: &'tcx hir::Generics<'_>, - ) -> Struct<'tcx> { - debug!("visiting struct"); - let struct_type = struct_type_from_def(&*sd); - Struct { id: item.hir_id, struct_type, name, generics, fields: sd.fields() } - } - - fn visit_union_data( - &mut self, - item: &'tcx hir::Item<'_>, - name: Symbol, - sd: &'tcx hir::VariantData<'_>, - generics: &'tcx hir::Generics<'_>, - ) -> Union<'tcx> { - debug!("visiting union"); - let struct_type = struct_type_from_def(&*sd); - Union { id: item.hir_id, struct_type, name, generics, fields: sd.fields() } - } - - fn visit_enum_def( - &mut self, - it: &'tcx hir::Item<'_>, - name: Symbol, - def: &'tcx hir::EnumDef<'_>, - generics: &'tcx hir::Generics<'_>, - ) -> Enum<'tcx> { - debug!("visiting enum"); - Enum { - name, - variants: def - .variants - .iter() - .map(|v| Variant { name: v.ident.name, id: v.id, def: &v.data }) - .collect(), - generics, - id: it.hir_id, - } - } - fn visit_fn( &mut self, om: &mut Module<'tcx>, @@ -414,45 +370,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Some(ident.name), )); } - hir::ItemKind::Enum(ref ed, ref gen) => { - om.enums.push(self.visit_enum_def(item, ident.name, ed, gen)) - } - hir::ItemKind::Struct(ref sd, ref gen) => { - om.structs.push(self.visit_variant_data(item, ident.name, sd, gen)) - } - hir::ItemKind::Union(ref sd, ref gen) => { - om.unions.push(self.visit_union_data(item, ident.name, sd, gen)) - } hir::ItemKind::Fn(ref sig, ref gen, body) => { self.visit_fn(om, item, ident.name, &sig.decl, sig.header, gen, body) } - hir::ItemKind::TyAlias(ty, ref gen) => { - let t = Typedef { ty, gen, name: ident.name, id: item.hir_id }; - om.typedefs.push(t); - } - hir::ItemKind::OpaqueTy(ref opaque_ty) => { - let t = OpaqueTy { opaque_ty, name: ident.name, id: item.hir_id }; - om.opaque_tys.push(t); - } - hir::ItemKind::Static(type_, mutability, expr) => { - let s = Static { - type_, - mutability, - expr, - id: item.hir_id, - name: ident.name, - attrs: &item.attrs, - span: item.span, - vis: &item.vis, - }; - om.statics.push(s); - } - hir::ItemKind::Const(type_, expr) => { + hir::ItemKind::Enum(..) + | hir::ItemKind::Struct(..) + | hir::ItemKind::Union(..) + | hir::ItemKind::TyAlias(..) + | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::Static(..) + | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)), + hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. if ident.name != kw::Underscore { - let s = Constant { type_, expr, id: item.hir_id, name: ident.name }; - om.constants.push(s); + om.items.push((item, renamed)); } } hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { @@ -469,11 +401,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.traits.push(t); } - hir::ItemKind::TraitAlias(ref generics, ref bounds) => { - let t = TraitAlias { name: ident.name, generics, bounds, id: item.hir_id }; - om.trait_aliases.push(t); - } - hir::ItemKind::Impl { unsafety, polarity, diff --git a/src/test/rustdoc-ui/doc-without-codeblock.stderr b/src/test/rustdoc-ui/doc-without-codeblock.stderr index f2b2328322a7b..3372304f44a3d 100644 --- a/src/test/rustdoc-ui/doc-without-codeblock.stderr +++ b/src/test/rustdoc-ui/doc-without-codeblock.stderr @@ -16,12 +16,6 @@ note: the lint level is defined here LL | #![deny(missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:3:1 - | -LL | /// Some docs. - | ^^^^^^^^^^^^^^ - error: missing code example in this documentation --> $DIR/doc-without-codeblock.rs:7:1 | @@ -34,5 +28,11 @@ error: missing code example in this documentation LL | /// Or maybe not because she saved herself! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: missing code example in this documentation + --> $DIR/doc-without-codeblock.rs:3:1 + | +LL | /// Some docs. + | ^^^^^^^^^^^^^^ + error: aborting due to 4 previous errors diff --git a/src/test/rustdoc-ui/intra-links-ambiguity.stderr b/src/test/rustdoc-ui/intra-links-ambiguity.stderr index 21b92a9673755..936055da01cf7 100644 --- a/src/test/rustdoc-ui/intra-links-ambiguity.stderr +++ b/src/test/rustdoc-ui/intra-links-ambiguity.stderr @@ -1,14 +1,29 @@ -error: `ambiguous` is both a struct and a function - --> $DIR/intra-links-ambiguity.rs:27:6 +error: `true` is both a module and a builtin type + --> $DIR/intra-links-ambiguity.rs:38:6 | -LL | /// [`ambiguous`] is ambiguous. - | ^^^^^^^^^^^ ambiguous link +LL | /// [true] + | ^^^^ ambiguous link | note: the lint level is defined here --> $DIR/intra-links-ambiguity.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: to link to the module, prefix with `mod@` + | +LL | /// [mod@true] + | ^^^^^^^^ +help: to link to the builtin type, prefix with `prim@` + | +LL | /// [prim@true] + | ^^^^^^^^^ + +error: `ambiguous` is both a struct and a function + --> $DIR/intra-links-ambiguity.rs:27:6 + | +LL | /// [`ambiguous`] is ambiguous. + | ^^^^^^^^^^^ ambiguous link + | help: to link to the struct, prefix with `struct@` | LL | /// [`struct@ambiguous`] is ambiguous. @@ -82,20 +97,5 @@ help: to link to the function, add parentheses LL | /// Ambiguous non-implied shortcut link [`foo::bar()`]. | ^^^^^^^^^^^^ -error: `true` is both a module and a builtin type - --> $DIR/intra-links-ambiguity.rs:38:6 - | -LL | /// [true] - | ^^^^ ambiguous link - | -help: to link to the module, prefix with `mod@` - | -LL | /// [mod@true] - | ^^^^^^^^ -help: to link to the builtin type, prefix with `prim@` - | -LL | /// [prim@true] - | ^^^^^^^^^ - error: aborting due to 6 previous errors diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index 4cdb8bbdde782..bf437a7cf4674 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -36,6 +36,60 @@ warning: unresolved link to `Qux::Z` LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^ no item named `Qux` in scope +warning: unresolved link to `BarA` + --> $DIR/intra-links-warning.rs:21:10 + | +LL | /// bar [BarA] bar + | ^^^^ no item named `BarA` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `BarB` + --> $DIR/intra-links-warning.rs:27:9 + | +LL | * bar [BarB] bar + | ^^^^ no item named `BarB` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `BarC` + --> $DIR/intra-links-warning.rs:34:6 + | +LL | bar [BarC] bar + | ^^^^ no item named `BarC` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `BarD` + --> $DIR/intra-links-warning.rs:45:1 + | +LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the link appears in this line: + + bar [BarD] bar + ^^^^ + = note: no item named `BarD` in scope + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `BarF` + --> $DIR/intra-links-warning.rs:50:9 + | +LL | #[doc = $f] + | ^^^^^^^^^^^ +... +LL | f!("Foo\nbar [BarF] bar\nbaz"); + | ------------------------------- in this macro invocation + | + = note: the link appears in this line: + + bar [BarF] bar + ^^^^ + = note: no item named `BarF` in scope + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + warning: unresolved link to `Qux:Y` --> $DIR/intra-links-warning.rs:14:13 | @@ -117,59 +171,5 @@ LL | /// docs [error2] | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: unresolved link to `BarA` - --> $DIR/intra-links-warning.rs:21:10 - | -LL | /// bar [BarA] bar - | ^^^^ no item named `BarA` in scope - | - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - -warning: unresolved link to `BarB` - --> $DIR/intra-links-warning.rs:27:9 - | -LL | * bar [BarB] bar - | ^^^^ no item named `BarB` in scope - | - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - -warning: unresolved link to `BarC` - --> $DIR/intra-links-warning.rs:34:6 - | -LL | bar [BarC] bar - | ^^^^ no item named `BarC` in scope - | - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - -warning: unresolved link to `BarD` - --> $DIR/intra-links-warning.rs:45:1 - | -LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the link appears in this line: - - bar [BarD] bar - ^^^^ - = note: no item named `BarD` in scope - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - -warning: unresolved link to `BarF` - --> $DIR/intra-links-warning.rs:50:9 - | -LL | #[doc = $f] - | ^^^^^^^^^^^ -... -LL | f!("Foo\nbar [BarF] bar\nbaz"); - | ------------------------------- in this macro invocation - | - = note: the link appears in this line: - - bar [BarF] bar - ^^^^ - = note: no item named `BarF` in scope - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - warning: 19 warnings emitted diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr index 32756c99e7f9f..e02ed4a056c12 100644 --- a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr @@ -1,8 +1,9 @@ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:49:1 + --> $DIR/lint-missing-doc-code-example.rs:19:1 | -LL | /// Doc - | ^^^^^^^ +LL | / mod module1 { +LL | | } + | |_^ | note: the lint level is defined here --> $DIR/lint-missing-doc-code-example.rs:2:9 @@ -11,29 +12,28 @@ LL | #![deny(missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:63:1 + --> $DIR/lint-missing-doc-code-example.rs:37:3 | -LL | /// Doc - | ^^^^^^^ +LL | /// doc + | ^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:56:1 + --> $DIR/lint-missing-doc-code-example.rs:49:1 | LL | /// Doc | ^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:19:1 + --> $DIR/lint-missing-doc-code-example.rs:56:1 | -LL | / mod module1 { -LL | | } - | |_^ +LL | /// Doc + | ^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:37:3 + --> $DIR/lint-missing-doc-code-example.rs:63:1 | -LL | /// doc - | ^^^^^^^ +LL | /// Doc + | ^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/rustdoc/intra-link-extern-type.rs b/src/test/rustdoc/intra-link-extern-type.rs new file mode 100644 index 0000000000000..418e0d91ea7ef --- /dev/null +++ b/src/test/rustdoc/intra-link-extern-type.rs @@ -0,0 +1,18 @@ +#![feature(extern_types)] + +extern { + pub type ExternType; +} + +impl ExternType { + pub fn f(&self) { + + } +} + +// @has 'intra_link_extern_type/foreigntype.ExternType.html' +// @has 'intra_link_extern_type/fn.links_to_extern_type.html' \ +// 'href="../intra_link_extern_type/foreigntype.ExternType.html#method.f"' +/// See also [ExternType::f] +pub fn links_to_extern_type() { +} diff --git a/src/test/rustdoc/redirect-rename.rs b/src/test/rustdoc/redirect-rename.rs index 7de56080e52b9..504c0687c8dc2 100644 --- a/src/test/rustdoc/redirect-rename.rs +++ b/src/test/rustdoc/redirect-rename.rs @@ -4,6 +4,10 @@ mod hidden { // @has foo/hidden/struct.Foo.html // @has - '//p/a' '../../foo/struct.FooBar.html' pub struct Foo {} + pub union U { a: usize } + pub enum Empty {} + pub const C: usize = 1; + pub static S: usize = 1; // @has foo/hidden/bar/index.html // @has - '//p/a' '../../foo/baz/index.html' @@ -16,6 +20,14 @@ mod hidden { // @has foo/struct.FooBar.html pub use hidden::Foo as FooBar; +// @has foo/union.FooU.html +pub use hidden::U as FooU; +// @has foo/enum.FooEmpty.html +pub use hidden::Empty as FooEmpty; +// @has foo/constant.FooC.html +pub use hidden::C as FooC; +// @has foo/static.FooS.html +pub use hidden::S as FooS; // @has foo/baz/index.html // @has foo/baz/struct.Thing.html diff --git a/src/test/ui/consts/issue-79137-monomorphic.rs b/src/test/ui/consts/issue-79137-monomorphic.rs new file mode 100644 index 0000000000000..58e0c387ffb9c --- /dev/null +++ b/src/test/ui/consts/issue-79137-monomorphic.rs @@ -0,0 +1,19 @@ +// check-pass + +// Verify that variant count intrinsic can still evaluate for types like `Option`. + +#![feature(variant_count)] + +pub struct GetVariantCount(T); + +impl GetVariantCount { + pub const VALUE: usize = std::mem::variant_count::(); +} + +const fn check_variant_count() -> bool { + matches!(GetVariantCount::>::VALUE, GetVariantCount::>::VALUE) +} + +fn main() { + assert!(check_variant_count::<()>()); +} diff --git a/src/test/ui/consts/issue-79137-toogeneric.rs b/src/test/ui/consts/issue-79137-toogeneric.rs new file mode 100644 index 0000000000000..456035458cfc5 --- /dev/null +++ b/src/test/ui/consts/issue-79137-toogeneric.rs @@ -0,0 +1,19 @@ +// Test that `variant_count` only gets evaluated once the type is concrete enough. + +#![feature(variant_count)] + +pub struct GetVariantCount(T); + +impl GetVariantCount { + pub const VALUE: usize = std::mem::variant_count::(); +} + +const fn check_variant_count() -> bool { + matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter +} + +fn main() { + assert!(check_variant_count::>()); +} diff --git a/src/test/ui/consts/issue-79137-toogeneric.stderr b/src/test/ui/consts/issue-79137-toogeneric.stderr new file mode 100644 index 0000000000000..579e6aa09bdbd --- /dev/null +++ b/src/test/ui/consts/issue-79137-toogeneric.stderr @@ -0,0 +1,14 @@ +error: constant pattern depends on a generic parameter + --> $DIR/issue-79137-toogeneric.rs:12:43 + | +LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/issue-79137-toogeneric.rs:12:43 + | +LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs new file mode 100644 index 0000000000000..8a96303e6b904 --- /dev/null +++ b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs @@ -0,0 +1,13 @@ +// Checks that we can build a clone shim for array with generic size. +// Regression test for issue #79269. +// +// build-pass +// compile-flags: -Zmir-opt-level=2 -Zvalidate-mir +#![feature(min_const_generics)] + +#[derive(Clone)] +struct Array([T; N]); + +fn main() { + let _ = Array([0u32, 1u32, 2u32]).clone(); +}