diff --git a/.mailmap b/.mailmap index 38ea8431e8814..d72c2e39c26a3 100644 --- a/.mailmap +++ b/.mailmap @@ -462,6 +462,8 @@ Mateusz Mikuła Mateusz Mikuła Mateusz Mikuła Mateusz Mikuła +Matilde Morrone +Matilde Morrone Matt Brubeck Matthew Auld Matthew Jasper diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index e8779d6ee6869..fa03fb87d02d1 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -11,8 +11,9 @@ use tracing::{debug, trace}; use crate::{ AbiAlign, Align, BackendLaneCount, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, - IndexVec, Integer, LayoutData, Niche, NumScalableVectors, Primitive, ReprOptions, Scalar, Size, - StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, WrappingRange, + IndexVec, Integer, LayoutData, Niche, NicheOptimizations, NumScalableVectors, Primitive, + ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, + WrappingRange, }; mod coroutine; @@ -178,7 +179,7 @@ impl LayoutCalculator { Self { cx } } - pub fn array_like( + pub fn layout_of_array_like( &self, element: &LayoutData, count_if_sized: Option, // None for slices @@ -201,7 +202,7 @@ impl LayoutCalculator { }) } - pub fn scalable_vector_type( + pub fn layout_of_scalable_vector_type( &self, element: F, count: u64, @@ -220,7 +221,7 @@ impl LayoutCalculator { ) } - pub fn simd_type( + pub fn layout_of_simd_type( &self, element: F, count: u64, @@ -239,20 +240,20 @@ impl LayoutCalculator { /// /// This uses dedicated code instead of [`Self::layout_of_struct_or_enum`], as coroutine /// fields may be shared between multiple variants (see the [`coroutine`] module for details). - pub fn coroutine< - 'a, - F: Deref> + fmt::Debug + Copy, - VariantIdx: Idx, - FieldIdx: Idx, - LocalIdx: Idx, - >( + pub fn layout_of_coroutine<'a, F, VariantIdx, FieldIdx, LocalIdx>( &self, local_layouts: &IndexSlice, prefix_layouts: IndexVec, variant_fields: &IndexSlice>, storage_conflicts: &BitMatrix, tag_to_layout: impl Fn(Scalar) -> F, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + F: Deref> + fmt::Debug + Copy, + VariantIdx: Idx, + FieldIdx: Idx, + LocalIdx: Idx, + { coroutine::layout( self, local_layouts, @@ -263,96 +264,96 @@ impl LayoutCalculator { ) } - pub fn univariant< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + /// Compute the layout for a univariant (see [`Variants::Single`]). + /// + /// As a consumer of `rustc_abi`, you should only use this method for non-ADTs. + /// For structs and univariant enums, use [`Self::layout_of_struct`] instead + /// (it uses this function internally). + pub fn layout_of_univariant<'a, FieldIdx, VariantIdx, F>( &self, fields: &IndexSlice, repr: &ReprOptions, kind: StructKind, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); - let layout = self.univariant_biased(fields, repr, kind, NicheBias::Start); + let layout = self.layout_of_univariant_biased(fields, repr, kind, NicheBias::Start); // Enums prefer niches close to the beginning or the end of the variants so that other // (smaller) data-carrying variants can be packed into the space after/before the niche. // If the default field ordering does not give us a niche at the front then we do a second // run and bias niches to the right and then check which one is closer to one of the // struct's edges. - if let Ok(layout) = &layout { + if let Ok(layout) = &layout // Don't try to calculate an end-biased layout for unsizable structs, // otherwise we could end up with different layouts for // Foo and Foo which would break unsizing. - if !matches!(kind, StructKind::MaybeUnsized) { - if let Some(niche) = layout.largest_niche { - let head_space = niche.offset.bytes(); - let niche_len = niche.value.size(dl).bytes(); - let tail_space = layout.size.bytes() - head_space - niche_len; - - // This may end up doing redundant work if the niche is already in the last - // field (e.g. a trailing bool) and there is tail padding. But it's non-trivial - // to get the unpadded size so we try anyway. - if fields.len() > 1 && head_space != 0 && tail_space > 0 { - let alt_layout = self - .univariant_biased(fields, repr, kind, NicheBias::End) - .expect("alt layout should always work"); - let alt_niche = alt_layout - .largest_niche - .expect("alt layout should have a niche like the regular one"); - let alt_head_space = alt_niche.offset.bytes(); - let alt_niche_len = alt_niche.value.size(dl).bytes(); - let alt_tail_space = - alt_layout.size.bytes() - alt_head_space - alt_niche_len; - - debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes()); - - let prefer_alt_layout = - alt_head_space > head_space && alt_head_space > tail_space; - - debug!( - "sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\ - layout: {}\n\ - alt_layout: {}\n", - layout.size.bytes(), - head_space, - niche_len, - tail_space, - alt_head_space, - alt_niche_len, - alt_tail_space, - layout.fields.count(), - prefer_alt_layout, - self.format_field_niches(layout, fields), - self.format_field_niches(&alt_layout, fields), - ); - - if prefer_alt_layout { - return Ok(alt_layout); - } - } - } + && !matches!(kind, StructKind::MaybeUnsized) + && let Some(niche) = layout.largest_niche + && let head_space = niche.offset.bytes() + && let niche_len = niche.value.size(dl).bytes() + && let tail_space = layout.size.bytes() - head_space - niche_len + // This may end up doing redundant work if the niche is already in the last + // field (e.g. a trailing bool) and there is tail padding. But it's non-trivial + // to get the unpadded size so we try anyway. + && (fields.len() > 1 && head_space != 0 && tail_space > 0) + { + let alt_layout = self + .layout_of_univariant_biased(fields, repr, kind, NicheBias::End) + .expect("alt layout should always work"); + let alt_niche = alt_layout + .largest_niche + .expect("alt layout should have a niche like the regular one"); + let alt_head_space = alt_niche.offset.bytes(); + let alt_niche_len = alt_niche.value.size(dl).bytes(); + let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len; + + debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes()); + + let prefer_alt_layout = alt_head_space > head_space && alt_head_space > tail_space; + + debug!( + "sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\ + layout: {}\n\ + alt_layout: {}\n", + layout.size.bytes(), + head_space, + niche_len, + tail_space, + alt_head_space, + alt_niche_len, + alt_tail_space, + layout.fields.count(), + prefer_alt_layout, + self.format_field_niches(layout, fields), + self.format_field_niches(&alt_layout, fields), + ); + + if prefer_alt_layout { + return Ok(alt_layout); } } layout } - pub fn layout_of_struct_or_enum< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + pub fn layout_of_struct_or_enum<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, variants: &IndexSlice>, is_enum: bool, - is_special_no_niche: bool, + niche_optimizations: NicheOptimizations, discr_range_of_repr: impl Fn(RangeFrom, RangeToInclusive) -> (Integer, bool), discriminants: impl Iterator, always_sized: bool, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let (present_first, present_second) = { let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| { if !repr.inhibit_enum_layout_opt() && absent(v) { None } else { Some(i) } @@ -378,10 +379,10 @@ impl LayoutCalculator { self.layout_of_struct( repr, variants, + present_first, is_enum, - is_special_no_niche, + niche_optimizations, always_sized, - present_first, ) } else { // At this point, we have handled all unions and @@ -392,16 +393,16 @@ impl LayoutCalculator { } } - pub fn layout_of_union< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + pub fn layout_of_union<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, variants: &IndexSlice>, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; @@ -519,36 +520,36 @@ impl LayoutCalculator { }) } - /// single-variant enums are just structs, if you think about it - fn layout_of_struct< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + /// Calculate the layout for a struct, or a single-variant enum. + /// + /// They are the same thing, if you think about it + /// (Typechecking will reject discriminant-sizing attrs.) + fn layout_of_struct<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, variants: &IndexSlice>, + variant_idx: VariantIdx, is_enum: bool, - is_special_no_niche: bool, + niche_optimizations: NicheOptimizations, always_sized: bool, - present_first: VariantIdx, - ) -> LayoutCalculatorResult { - // Struct, or univariant enum equivalent to a struct. - // (Typechecking will reject discriminant-sizing attrs.) - + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); - let v = present_first; + let v = variant_idx; let kind = if is_enum || variants[v].is_empty() || always_sized { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; - let mut st = self.univariant(&variants[v], repr, kind)?; + let mut st = self.layout_of_univariant(&variants[v], repr, kind)?; st.variants = Variants::Single { index: v }; - if is_special_no_niche { + if niche_optimizations == NicheOptimizations::Disabled { let hide_niches = |scalar: &mut _| match scalar { Scalar::Initialized { value, valid_range } => { *valid_range = WrappingRange::full(value.size(dl)) @@ -573,18 +574,18 @@ impl LayoutCalculator { Ok(st) } - fn layout_of_enum< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + fn layout_of_enum<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, variants: &IndexSlice>, discr_range_of_repr: impl Fn(RangeFrom, RangeToInclusive) -> (Integer, bool), discriminants: impl Iterator, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); // bail if the enum has an incoherent repr that cannot be computed if repr.packed() { @@ -613,7 +614,7 @@ impl LayoutCalculator { let mut variant_layouts = variants .iter() .map(|v| { - let st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?; + let st = self.layout_of_univariant(v, repr, StructKind::AlwaysSized).ok()?; variants_info.push(VariantLayoutInfo { align_abi: st.align.abi }); @@ -815,7 +816,7 @@ impl LayoutCalculator { let mut layout_variants = variants .iter() .map(|field_layouts| { - let st = self.univariant( + let st = self.layout_of_univariant( field_layouts, repr, StructKind::Prefixed(min_ity.size(), prefix_align), @@ -1078,18 +1079,18 @@ impl LayoutCalculator { Ok(best_layout) } - fn univariant_biased< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + fn layout_of_univariant_biased<'a, FieldIdx, VariantIdx, F>( &self, fields: &IndexSlice, repr: &ReprOptions, kind: StructKind, niche_bias: NicheBias, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); let pack = repr.pack; let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; @@ -1424,16 +1425,16 @@ impl LayoutCalculator { }) } - fn format_field_niches< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug, - >( + fn format_field_niches<'a, FieldIdx, VariantIdx, F>( &self, layout: &LayoutData, fields: &IndexSlice, - ) -> String { + ) -> String + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug, + { let dl = self.cx.data_layout(); let mut s = String::new(); for i in layout.fields.index_by_increasing_offset() { @@ -1484,15 +1485,13 @@ where }; // Compute the size and alignment of the vector - let size = elt - .size - .checked_mul(count.as_u64(), dl) - .ok_or_else(|| LayoutCalculatorError::SizeOverflow)?; + let size = + elt.size.checked_mul(count.as_u64(), dl).ok_or(LayoutCalculatorError::SizeOverflow)?; let (repr, size, align) = match kind { SimdVectorKind::Scalable(number_of_vectors) => ( BackendRepr::SimdScalableVector { element, count, number_of_vectors }, size.checked_mul(number_of_vectors.0 as u64, dl) - .ok_or_else(|| LayoutCalculatorError::SizeOverflow)?, + .ok_or(LayoutCalculatorError::SizeOverflow)?, dl.rust_vector_align(size), ), // Non-power-of-two vectors have padding up to the next power-of-two. diff --git a/compiler/rustc_abi/src/layout/coroutine.rs b/compiler/rustc_abi/src/layout/coroutine.rs index fd68d06c93829..c102fbb3e843c 100644 --- a/compiler/rustc_abi/src/layout/coroutine.rs +++ b/compiler/rustc_abi/src/layout/coroutine.rs @@ -136,20 +136,20 @@ fn coroutine_saved_local_eligibility> + core::fmt::Debug + Copy, - VariantIdx: Idx, - FieldIdx: Idx, - LocalIdx: Idx, ->( +pub(super) fn layout<'a, F, VariantIdx, FieldIdx, LocalIdx>( calc: &super::LayoutCalculator, local_layouts: &IndexSlice, mut prefix_layouts: IndexVec, variant_fields: &IndexSlice>, storage_conflicts: &BitMatrix, tag_to_layout: impl Fn(Scalar) -> F, -) -> super::LayoutCalculatorResult { +) -> super::LayoutCalculatorResult +where + F: core::ops::Deref> + core::fmt::Debug + Copy, + VariantIdx: Idx, + FieldIdx: Idx, + LocalIdx: Idx, +{ use SavedLocalEligibility::*; let (ineligible_locals, assignments) = @@ -171,8 +171,11 @@ pub(super) fn layout< let promoted_layouts = ineligible_locals.iter().map(|local| local_layouts[local]); prefix_layouts.push(tag_to_layout(tag)); prefix_layouts.extend(promoted_layouts); - let prefix = - calc.univariant(&prefix_layouts, &ReprOptions::default(), StructKind::AlwaysSized)?; + let prefix = calc.layout_of_univariant( + &prefix_layouts, + &ReprOptions::default(), + StructKind::AlwaysSized, + )?; let (prefix_size, prefix_align) = (prefix.size, prefix.align); @@ -225,7 +228,7 @@ pub(super) fn layout< }) .map(|local| local_layouts[*local]); - let mut variant = calc.univariant( + let mut variant = calc.layout_of_univariant( &variant_only_tys.collect::>(), &ReprOptions::default(), StructKind::Prefixed(prefix_size, prefix_align.abi), diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 5322b451fc6e8..df2dca6ec252b 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2027,10 +2027,10 @@ pub enum Variants { /// 2. the never type Empty, - /// The type has a single valid variant. + /// The type has a single valid variant. Such types are called "univariant". /// /// This is the case for: - /// 1. enums with a single inhabited variant + /// 1. enums with a single inhabited variant, aka. "univariant enums" /// 2. structs, unions, and non-ADTs (except coroutines; see below), /// as those can't have multiple variants Single { @@ -2195,6 +2195,18 @@ impl Niche { } } +/// Whether niche optimizations should be performed during layout calculation. +/// +/// [`UnsafeCell`] and [`UnsafePinned`] both disable niche optimizations. +/// +/// [`UnsafeCell`]: std::cell::UnsafeCell +/// [`UnsafePinned`]: std::pin::UnsafePinned +#[derive(PartialEq, Eq, Clone, Copy)] +pub enum NicheOptimizations { + Enabled, + Disabled, +} + // NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage. #[derive(PartialEq, Eq, Hash, Clone)] #[cfg_attr(feature = "nightly", derive(StableHash))] diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 712ed41ae7759..55c0bedb9c39c 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -283,7 +283,6 @@ impl StrippedCfgItem { #[derive(StableHash, PrintAttribute)] pub enum Linkage { AvailableExternally, - Common, ExternalWeak, External, Internal, diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index a00e5af00c2eb..6b4c5b8a681ca 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -660,10 +660,7 @@ impl SingleAttributeParser for LinkageParser { ]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: [ "available_externally", - "common", "extern_weak", - "external", - "internal", "linkonce", "linkonce_odr", "weak", @@ -686,10 +683,7 @@ impl SingleAttributeParser for LinkageParser { // and don't have to be, LLVM treats them as no-ops. let linkage = match value { sym::available_externally => Linkage::AvailableExternally, - sym::common => Linkage::Common, sym::extern_weak => Linkage::ExternalWeak, - sym::external => Linkage::External, - sym::internal => Linkage::Internal, sym::linkonce => Linkage::LinkOnceAny, sym::linkonce_odr => Linkage::LinkOnceODR, sym::weak => Linkage::WeakAny, @@ -700,10 +694,7 @@ impl SingleAttributeParser for LinkageParser { name_value.value_span, &[ sym::available_externally, - sym::common, sym::extern_weak, - sym::external, - sym::internal, sym::linkonce, sym::linkonce_odr, sym::weak, diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 07214096b3e49..acf5c75e4d8cd 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -55,19 +55,14 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR - | Linkage::ExternalWeak - | Linkage::Common => GlobalKind::Exported, + | Linkage::ExternalWeak => GlobalKind::Exported, } } /// The attribute a global *definition* needs on top of its [`GlobalKind`] to get this linkage. #[cfg(feature = "master")] pub fn global_linkage_attribute<'gcc>(linkage: Linkage) -> Option> { - match linkage { - Linkage::Common => Some(VarAttribute::Common), - _ if linkage_needs_weak_attribute(linkage) => Some(VarAttribute::Weak), - _ => None, - } + if linkage_needs_weak_attribute(linkage) { Some(VarAttribute::Weak) } else { None } } /// The type of a function *definition* with an explicit `#[linkage]`. @@ -85,17 +80,12 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR - | Linkage::ExternalWeak - | Linkage::Common => FunctionType::Exported, + | Linkage::ExternalWeak => FunctionType::Exported, } } /// Whether a definition with this linkage must carry the `weak` attribute, so that a strong /// definition in another object file wins over it instead of clashing with it. -/// -/// `common` is in here for functions only: GCC honours that attribute on a variable, but drops it -/// on a function, so a common function falls back to weak. Globals go through -/// `global_linkage_attribute` instead. #[cfg(feature = "master")] pub fn linkage_needs_weak_attribute(linkage: Linkage) -> bool { match linkage { @@ -103,8 +93,7 @@ pub fn linkage_needs_weak_attribute(linkage: Linkage) -> bool { | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR - | Linkage::ExternalWeak - | Linkage::Common => true, + | Linkage::ExternalWeak => true, Linkage::External | Linkage::AvailableExternally | Linkage::Internal => false, } } diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index c58ab6d2a9bef..0784064547e0f 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -13,8 +13,7 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_log::tracing::trace; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ - self, Allocation, ConstAllocation, CtfeProvenance, ErrorHandled, Scalar as InterpScalar, - read_target_uint, + self, ConstAllocation, CtfeProvenance, ErrorHandled, Scalar as InterpScalar, read_target_uint, }; use rustc_middle::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; @@ -113,12 +112,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // NOTE: Alignment from attributes has already been applied to the allocation. set_global_alignment(self, global, alloc.align); - // A common symbol is storage the linker allocates and zero-fills, so giving the definition - // an initializer — even an all-zero one — takes it back out of `.comm`. A non-zero one is - // kept: the symbol is then an ordinary definition, which is what GCC does with it too. - if attrs.linkage != Some(Linkage::Common) || !is_zero_initializer(alloc) { - global.global_set_initializer_rvalue(value); - } + global.global_set_initializer_rvalue(value); // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. @@ -458,17 +452,6 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( cx.const_struct(&llvals, true) } -/// Whether this allocation is all zeroes, and so needs no initializer to be spelled out. -fn is_zero_initializer(alloc: &Allocation) -> bool { - alloc.provenance().ptrs().is_empty() - // This `inspect` is okay: it is within the bounds of the allocation, there is no provenance - // to misread, and it does not affect interpreter execution. - && alloc - .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.size().bytes_usize()) - .iter() - .all(|&byte| byte == 0) -} - fn codegen_static_initializer<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId, diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index deaa78fcda003..ea37fc9666ae8 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -22,7 +22,7 @@ use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath}; -use rustc_span::{BytePos, InnerSpan, Pos, RemapPathScopeComponents, SpanData, SyntaxContext}; +use rustc_span::{BytePos, DUMMY_SP, InnerSpan, Pos, RemapPathScopeComponents}; use rustc_target::spec::{CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel}; use tracing::{debug, trace}; @@ -406,15 +406,12 @@ fn report_inline_asm( // In LTO build we may get srcloc values from other crates which are invalid // since they use a different source map. To be safe we just suppress these // in LTO builds. - let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) { - SpanData::default() + let (lo, hi) = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) { + (DUMMY_SP.lo(), DUMMY_SP.hi()) } else { - SpanData { - lo: BytePos::from_u32(cookie as u32), - hi: BytePos::from_u32((cookie >> 32) as u32), - ctxt: SyntaxContext::root(), - parent: None, - } + let lo = BytePos::from_u32(cookie as u32); + let hi = BytePos::from_u32((cookie >> 32) as u32); + (lo, hi) }; let level = match level { llvm::DiagnosticLevel::Error => Level::Error, @@ -422,7 +419,7 @@ fn report_inline_asm( llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note, }; let msg = msg.trim_prefix("error: ").to_string(); - InlineAsmError { span, msg, level, source } + InlineAsmError { lo, hi, msg, level, source } } unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index cf278694399f3..77cb37edec770 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -237,7 +237,6 @@ pub(crate) fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { Linkage::WeakODR => llvm::Linkage::WeakODRLinkage, Linkage::Internal => llvm::Linkage::InternalLinkage, Linkage::ExternalWeak => llvm::Linkage::ExternalWeakLinkage, - Linkage::Common => llvm::Linkage::CommonLinkage, } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 9f239bbb9ac98..d39ae5a1852d5 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -4,15 +4,15 @@ use std::panic::AssertUnwindSafe; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender, channel}; -use std::{assert_matches, fs, io, mem, str, thread}; +use std::{assert_matches, fs, io, str, thread}; use rustc_abi::Size; use rustc_data_structures::jobserver::{self, Acquired}; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_errors::emitter::Emitter; use rustc_errors::{ - Diag, DiagArgMap, DiagCtxt, DiagCtxtHandle, DiagMessage, ErrCode, FatalError, FatalErrorMarker, - Level, MultiSpan, Style, Sublevel, Suggestions, catch_fatal_errors, + Diag, DiagCtxt, DiagCtxtHandle, DiagInner, FatalError, FatalErrorMarker, Level, + catch_fatal_errors, }; use rustc_fs_util::link_or_copy; use rustc_incremental::{ @@ -27,7 +27,7 @@ use rustc_session::config::{ }; use rustc_session::{IncrCompSession, Session}; use rustc_span::source_map::SourceMap; -use rustc_span::{FileName, InnerSpan, Span, SpanData, bug}; +use rustc_span::{BytePos, FileName, InnerSpan, Span, SyntaxContext, bug}; use rustc_structures::CrateType; use rustc_target::spec::{MergeFunctions, SanitizerSet}; use tracing::debug; @@ -1186,31 +1186,6 @@ pub(crate) enum ThinLtoMessage { /// process another codegen unit. pub struct CguMessage; -// A cut-down version of `rustc_errors::DiagInner` that impls `Send`, which -// can be used to send diagnostics from codegen threads to the main thread. -// It's missing the following fields from `rustc_errors::DiagInner`. -// - `span`: it doesn't impl `Send`. -// - `suggestions`: it doesn't impl `Send`, and isn't used for codegen -// diagnostics. -// - `is_lint`: lints aren't relevant during codegen. -// - `emitted_at`: not used for codegen diagnostics. -struct Diagnostic { - span: Vec, - level: Level, - messages: Vec<(DiagMessage, Style)>, - code: Option, - children: Vec, - args: DiagArgMap, -} - -// A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's -// missing the following fields from `rustc_errors::Subdiag`. -// - `span`: it doesn't impl `Send`. -struct Subdiagnostic { - level: Sublevel, - messages: Vec<(DiagMessage, Style)>, -} - #[derive(PartialEq, Clone, Copy, Debug)] enum MainThreadState { /// Doing nothing. @@ -1947,13 +1922,18 @@ fn spawn_thin_lto_work( } enum SharedEmitterMessage { - Diagnostic(Diagnostic), + Diagnostic(DiagInner), InlineAsmError(InlineAsmError), Fatal(String), } pub struct InlineAsmError { - pub span: SpanData, + // We store byte positions rather than a `Span` because this error is created on a codegen + // thread which doesn't have access to the span interner within the session globals. The byte + // positions are converted to a `Span` once they reach a thread with access to the span + // interner. + pub lo: BytePos, + pub hi: BytePos, pub msg: String, pub level: Level, pub source: Option<(String, Vec)>, @@ -1985,29 +1965,8 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, mut diag: rustc_errors::DiagInner) { - // Check that we aren't missing anything interesting when converting to - // the cut-down local `DiagInner`. - assert!(!diag.span.has_span_labels()); - assert_eq!(diag.suggestions, Suggestions::Enabled(vec![])); - assert_eq!(diag.is_lint, None); - // No sensible check for `diag.emitted_at`. - - let args = mem::take(&mut diag.args); - drop( - self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - span: diag.span.primary_spans().iter().map(|span| span.data()).collect::>(), - level: diag.level(), - messages: diag.messages, - code: diag.code, - children: diag - .children - .into_iter() - .map(|child| Subdiagnostic { level: child.level, messages: child.messages }) - .collect(), - args, - })), - ); + fn emit_diagnostic(&mut self, diag: DiagInner) { + drop(self.sender.send(SharedEmitterMessage::Diagnostic(diag))); } fn source_map(&self) -> Option<&SourceMap> { @@ -2032,33 +1991,16 @@ impl SharedEmitterMain { match message { Ok(SharedEmitterMessage::Diagnostic(diag)) => { - // The diagnostic has been received on the main thread. - // Convert it back to a full `Diagnostic` and emit. let dcx = sess.dcx(); - let mut d = - rustc_errors::DiagInner::new_with_messages(diag.level, diag.messages); - d.span = MultiSpan::from_spans( - diag.span.into_iter().map(|span| span.span()).collect(), - ); - d.code = diag.code; // may be `None`, that's ok - d.children = diag - .children - .into_iter() - .map(|sub| rustc_errors::Subdiag { - level: sub.level, - messages: sub.messages, - span: MultiSpan::new(), - }) - .collect(); - d.args = diag.args; - dcx.emit_diagnostic(d); + dcx.emit_diagnostic(diag); sess.dcx().abort_if_errors(); } Ok(SharedEmitterMessage::InlineAsmError(inner)) => { assert_matches!(inner.level, Level::Error | Level::Warning(None) | Level::Note); let mut err = Diag::new(sess.dcx(), inner.level, inner.msg); - if !inner.span.is_dummy() { - err.span(inner.span.span()); + let span = Span::new(inner.lo, inner.hi, SyntaxContext::root(), None); + if !span.is_dummy() { + err.span(span); } // Point to the generated assembly if it is available. diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 2fa6f3fc06550..5433b9da6f2b6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -228,7 +228,6 @@ fn prefix_and_suffix<'tcx>( // LTO can fail when internal linkage is used. emit_fatal("naked functions may not have internal linkage") } - Linkage::Common => emit_fatal("Functions may not have common linkage"), Linkage::AvailableExternally => { // this would make the function equal an extern definition emit_fatal("Functions may not have available_externally linkage") diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index 98a11f8e1df08..464423b303f4f 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -2709,6 +2709,27 @@ pub(crate) enum UnusedDefSuggestion { #[suggestion_part(code = ";")] after_span: Span, }, + #[suggestion( + "use `let _unused = ...` to ignore the resulting value without dropping it immediately", + style = "verbose", + code = "let _unused = ", + applicability = "maybe-incorrect" + )] + BindingExpr { + #[primary_span] + span: Span, + }, + #[multipart_suggestion( + "use `let _unused = ...` to ignore the resulting value without dropping it immediately", + style = "verbose", + applicability = "maybe-incorrect" + )] + BindingBlockTailExpr { + #[suggestion_part(code = "let _unused = ")] + before_span: Span, + #[suggestion_part(code = ";")] + after_span: Span, + }, } // Needed because of def_path_str diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index dab842a688ae1..89e3981b965f2 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -299,6 +299,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { return; } + let ty = cx.typeck_results().expr_ty(expr); + let needs_binding = ty.has_significant_drop(cx.tcx, cx.typing_env()); + if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind && let ty = cx.typeck_results().expr_ty(await_expr) && let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: future_def_id }, .. }) = ty.kind() @@ -314,6 +317,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { "output of future returned by ", "", expr_is_from_block, + needs_binding, ) { // We have a bare `foo().await;` on an opaque type from an async function that was @@ -321,19 +325,26 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { return; } - let ty = cx.typeck_results().expr_ty(expr); - let must_use_result = is_ty_must_use(cx, ty, expr); let type_lint_emitted_or_trivial = match must_use_result { IsTyMustUse::Yes(path) => { - emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block); + emit_must_use_untranslated( + cx, + &path, + "", + "", + 1, + false, + expr_is_from_block, + needs_binding, + ); true } IsTyMustUse::Trivial => true, IsTyMustUse::No => false, }; - let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block); + let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block, needs_binding); if !fn_warned && type_lint_emitted_or_trivial { // We don't warn about unused unit or uninhabited types. @@ -415,7 +426,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { /// Checks if `expr` is a \[method\] call expression marked as `#[must_use]` and emits a lint if so. /// Returns `true` if the lint has been emitted. -fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>, expr_is_from_block: bool) -> bool { +fn check_fn_must_use( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + expr_is_from_block: bool, + needs_binding: bool, +) -> bool { let maybe_def_id = match expr.kind { hir::ExprKind::Call(callee, _) => { if let hir::ExprKind::Path(ref qpath) = callee.kind @@ -434,9 +450,15 @@ fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>, expr_is_from_bl }; match maybe_def_id { - Some(def_id) => { - check_must_use_def(cx, def_id, expr.span, "return value of ", "", expr_is_from_block) - } + Some(def_id) => check_must_use_def( + cx, + def_id, + expr.span, + "return value of ", + "", + expr_is_from_block, + needs_binding, + ), None => false, } } @@ -455,6 +477,7 @@ fn check_must_use_def( descr_pre_path: &str, descr_post_path: &str, expr_is_from_block: bool, + needs_binding: bool, ) -> bool { is_def_must_use(cx, def_id, span) .map(|must_use_path| { @@ -466,6 +489,7 @@ fn check_must_use_def( 1, false, expr_is_from_block, + needs_binding, ) }) .is_some() @@ -480,6 +504,7 @@ fn emit_must_use_untranslated( plural_len: usize, is_inner: bool, expr_is_from_block: bool, + needs_binding: bool, ) { let plural_suffix = pluralize!(plural_len); @@ -494,6 +519,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::Pinned(path) => { @@ -506,6 +532,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::Opaque(path) => { @@ -518,6 +545,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::TraitObject(path) => { @@ -530,6 +558,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::TupleElement(elems) => { @@ -543,6 +572,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } } @@ -556,6 +586,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::ControlFlow(path) => { @@ -568,6 +599,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::Array(path, len) => { @@ -580,6 +612,7 @@ fn emit_must_use_untranslated( plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)), true, expr_is_from_block, + needs_binding, ); } MustUsePath::Closure(span) => { @@ -615,14 +648,24 @@ fn emit_must_use_untranslated( cx, def_id: *def_id, note: *reason, - suggestion: (!is_inner).then_some(if expr_is_from_block { - UnusedDefSuggestion::BlockTailExpr { - before_span: suggestion_span.shrink_to_lo(), - after_span: suggestion_span.shrink_to_hi(), - } + suggestion: if is_inner { + None } else { - UnusedDefSuggestion::NormalExpr { span: suggestion_span.shrink_to_lo() } - }), + let lo = suggestion_span.shrink_to_lo(); + let hi = suggestion_span.shrink_to_hi(); + Some(match (needs_binding, expr_is_from_block) { + (true, true) => UnusedDefSuggestion::BindingBlockTailExpr { + before_span: lo, + after_span: hi, + }, + (true, false) => UnusedDefSuggestion::BindingExpr { span: lo }, + (false, true) => UnusedDefSuggestion::BlockTailExpr { + before_span: lo, + after_span: hi, + }, + (false, false) => UnusedDefSuggestion::NormalExpr { span: lo }, + }) + }, }, ); } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 43ce9634cc203..16df895b0f728 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -1252,7 +1252,6 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitio Linkage::WeakODR => "WeakODR", Linkage::Internal => "Internal", Linkage::ExternalWeak => "ExternalWeak", - Linkage::Common => "Common", }; output.push('['); diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 2ea2f52c696ba..9defefee9637b 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1042,6 +1042,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Res::Def(k, _) => matches_kind(k), _ => false, }, + &|_| true, ) && let Res::Def(kind, mut def_id) = suggestion.res { if let DefKind::Ctor(_, _) = kind { @@ -1615,6 +1616,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope: &ParentScope<'ra>, ident: Ident, filter_fn: &impl Fn(Res) -> bool, + suggestion_filter: &impl Fn(&TypoSuggestion) -> bool, ) -> Option { let mut suggestions = Vec::new(); self.add_scope_set_candidates( @@ -1625,6 +1627,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { filter_fn, ); + // Some candidates cannot be decided from the `Res` alone (e.g. they need + // re-resolution or visibility checks), filter them out before picking the + // best name match. + suggestions.retain(suggestion_filter); + // Make sure error reporting is deterministic. suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); @@ -1977,6 +1984,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope, ident, is_expected, + &|_| true, ); self.add_typo_suggestion(err, suggestion, ident.span); self.detect_derive_attribute(err, ident, parent_scope, sugg_span); @@ -3035,6 +3043,45 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let message = format!("cannot find `{ident}` in {scope}"); + // we may have typo in the middle part of path, try find a candidate with a similar name + // and then check whether it contains a candidate that is accessible from the current scope + let typo_suggestion = if opt_ns.is_none() + && ignore_import.is_some() + && let Some(ModuleOrUniformRoot::Module(module)) = module + && let Some(candidate) = self.early_lookup_typo_candidate( + ScopeSet::Module(TypeNS, module), + parent_scope, + ident, + &|res| matches!(res, Res::Def(DefKind::Mod | DefKind::Enum, _)), + &|candidate| { + self.cm() + .resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + Ident::new(candidate.candidate, ident.span), + TypeNS, + parent_scope, + None, + ignore_decl, + ignore_import, + ) + .is_ok_and(|binding| { + self.is_accessible_from(binding.vis(), parent_scope.module) + }) + }, + ) { + Some(( + vec![(ident.span, Ident::new(candidate.candidate, ident.span).to_string())], + format!( + "{} {} with a similar name exists", + candidate.res.article(), + candidate.res.descr(), + ), + Applicability::MaybeIncorrect, + )) + } else { + None + }; + if module_def_id == Some(CRATE_DEF_ID.to_def_id()) { let is_mod = |res| matches!(res, Res::Def(DefKind::Mod, _)); let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod); @@ -3061,6 +3108,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { )), None, ) + } else if let Some(suggestion) = typo_suggestion { + ( + message, + format!("could not find `{ident}` in the crate root"), + Some(suggestion), + None, + ) } else if ident.name == sym::core { ( message, @@ -3193,7 +3247,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); }; } - (message, msg, None, None) + (message, msg, typo_suggestion, None) } else if ident.name == kw::SelfUpper { // As mentioned above, `opt_ns` being `None` indicates a module path in import. // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e62ad42875248..b7aa25a5cfa7c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -666,7 +666,6 @@ symbols! { cold_path, collapse_debuginfo, column, - common, compare_bytes, compare_exchange, compare_exchange_weak, @@ -1168,7 +1167,6 @@ symbols! { integer_max, integer_min, integral, - internal, internal_eq_trait_method_impls, internal_features, interrupt, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 8f63c96fad707..8d8e501391c43 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -5,8 +5,8 @@ use rustc_abi::Integer::{I8, I32}; use rustc_abi::Primitive::{self, Float, Int, Pointer}; use rustc_abi::{ AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, Layout, - LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, - VariantIdx, Variants, WrappingRange, + LayoutCalculatorError, LayoutData, Niche, NicheOptimizations, ReprOptions, Scalar, Size, + StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; @@ -235,7 +235,7 @@ fn layout_of_uncached<'tcx>( let univariant = |tys: &[Ty<'tcx>], kind| { let fields = tys.iter().map(|ty| cx.layout_of(*ty)).try_collect::>()?; let repr = ReprOptions::default(); - map_layout(cx.calc.univariant(&fields, &repr, kind)) + map_layout(cx.calc.layout_of_univariant(&fields, &repr, kind)) }; debug_assert!(!ty.has_non_region_infer()); @@ -523,11 +523,11 @@ fn layout_of_uncached<'tcx>( .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; let element = cx.layout_of(element)?; - map_layout(cx.calc.array_like(&element, Some(count)))? + map_layout(cx.calc.layout_of_array_like(&element, Some(count)))? } ty::Slice(element) => { let element = cx.layout_of(element)?; - map_layout(cx.calc.array_like(&element, None).map(|mut layout| { + map_layout(cx.calc.layout_of_array_like(&element, None).map(|mut layout| { // a randomly chosen value to distinguish slices layout.randomization_seed = Hash64::new(0x2dcba99c39784102); layout @@ -535,7 +535,7 @@ fn layout_of_uncached<'tcx>( } ty::Str => { let element = scalar(Int(I8, false)); - map_layout(cx.calc.array_like(&element, None).map(|mut layout| { + map_layout(cx.calc.layout_of_array_like(&element, None).map(|mut layout| { // another random value layout.randomization_seed = Hash64::new(0xc1325f37d127be22); layout @@ -586,7 +586,7 @@ fn layout_of_uncached<'tcx>( let layout = cx .calc - .coroutine( + .layout_of_coroutine( &local_layouts, prefix_layouts, &info.variant_fields, @@ -638,7 +638,7 @@ fn layout_of_uncached<'tcx>( }; let element_layout = cx.layout_of(element_ty)?; - map_layout(cx.calc.scalable_vector_type( + map_layout(cx.calc.layout_of_scalable_vector_type( element_layout, element_count as u64, number_of_vectors, @@ -683,7 +683,7 @@ fn layout_of_uncached<'tcx>( } } - map_layout(cx.calc.simd_type(e_ly, e_len, def.repr().packed()))? + map_layout(cx.calc.layout_of_simd_type(e_ly, e_len, def.repr().packed()))? } // ADTs. @@ -713,7 +713,10 @@ fn layout_of_uncached<'tcx>( } // UnsafeCell and UnsafePinned both disable niche optimizations - let is_special_no_niche = def.is_unsafe_cell() || def.is_unsafe_pinned(); + let niche_optimizations = match def.is_unsafe_cell() || def.is_unsafe_pinned() { + true => NicheOptimizations::Disabled, + false => NicheOptimizations::Enabled, + }; let discr_range_of_repr = |min: RangeFrom, max: RangeToInclusive| { abi::Integer::discr_range_of_repr(tcx, ty, &def.repr(), min.start, max.last) @@ -755,7 +758,7 @@ fn layout_of_uncached<'tcx>( &def.repr(), &variants, def.is_enum(), - is_special_no_niche, + niche_optimizations, discr_range_of_repr, discriminants_iter(), !maybe_unsized, @@ -784,7 +787,7 @@ fn layout_of_uncached<'tcx>( &def.repr(), &variants, def.is_enum(), - is_special_no_niche, + niche_optimizations, discr_range_of_repr, discriminants_iter(), !maybe_unsized, diff --git a/library/alloc/src/collections/vec_deque/macros.rs b/library/alloc/src/collections/vec_deque/macros.rs index 5c7913073fe87..dbc1fa3f11578 100644 --- a/library/alloc/src/collections/vec_deque/macros.rs +++ b/library/alloc/src/collections/vec_deque/macros.rs @@ -17,3 +17,23 @@ macro_rules! __impl_slice_eq1 { } } } + +macro_rules! __impl_slice_eq2 { + ($(#[$stability:meta])+, [$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { + $(#[$stability])+ + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($constraints)* + { + fn eq(&self, other: &$rhs) -> bool { + if self.len() != other.len() { + return false; + } + let (oa, ob) = other.as_slices(); + let (sa, sb) = self[..].split_at(oa.len()); + sa == oa && sb == ob + } + } + } +} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 8e4507c6fd0aa..545c6ca59cc32 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -3907,6 +3907,13 @@ __impl_slice_eq1! { [const N: usize] VecDeque, [U; N], } __impl_slice_eq1! { [const N: usize] VecDeque, &[U; N], } __impl_slice_eq1! { [const N: usize] VecDeque, &mut [U; N], } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] Vec, VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] &[T], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] &mut [T], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] [T; N], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] &[T; N], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] &mut [T; N], VecDeque, } + #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for VecDeque { fn partial_cmp(&self, other: &Self) -> Option { diff --git a/library/alloctests/tests/vec_deque.rs b/library/alloctests/tests/vec_deque.rs index 00b2c2e34d569..3925a1235d3e7 100644 --- a/library/alloctests/tests/vec_deque.rs +++ b/library/alloctests/tests/vec_deque.rs @@ -631,6 +631,27 @@ fn test_partial_eq_array() { assert!(d == ['a', 'b']); } +#[test] +fn test_partial_eq_vecdeque_reverse() { + let mut d = VecDeque::with_capacity(4); + d.push_back(1); + d.push_back(2); + d.push_back(3); + d.pop_front(); + d.push_back(4); + + let v = vec![2, 3, 4]; + let a = [2, 3, 4]; + let mut b = [2, 3, 4]; + + assert!(v == d); + assert!(&v[..] == d); + assert!(&mut b[..] == d); + assert!(a == d); + assert!(&a == d); + assert!(&mut b == d); +} + #[test] fn test_hash() { let mut x = VecDeque::new(); diff --git a/library/core/src/fmt/num_buffer.rs b/library/core/src/fmt/num_buffer.rs index 5c29964b1cff8..62089e30a06e2 100644 --- a/library/core/src/fmt/num_buffer.rs +++ b/library/core/src/fmt/num_buffer.rs @@ -84,3 +84,10 @@ impl NumBuffer { NumBuffer { buf: T::DEFAULT, phantom: core::marker::PhantomData } } } + +#[stable(feature = "num_buffer_default", since = "CURRENT_RUSTC_VERSION")] +impl Default for NumBuffer { + fn default() -> Self { + Self::new() + } +} diff --git a/library/core/src/intrinsics/fallback.rs b/library/core/src/intrinsics/fallback.rs index d2794a5b1202d..3e6829ab16b18 100644 --- a/library/core/src/intrinsics/fallback.rs +++ b/library/core/src/intrinsics/fallback.rs @@ -112,8 +112,13 @@ const impl CarryingMulAdd for i128 { #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")] pub const trait DisjointBitOr: Copy + 'static { - /// See [`super::disjoint_bitor`]; we just need the trait indirection to handle - /// different types since calling intrinsics with generics doesn't work. + /// We just need the trait indirection to handle different types + /// since calling intrinsics with generics doesn't work. + /// + /// # Safety + /// + /// See [`super::disjoint_bitor`], with `self` corresponding to `a` and + /// `other` corresponding to `b`. unsafe fn disjoint_bitor(self, other: Self) -> Self; } macro_rules! zero { @@ -149,12 +154,22 @@ impl_disjoint_bitor! { #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")] pub const trait FunnelShift: Copy + 'static { - /// See [`super::unchecked_funnel_shl`]; we just need the trait indirection to handle - /// different types since calling intrinsics with generics doesn't work. + /// We just need the trait indirection to handle different types + /// since calling intrinsics with generics doesn't work. + /// + /// # Safety + /// + /// See [`super::unchecked_funnel_shl`], with `self` corresponding to `a` and + /// `right` corresponding to `b`. unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self; - /// See [`super::unchecked_funnel_shr`]; we just need the trait indirection to handle - /// different types since calling intrinsics with generics doesn't work. + /// We just need the trait indirection to handle different types + /// since calling intrinsics with generics doesn't work. + /// + /// # Safety + /// + /// See [`super::unchecked_funnel_shr`], with `self` corresponding to `a` and + /// `right` corresponding to `b`. unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self; } diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh index 370b243dd4551..2402ec6ae34bf 100644 --- a/src/ci/docker/scripts/musl.sh +++ b/src/ci/docker/scripts/musl.sh @@ -78,12 +78,14 @@ EOF # project, so we just apply them directly on top of the version we were distributing already. The # patches should be removed once we upgrade to musl >= 1.2.7. # + SCRIPT_DIR=$(cd -- "$(dirname -- "$0")" && pwd) + MUSL_PATCH_DIR="$SCRIPT_DIR" # Advisory: https://www.openwall.com/lists/oss-security/2026/04/09/19 # Patches: https://www.openwall.com/lists/musl/2026/04/03/2/1 - patch -p1 -d $MUSL SBValue: return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0) -def unwrap_scalar_wrappers(wrapper: SBValue) -> SBValue: - while (wrapper.type.GetTypeFlags() & eTypeIsInteger) == 0: - wrapper = wrapper.GetChildAtIndex(0) - return wrapper - - class DefaultSyntheticProvider: def __init__(self, valobj: SBValue, _dict: LLDBOpaque): # logger = Logger.Logger() @@ -1549,9 +1542,17 @@ def has_children(self) -> bool: def StdRcSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: - strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned() - weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned() - return "strong={}, weak={}".format(strong, weak) + strong = valobj.GetChildMemberWithName("strong") + weak = valobj.GetChildMemberWithName("weak") + + if not (strong.IsValid() and weak.IsValid()): + strong = "?" + weak = "?" + else: + strong = strong.GetValueAsUnsigned() + weak = weak.GetValueAsUnsigned() + + return f"strong={strong}, weak={weak}" class StdRcSyntheticProvider: @@ -1574,8 +1575,24 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_atomic: bool = False): self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value") - self.strong = unwrap_scalar_wrappers(self.ptr.GetChildMemberWithName("strong")) - self.weak = unwrap_scalar_wrappers(self.ptr.GetChildMemberWithName("weak")) + # infallibly gets an unsigned integer type of at least 64 bits. We don't need to worry about + # whether or not `usize` is actually smaller than that since we don't ever display the + # underlying type to the user anyway + usize_type = valobj.GetTarget().GetBasicType(eBasicTypeUnsignedLongLong) + + self.strong = self.ptr.GetChildMemberWithName("strong").Cast(usize_type) + self.weak = self.ptr.GetChildMemberWithName("weak").Cast(usize_type) + + # If the usize type isn't valid due to llvm/llvm-project#196812, not even the type's fields + # will populate. Luckily, `RcInner` is `#[repr(C)]`, so we can infallibly find the strong + # and weak values in memory + if not self.strong.IsValid() or not self.weak.IsValid(): + raw_ptr = self.ptr.Cast(usize_type.GetPointerType()) + addr = raw_ptr.GetValueAsAddress() + self.strong = self.valobj.CreateValueFromAddress("strong", addr, usize_type) + self.weak = self.valobj.CreateValueFromAddress( + "weak", addr + usize_type.GetByteSize(), usize_type + ) self.value_builder = ValueBuilder(valobj) @@ -1598,15 +1615,14 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]: if index == 0: return self.value if index == 1: - return self.value_builder.from_uint("strong", self.strong_count) + return self.strong if index == 2: - return self.value_builder.from_uint("weak", self.weak_count) + return self.weak return None def update(self): - self.strong_count = self.strong.GetValueAsUnsigned() - self.weak_count = self.weak.GetValueAsUnsigned() - 1 + pass def has_children(self) -> bool: return True diff --git a/tests/codegen-llvm/direct-access-external-data.rs b/tests/codegen-llvm/direct-access-external-data.rs index a151bb6012e1e..43ee290d3a058 100644 --- a/tests/codegen-llvm/direct-access-external-data.rs +++ b/tests/codegen-llvm/direct-access-external-data.rs @@ -22,15 +22,6 @@ unsafe extern "C" { // When "linkage" is used, we generate an indirection global. // Check dso_local is still applied to the actual global. - // CHECK: @EXTERNAL = external - // DEFAULT-SAME: dso_local - // PIE-NOT: dso_local - // DIRECT-SAME: dso_local - // INDIRECT-NOT: dso_local - // CHECK-SAME: global i8 - #[linkage = "external"] - safe static EXTERNAL: *const u32; - // CHECK: @WEAK = extern_weak // DEFAULT-SAME: dso_local // PIE-NOT: dso_local @@ -44,6 +35,5 @@ unsafe extern "C" { #[no_mangle] pub fn refer() { core::hint::black_box(VAR); - core::hint::black_box(EXTERNAL); core::hint::black_box(WEAK); } diff --git a/tests/debuginfo/rc_arc.rs b/tests/debuginfo/rc_arc.rs index b22b7e0d1611d..4399dfe54e7a5 100644 --- a/tests/debuginfo/rc_arc.rs +++ b/tests/debuginfo/rc_arc.rs @@ -18,9 +18,9 @@ //@ lldb-command:run //@ lldb-command:v rc -//@ lldb-check:[...] strong=11, weak=1 { value = 111 } +//@ lldb-check:[...] strong=11, weak=2 { value = 111 } //@ lldb-command:v arc -//@ lldb-check:[...] strong=21, weak=1 { data = 222 } +//@ lldb-check:[...] strong=21, weak=2 { data = 222 } // === CDB TESTS ================================================================================== diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 4ad61e29d3ec0..81e3037f1e566 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -43,7 +43,7 @@ //@ lldb-check:[...] str_in_tuple = ("Hello", "World") //@ lldb-command:v str_in_rc -//@ lldb-check:[...] str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } +//@ lldb-check:[...] str_in_rc = strong=1, weak=1 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } //@ lldb-command:v box_str //@ lldb-check:[...] box_str = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } @@ -56,7 +56,7 @@ // lldb-command:v rc_str // ignore-tidy-linelength -// lldb-check:(alloc::rc::Rc) rc_str = strong=1, weak=0 { value = "World" } +// lldb-check:(alloc::rc::Rc) rc_str = strong=1, weak=1 { value = "World" } #![allow(unused_variables)] diff --git a/tests/run-make/linkage-attr-on-static/bar.rs b/tests/run-make/linkage-attr-on-static/bar.rs index 68607cbb65721..cbab76ba6f403 100644 --- a/tests/run-make/linkage-attr-on-static/bar.rs +++ b/tests/run-make/linkage-attr-on-static/bar.rs @@ -1,7 +1,7 @@ #![feature(linkage)] #[no_mangle] -#[linkage = "external"] +#[linkage = "weak"] static BAZ: i32 = 21; #[link(name = "foo", kind = "static")] diff --git a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs index ce787f83ade6d..8d699a665ae24 100644 --- a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs +++ b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs @@ -51,17 +51,6 @@ pub extern "C" fn public_naked_generic() -> u32 { naked_asm!("mov rax, {}", "ret", const T::COUNT) } -#[linkage = "external"] -extern "C" fn vanilla_external_linkage() -> u32 { - 42 -} - -#[unsafe(naked)] -#[linkage = "external"] -extern "C" fn naked_external_linkage() -> u32 { - naked_asm!("mov rax, 42", "ret") -} - #[cfg(not(windows))] #[linkage = "weak"] extern "C" fn vanilla_weak_linkage() -> u32 { diff --git a/tests/run-make/naked-symbol-visibility/rmake.rs b/tests/run-make/naked-symbol-visibility/rmake.rs index 69317c872f895..1acbe11dc4ae4 100644 --- a/tests/run-make/naked-symbol-visibility/rmake.rs +++ b/tests/run-make/naked-symbol-visibility/rmake.rs @@ -29,9 +29,6 @@ fn main() { // -Zshare-generics. global_function(&rdylib, "public_naked_generic"); - global_function(&rdylib, "vanilla_external_linkage"); - global_function(&rdylib, "naked_external_linkage"); - // FIXME: make this work on windows (gnu and msvc). See the PR // https://github.com/rust-lang/rust/pull/128362 for some approaches // that don't work diff --git a/tests/ui/asm/naked-functions/naked-functions.rs b/tests/ui/asm/naked-functions/naked-functions.rs index d994b1151514a..e7da65a169074 100644 --- a/tests/ui/asm/naked-functions/naked-functions.rs +++ b/tests/ui/asm/naked-functions/naked-functions.rs @@ -224,7 +224,7 @@ pub extern "C" fn compatible_doc_attributes() { naked_asm!("", options(raw)); } -#[linkage = "external"] +#[linkage = "weak"] #[unsafe(naked)] pub extern "C" fn compatible_linkage() { naked_asm!("", options(raw)); diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.rs b/tests/ui/attributes/codegen_attr_on_required_trait_method.rs index 737ebf7f2b144..2ea4e0b5a395c 100644 --- a/tests/ui/attributes/codegen_attr_on_required_trait_method.rs +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.rs @@ -11,7 +11,7 @@ trait Test { //~^ ERROR cannot be used on required trait methods [unused_attributes] //~| WARN previously accepted fn method2(&self); - #[linkage = "common"] + #[linkage = "weak"] //~^ ERROR `linkage` attribute cannot be used on required trait methods fn method3(&self); #[track_caller] diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr index b5452ba2882c0..729231956337d 100644 --- a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr @@ -1,7 +1,7 @@ error: the `linkage` attribute cannot be used on required trait methods --> $DIR/codegen_attr_on_required_trait_method.rs:14:7 | -LL | #[linkage = "common"] +LL | #[linkage = "weak"] | ^^^^^^^ | = help: the `linkage` attribute can be applied to foreign functions, foreign statics, functions with a body, and statics diff --git a/tests/ui/consts/too_generic_eval_ice.current.stderr b/tests/ui/consts/too_generic_eval_ice.current.stderr index 061945e344ede..dd5c3bd51bc52 100644 --- a/tests/ui/consts/too_generic_eval_ice.current.stderr +++ b/tests/ui/consts/too_generic_eval_ice.current.stderr @@ -30,15 +30,15 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]` = help: the following other types implement trait `PartialEq`: + `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` + `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - `&[u8]` implements `PartialEq` - `&mut [T]` implements `PartialEq>` - and 13 others + and 18 others error: aborting due to 4 previous errors diff --git a/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.rs b/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.rs new file mode 100644 index 0000000000000..39dc8cd381268 --- /dev/null +++ b/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.rs @@ -0,0 +1,19 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/131366. +//! Similar spelling does not make a private module or a non-module importable. + +//@ edition: 2021 +#![allow(unused_imports, dead_code)] + +mod private { + mod collections { pub struct Item; } +} +use private::collection::Item; +//~^ ERROR unresolved import `private::collection` + +mod non_module { + pub struct Collections; +} +use non_module::Collection::Item; +//~^ ERROR unresolved import `non_module::Collection` + +fn main() {} diff --git a/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.stderr b/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.stderr new file mode 100644 index 0000000000000..020711207ef38 --- /dev/null +++ b/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.stderr @@ -0,0 +1,15 @@ +error[E0432]: unresolved import `private::collection` + --> $DIR/nested-module-typo-inaccessible-issue-131366.rs:10:14 + | +LL | use private::collection::Item; + | ^^^^^^^^^^ could not find `collection` in `private` + +error[E0432]: unresolved import `non_module::Collection` + --> $DIR/nested-module-typo-inaccessible-issue-131366.rs:16:17 + | +LL | use non_module::Collection::Item; + | ^^^^^^^^^^ could not find `Collection` in `non_module` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/nested-module-typo-issue-131366.fixed b/tests/ui/imports/nested-module-typo-issue-131366.fixed new file mode 100644 index 0000000000000..ff1c4eb2532b2 --- /dev/null +++ b/tests/ui/imports/nested-module-typo-issue-131366.fixed @@ -0,0 +1,46 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/131366. +//! Suggest accessible, similarly named modules within the resolved import prefix. + +//@ edition: 2021 +//@ run-rustfix +#![allow(unused_imports, dead_code)] + +use std::collections::HashMap; +//~^ ERROR unresolved import `std::collection` + +mod local { + pub mod collections { + pub struct Item; + } + pub use collections as containers; + pub enum Choices { First } +} + +use local::collections::Item; +//~^ ERROR unresolved import `local::collection` +use local::containers::Item as Alias; +//~^ ERROR unresolved import `local::container` +use local::Choices::First; +//~^ ERROR unresolved import `local::Choice` + +mod root_module {} +use crate::root_module::*; +//~^ ERROR unresolved import `crate::root_modul` + +macro_rules! import { + ($module:ident) => { use local::$module::Item as MacroItem; }; +} +import!(collections); +//~^ ERROR unresolved import `local::collection` + +mod accessible { + pub mod collections { + pub struct Item; + } + use collections as collection; +} +// The closer match is a private alias, so suggest the accessible module instead. +use accessible::collections::Item as AccessibleItem; +//~^ ERROR unresolved import `accessible::collectio` + +fn main() {} diff --git a/tests/ui/imports/nested-module-typo-issue-131366.rs b/tests/ui/imports/nested-module-typo-issue-131366.rs new file mode 100644 index 0000000000000..2d0e81e2e0e3a --- /dev/null +++ b/tests/ui/imports/nested-module-typo-issue-131366.rs @@ -0,0 +1,46 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/131366. +//! Suggest accessible, similarly named modules within the resolved import prefix. + +//@ edition: 2021 +//@ run-rustfix +#![allow(unused_imports, dead_code)] + +use std::collection::HashMap; +//~^ ERROR unresolved import `std::collection` + +mod local { + pub mod collections { + pub struct Item; + } + pub use collections as containers; + pub enum Choices { First } +} + +use local::collection::Item; +//~^ ERROR unresolved import `local::collection` +use local::container::Item as Alias; +//~^ ERROR unresolved import `local::container` +use local::Choice::First; +//~^ ERROR unresolved import `local::Choice` + +mod root_module {} +use crate::root_modul::*; +//~^ ERROR unresolved import `crate::root_modul` + +macro_rules! import { + ($module:ident) => { use local::$module::Item as MacroItem; }; +} +import!(collection); +//~^ ERROR unresolved import `local::collection` + +mod accessible { + pub mod collections { + pub struct Item; + } + use collections as collection; +} +// The closer match is a private alias, so suggest the accessible module instead. +use accessible::collectio::Item as AccessibleItem; +//~^ ERROR unresolved import `accessible::collectio` + +fn main() {} diff --git a/tests/ui/imports/nested-module-typo-issue-131366.stderr b/tests/ui/imports/nested-module-typo-issue-131366.stderr new file mode 100644 index 0000000000000..1173fc1fb5c57 --- /dev/null +++ b/tests/ui/imports/nested-module-typo-issue-131366.stderr @@ -0,0 +1,80 @@ +error[E0432]: unresolved import `std::collection` + --> $DIR/nested-module-typo-issue-131366.rs:8:10 + | +LL | use std::collection::HashMap; + | ^^^^^^^^^^ could not find `collection` in `std` + | +help: a module with a similar name exists + | +LL | use std::collections::HashMap; + | + + +error[E0432]: unresolved import `local::collection` + --> $DIR/nested-module-typo-issue-131366.rs:19:12 + | +LL | use local::collection::Item; + | ^^^^^^^^^^ could not find `collection` in `local` + | +help: a module with a similar name exists + | +LL | use local::collections::Item; + | + + +error[E0432]: unresolved import `local::container` + --> $DIR/nested-module-typo-issue-131366.rs:21:12 + | +LL | use local::container::Item as Alias; + | ^^^^^^^^^ could not find `container` in `local` + | +help: a module with a similar name exists + | +LL | use local::containers::Item as Alias; + | + + +error[E0432]: unresolved import `local::Choice` + --> $DIR/nested-module-typo-issue-131366.rs:23:12 + | +LL | use local::Choice::First; + | ^^^^^^ could not find `Choice` in `local` + | +help: an enum with a similar name exists + | +LL | use local::Choices::First; + | + + +error[E0432]: unresolved import `accessible::collectio` + --> $DIR/nested-module-typo-issue-131366.rs:43:17 + | +LL | use accessible::collectio::Item as AccessibleItem; + | ^^^^^^^^^ could not find `collectio` in `accessible` + | +help: a module with a similar name exists + | +LL | use accessible::collections::Item as AccessibleItem; + | ++ + +error[E0432]: unresolved import `crate::root_modul` + --> $DIR/nested-module-typo-issue-131366.rs:27:12 + | +LL | use crate::root_modul::*; + | ^^^^^^^^^^ could not find `root_modul` in the crate root + | +help: a module with a similar name exists + | +LL | use crate::root_module::*; + | + + +error[E0432]: unresolved import `local::collection` + --> $DIR/nested-module-typo-issue-131366.rs:33:9 + | +LL | import!(collection); + | ^^^^^^^^^^ could not find `collection` in `local` + | +help: a module with a similar name exists + | +LL | import!(collections); + | + + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/linkage-attr/auxiliary/def_external.rs b/tests/ui/linkage-attr/auxiliary/def_external.rs deleted file mode 100644 index 2300930e513af..0000000000000 --- a/tests/ui/linkage-attr/auxiliary/def_external.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(linkage)] -#![crate_type = "lib"] - -#[linkage="external"] -pub static EXTERN: u32 = 0; diff --git a/tests/ui/linkage-attr/auxiliary/def_weak.rs b/tests/ui/linkage-attr/auxiliary/def_weak.rs new file mode 100644 index 0000000000000..a8940f73c5536 --- /dev/null +++ b/tests/ui/linkage-attr/auxiliary/def_weak.rs @@ -0,0 +1,5 @@ +#![feature(linkage)] +#![crate_type = "lib"] + +#[linkage = "weak"] +pub static WEAK: u32 = 0; diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs deleted file mode 100644 index 512616251c2f7..0000000000000 --- a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ build-fail -//@ failure-status: 101 -//@ known-bug: #109681 -//@ ignore-wasm32 this appears to SIGABRT on wasm, not fail cleanly -//@ compile-flags: -Z verify-llvm-ir -//@ ignore-backends: gcc - -// This test verifies that we continue to hit the LLVM error for common linkage with non-zero -// initializers, since it generates invalid LLVM IR. -// Linkages are internal features marked as perma-unstable, so we don't need to fix the issue -// for now. -#![crate_type="lib"] -#![feature(linkage)] - -#[linkage = "common"] -#[no_mangle] -pub static TEST: bool = true; diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr deleted file mode 100644 index 93015bb2bac12..0000000000000 --- a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr +++ /dev/null @@ -1,3 +0,0 @@ -'common' global must have a zero initializer! -ptr @TEST -rustc-LLVM ERROR: Broken module found, compilation aborted! diff --git a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs index 0717a2d5a6c9e..eb8a1a71ed17f 100644 --- a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs +++ b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs @@ -1,15 +1,8 @@ //@ run-pass //@ ignore-apple -//@ ignore-wasm32 common linkage not implemented right now #![feature(linkage)] -#[linkage = "external"] -pub static TEST2: bool = true; - -#[linkage = "internal"] -pub static TEST3: bool = true; - #[cfg(not(target_env = "msvc"))] #[linkage = "linkonce"] pub static TEST4: bool = true; diff --git a/tests/ui/linkage-attr/linkage-import.rs b/tests/ui/linkage-attr/linkage-import.rs index 838d1fc29a238..51fcf1c133f32 100644 --- a/tests/ui/linkage-attr/linkage-import.rs +++ b/tests/ui/linkage-attr/linkage-import.rs @@ -1,8 +1,8 @@ //@ build-pass -//@ aux-build:def_external.rs +//@ aux-build:def_weak.rs -extern crate def_external as dep; +extern crate def_weak as dep; fn main() { - println!("{:p}", &dep::EXTERN); + println!("{:p}", &dep::WEAK); } diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr index aa25cd39ba291..616f80df09c8b 100644 --- a/tests/ui/linkage-attr/linkage3.stderr +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -4,7 +4,7 @@ error[E0539]: malformed `linkage` attribute input LL | #[linkage = "foo"] | ^^^^^^^^^^----- | | - | valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `internal`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` + | valid arguments are `available_externally`, `extern_weak`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/linkage4.rs b/tests/ui/linkage-attr/linkage4.rs index 3b935f9723dc1..25df81189d8f5 100644 --- a/tests/ui/linkage-attr/linkage4.rs +++ b/tests/ui/linkage-attr/linkage4.rs @@ -1,4 +1,4 @@ -#[linkage = "external"] +#[linkage = "weak"] static foo: isize = 0; //~^^ ERROR: the `linkage` attribute is experimental and not portable diff --git a/tests/ui/linkage-attr/linkage4.stderr b/tests/ui/linkage-attr/linkage4.stderr index a5970d100581a..2f04ceee5199d 100644 --- a/tests/ui/linkage-attr/linkage4.stderr +++ b/tests/ui/linkage-attr/linkage4.stderr @@ -1,7 +1,7 @@ error[E0658]: the `linkage` attribute is experimental and not portable across platforms --> $DIR/linkage4.rs:1:3 | -LL | #[linkage = "external"] +LL | #[linkage = "weak"] | ^^^^^^^ | = note: see issue #29603 for more information diff --git a/tests/ui/lint/inline-exported.rs b/tests/ui/lint/inline-exported.rs index 6a23cd58236ff..25ca5f0633079 100644 --- a/tests/ui/lint/inline-exported.rs +++ b/tests/ui/lint/inline-exported.rs @@ -17,12 +17,8 @@ fn export_name() {} #[inline] //~^ ERROR: `#[inline]` is ignored on externally exported functions -#[linkage = "external"] -fn external_linkage() {} +#[linkage = "weak"] +fn weak_linkage() {} #[inline] fn normal() {} - -#[inline] -#[linkage = "internal"] // not exported -fn internal_linkage() {} diff --git a/tests/ui/lint/unused/must-use-box-from-raw.stderr b/tests/ui/lint/unused/must-use-box-from-raw.stderr index 4898db7fe3ddd..7eab99e97cd82 100644 --- a/tests/ui/lint/unused/must-use-box-from-raw.stderr +++ b/tests/ui/lint/unused/must-use-box-from-raw.stderr @@ -10,10 +10,10 @@ note: the lint level is defined here | LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = Box::from_raw(ptr); - | +++++++ +LL | let _unused = Box::from_raw(ptr); + | +++++++++++++ warning: 1 warning emitted diff --git a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.fixed b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.fixed new file mode 100644 index 0000000000000..13289df3677fd --- /dev/null +++ b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.fixed @@ -0,0 +1,41 @@ +//@ run-rustfix +//! Regression test for https://github.com/rust-lang/rust/issues/162843. +//! Must-use values with nontrivial drop should suggest a binding that preserves drop timing. +#![deny(unused_must_use)] + +use std::sync::Mutex; + +struct Guard; + +impl Drop for Guard { + fn drop(&mut self) {} +} + +#[must_use] +fn guard() -> Guard { + Guard +} + +#[must_use] +fn value() -> u8 { + 0 +} + +#[must_use] +fn vec_values() -> Vec { + vec![1, 2, 3] +} + +#[must_use] +fn box_value() -> Box { + Box::new(0) +} + +fn main() { + let mutex = Mutex::new(0); + let _unused = mutex.lock().unwrap(); //~ ERROR unused `std::sync::MutexGuard` that must be used + let _unused = guard(); //~ ERROR unused return value of `guard` that must be used + let _ = value(); //~ ERROR unused return value of `value` that must be used + let _ = vec_values(); //~ ERROR unused return value of `vec_values` that must be used + let _ = box_value(); //~ ERROR unused return value of `box_value` that must be used +} diff --git a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs new file mode 100644 index 0000000000000..1b0de8242a7a7 --- /dev/null +++ b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs @@ -0,0 +1,41 @@ +//@ run-rustfix +//! Regression test for https://github.com/rust-lang/rust/issues/162843. +//! Must-use values with nontrivial drop should suggest a binding that preserves drop timing. +#![deny(unused_must_use)] + +use std::sync::Mutex; + +struct Guard; + +impl Drop for Guard { + fn drop(&mut self) {} +} + +#[must_use] +fn guard() -> Guard { + Guard +} + +#[must_use] +fn value() -> u8 { + 0 +} + +#[must_use] +fn vec_values() -> Vec { + vec![1, 2, 3] +} + +#[must_use] +fn box_value() -> Box { + Box::new(0) +} + +fn main() { + let mutex = Mutex::new(0); + mutex.lock().unwrap(); //~ ERROR unused `std::sync::MutexGuard` that must be used + guard(); //~ ERROR unused return value of `guard` that must be used + value(); //~ ERROR unused return value of `value` that must be used + vec_values(); //~ ERROR unused return value of `vec_values` that must be used + box_value(); //~ ERROR unused return value of `box_value` that must be used +} diff --git a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr new file mode 100644 index 0000000000000..8fa5c693f2561 --- /dev/null +++ b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr @@ -0,0 +1,63 @@ +error: unused `std::sync::MutexGuard` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:36:5 + | +LL | mutex.lock().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: if unused the Mutex will immediately unlock +note: the lint level is defined here + --> $DIR/must-use-lock-guard-issue-162843.rs:4:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately + | +LL | let _unused = mutex.lock().unwrap(); + | +++++++++++++ + +error: unused return value of `guard` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:37:5 + | +LL | guard(); + | ^^^^^^^ + | +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately + | +LL | let _unused = guard(); + | +++++++++++++ + +error: unused return value of `value` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:38:5 + | +LL | value(); + | ^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = value(); + | +++++++ + +error: unused return value of `vec_values` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:39:5 + | +LL | vec_values(); + | ^^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = vec_values(); + | +++++++ + +error: unused return value of `box_value` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:40:5 + | +LL | box_value(); + | ^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = box_value(); + | +++++++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr index 230c97092b526..13c51a588fb03 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr @@ -75,10 +75,10 @@ LL | self.generate(); | ^^^^^^^^^^^^^^^ | = note: this `Result` may be an `Err` variant, which should be handled -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = self.generate(); - | +++++++ +LL | let _unused = self.generate(); + | +++++++++++++ error: aborting due to 7 previous errors diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr index e93a40658f3c2..43bc73d2758c1 100644 --- a/tests/ui/lint/unused/unused-async.stderr +++ b/tests/ui/lint/unused/unused-async.stderr @@ -17,10 +17,10 @@ error: unused return value of `foo` that must be used LL | foo(); | ^^^^^ | -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = foo(); - | +++++++ +LL | let _unused = foo(); + | +++++++++++++ error: unused output of future returned by `foo` that must be used --> $DIR/unused-async.rs:33:5 @@ -47,10 +47,10 @@ error: unused return value of `bar` that must be used LL | bar(); | ^^^^^ | -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = bar(); - | +++++++ +LL | let _unused = bar(); + | +++++++++++++ error: unused implementer of `Future` that must be used --> $DIR/unused-async.rs:37:5 diff --git a/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr b/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr index 8c3451af7235f..6d36dbdee7ba4 100644 --- a/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr +++ b/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr @@ -6,15 +6,15 @@ LL | assert_ne!(buf, b"----"); | = help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]` = help: the following other types implement trait `PartialEq`: + `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` + `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - `&[u8]` implements `PartialEq` - `&mut [T]` implements `PartialEq>` - and 13 others + and 18 others error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]` --> $DIR/assert-ne-no-invalid-help-issue-146204.rs:19:5 @@ -24,15 +24,15 @@ LL | assert_eq!(buf, b"----"); | = help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]` = help: the following other types implement trait `PartialEq`: + `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` + `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - `&[u8]` implements `PartialEq` - `&mut [T]` implements `PartialEq>` - and 13 others + and 18 others error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]` --> $DIR/assert-ne-no-invalid-help-issue-146204.rs:5:30 diff --git a/tests/ui/unresolved/unresolved-import.fixed b/tests/ui/unresolved/unresolved-import.fixed new file mode 100644 index 0000000000000..2132e5e21859f --- /dev/null +++ b/tests/ui/unresolved/unresolved-import.fixed @@ -0,0 +1,70 @@ +//@ edition:2015 +//@ run-rustfix + +#![allow(unused_imports, dead_code)] + +use food::beans; +//~^ ERROR unresolved import `foo` [E0432] +//~| NOTE could not find `foo` in the crate root +//~| HELP a module with a similar name exists +//~| SUGGESTION food + +use bar::Bar as x; +//~^ ERROR unresolved import `bar::Baz` [E0432] +//~| NOTE no `Baz` in `bar` +//~| HELP a similar name exists in the module +//~| SUGGESTION Bar + +use food::bag; +//~^ ERROR unresolved import `food::baz` +//~| NOTE no `baz` in `food` +//~| HELP a similar name exists in the module +//~| SUGGESTION bag + +use food::{beans as Foo}; +//~^ ERROR unresolved import `food::beens` [E0432] +//~| NOTE no `beens` in `food` +//~| HELP a similar name exists in the module +//~| SUGGESTION beans + +mod bar { + pub struct Bar; +} + +mod food { + pub use self::zug::baz::{self as bag, Foobar as beans}; + + mod zug { + pub mod baz { + //~^ NOTE module `food::zug::baz` exists but is inaccessible + //~| NOTE not accessible + pub struct Foobar; + } + } +} + +mod m { + enum MyEnum { + MyVariant + } + + use self::MyEnum::*; + //~^ ERROR unresolved import `MyEnum` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::MyEnum +} + +mod items { + enum Enum { + Variant + } + + use self::Enum::*; + //~^ ERROR unresolved import `Enum` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::Enum + + fn item() {} +} + +fn main() {} diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs index 8795a5342b2fd..ce9bf73537492 100644 --- a/tests/ui/unresolved/unresolved-import.rs +++ b/tests/ui/unresolved/unresolved-import.rs @@ -1,9 +1,13 @@ //@ edition:2015 -use foo::bar; +//@ run-rustfix + +#![allow(unused_imports, dead_code)] + +use foo::beans; //~^ ERROR unresolved import `foo` [E0432] -//~| NOTE use of unresolved module or unlinked crate `foo` -//~| HELP you might be missing a crate named `foo` -//~| SUGGESTION extern crate foo; +//~| NOTE could not find `foo` in the crate root +//~| HELP a module with a similar name exists +//~| SUGGESTION food use bar::Baz as x; //~^ ERROR unresolved import `bar::Baz` [E0432] diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr index a5704787688a9..7aac9dc683349 100644 --- a/tests/ui/unresolved/unresolved-import.stderr +++ b/tests/ui/unresolved/unresolved-import.stderr @@ -1,16 +1,16 @@ error[E0432]: unresolved import `foo` - --> $DIR/unresolved-import.rs:2:5 + --> $DIR/unresolved-import.rs:6:5 | -LL | use foo::bar; - | ^^^ use of unresolved module or unlinked crate `foo` +LL | use foo::beans; + | ^^^ could not find `foo` in the crate root | -help: you might be missing a crate named `foo`, add it to your project and import it in your code - | -LL + extern crate foo; +help: a module with a similar name exists | +LL | use food::beans; + | + error[E0432]: unresolved import `bar::Baz` - --> $DIR/unresolved-import.rs:8:5 + --> $DIR/unresolved-import.rs:12:5 | LL | use bar::Baz as x; | ^^^^^---^^^^^ @@ -24,7 +24,7 @@ LL + use bar::Bar as x; | error[E0432]: unresolved import `food::baz` - --> $DIR/unresolved-import.rs:14:5 + --> $DIR/unresolved-import.rs:18:5 | LL | use food::baz; | ^^^^^^--- @@ -32,7 +32,7 @@ LL | use food::baz; | no `baz` in `food` | note: module `food::zug::baz` exists but is inaccessible - --> $DIR/unresolved-import.rs:34:9 + --> $DIR/unresolved-import.rs:38:9 | LL | pub mod baz { | ^^^^^^^^^^^ not accessible @@ -43,7 +43,7 @@ LL + use food::bag; | error[E0432]: unresolved import `food::beens` - --> $DIR/unresolved-import.rs:20:12 + --> $DIR/unresolved-import.rs:24:12 | LL | use food::{beens as Foo}; | -----^^^^^^^ @@ -57,7 +57,7 @@ LL + use food::{beans as Foo}; | error[E0432]: unresolved import `MyEnum` - --> $DIR/unresolved-import.rs:47:9 + --> $DIR/unresolved-import.rs:51:9 | LL | use MyEnum::*; | ^^^^^^ @@ -68,7 +68,7 @@ LL | use self::MyEnum::*; | ++++++ error[E0432]: unresolved import `Enum` - --> $DIR/unresolved-import.rs:58:9 + --> $DIR/unresolved-import.rs:62:9 | LL | use Enum::*; | ^^^^