diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs index 198b62d5fb475..745a2ecfc6159 100644 --- a/compiler/rustc_abi/src/callconv/reg.rs +++ b/compiler/rustc_abi/src/callconv/reg.rs @@ -69,7 +69,7 @@ impl Reg { 128 => dl.f128_align, _ => panic!("unsupported float: {self:?}"), }, - RegKind::Vector { .. } => dl.llvmlike_vector_align(self.size), + RegKind::Vector { .. } => dl.rust_vector_align(self.size), } } } diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index ad48e14430952..2218780092287 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1514,7 +1514,7 @@ where BackendRepr::SimdScalableVector { element, count, number_of_vectors }, size.checked_mul(number_of_vectors.0 as u64, dl) .ok_or_else(|| LayoutCalculatorError::SizeOverflow)?, - dl.llvmlike_vector_align(size), + dl.rust_vector_align(size), ), // Non-power-of-two vectors have padding up to the next power-of-two. // If we're a packed repr, remove the padding while keeping the alignment as close @@ -1523,7 +1523,7 @@ where (BackendRepr::Memory { sized: true }, size, Align::max_aligned_factor(size)) } SimdVectorKind::PackedFixed | SimdVectorKind::Fixed => { - (BackendRepr::SimdVector { element, count }, size, dl.llvmlike_vector_align(size)) + (BackendRepr::SimdVector { element, count }, size, dl.rust_vector_align(size)) } }; let size = size.align_to(align); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index e26b806dc7397..ad745913399d4 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -658,17 +658,25 @@ impl TargetDataLayout { /// psABI-mandated alignment for a vector type, if any #[inline] - fn cabi_vector_align(&self, vec_size: Size) -> Option { + fn c_vector_align(&self, vec_size: Size) -> Option { self.vector_align .iter() .find(|(size, _align)| *size == vec_size) .map(|(_size, align)| *align) } - /// an alignment resembling the one LLVM would pick for a vector + /// Rust-assigned alignment of any vector type + /// + /// When the shape of a vector matches that in a C psABI, we *must* agree when performing FFI. + /// This currently answers correctly for C compatibility purposes as it is a useful default. + /// Otherwise this choice is arbitrary, as vector types do not necessarily match hardware so + /// this can conjure "imaginary" answers that just happen to be convenient for us. + /// + /// Importantly, Rust vector alignment is not required to be monotonic between vector sizes, + /// even though it currently is. #[inline] - pub fn llvmlike_vector_align(&self, vec_size: Size) -> Align { - self.cabi_vector_align(vec_size) + pub fn rust_vector_align(&self, vec_size: Size) -> Align { + self.c_vector_align(vec_size) .unwrap_or(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap()) } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a84e364ffe9c0..692c178a6875c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -897,6 +897,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None => Ident::new(sym::integer(index), self.lower_span(f.span)), }, vis_span: self.lower_span(f.vis.span), + mut_restriction: self.lower_mut_restriction(&f.mut_restriction), default: f .default .as_ref() @@ -1792,11 +1793,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - pub(super) fn lower_impl_restriction( - &mut self, - r: &ImplRestriction, - ) -> &'hir hir::ImplRestriction<'hir> { - let kind = match &r.kind { + fn lower_restriction_kind(&mut self, kind: &RestrictionKind) -> hir::RestrictionKind<'hir> { + match kind { RestrictionKind::Unrestricted => hir::RestrictionKind::Unrestricted, RestrictionKind::Restricted { path, id, shorthand: _ } => { let res = self.get_partial_res(*id); @@ -1820,10 +1818,25 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::RestrictionKind::Unrestricted } } - }; + } + } + + pub(super) fn lower_impl_restriction( + &mut self, + r: &ImplRestriction, + ) -> &'hir hir::ImplRestriction<'hir> { + let kind = self.lower_restriction_kind(&r.kind); self.arena.alloc(hir::ImplRestriction { kind, span: self.lower_span(r.span) }) } + pub(super) fn lower_mut_restriction( + &mut self, + r: &MutRestriction, + ) -> &'hir hir::MutRestriction<'hir> { + let kind = self.lower_restriction_kind(&r.kind); + self.arena.alloc(hir::MutRestriction { kind, span: self.lower_span(r.span) }) + } + /// Return the pair of the lowered `generics` as `hir::Generics` and the evaluation of `f` with /// the carried impl trait definitions and bounds. #[instrument(level = "debug", skip(self, f))] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6a6d55705eaa6..eb2893c88d854 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4498,6 +4498,7 @@ pub struct PolyTraitRef<'hir> { pub struct FieldDef<'hir> { pub span: Span, pub vis_span: Span, + pub mut_restriction: &'hir MutRestriction<'hir>, pub ident: Ident, #[stable_hash(ignore)] pub hir_id: HirId, @@ -4755,6 +4756,12 @@ pub struct ImplRestriction<'hir> { pub span: Span, } +#[derive(Debug, Clone, Copy, StableHash)] +pub struct MutRestriction<'hir> { + pub kind: RestrictionKind<'hir>, + pub span: Span, +} + #[derive(Debug, Clone, Copy, StableHash)] pub enum RestrictionKind<'hir> { /// The restriction does not affect the item. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index df410d680f533..5cdf7e920949b 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1405,8 +1405,21 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>( pub fn walk_field_def<'v, V: Visitor<'v>>( visitor: &mut V, - FieldDef { hir_id, ident, ty, default, span: _, vis_span: _, def_id: _, safety: _ }: &'v FieldDef<'v>, + FieldDef { + hir_id, + ident, + ty, + default, + span: _, + vis_span: _, + mut_restriction, + def_id: _, + safety: _, + }: &'v FieldDef<'v>, ) -> V::Result { + if let RestrictionKind::Restricted(path) = mut_restriction.kind { + walk_list!(visitor, visit_path_segment, path.segments); + } try_visit!(visitor.visit_id(*hir_id)); try_visit!(visitor.visit_ident(*ident)); visit_opt!(visitor, visit_anon_const, default); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 6c5d5864a623f..393e238712960 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -901,6 +901,7 @@ impl<'a> State<'a> { self.commasep(Inconsistent, struct_def.fields(), |s, field| { s.maybe_print_comment(field.span.lo()); s.print_attrs(s.attrs(field.hir_id)); + s.print_mut_restriction(field.mut_restriction); s.print_type(field.ty); }); self.pclose(); @@ -922,6 +923,7 @@ impl<'a> State<'a> { self.hardbreak_if_not_bol(); self.maybe_print_comment(field.span.lo()); self.print_attrs(self.attrs(field.hir_id)); + self.print_mut_restriction(field.mut_restriction); self.print_ident(field.ident); self.word_nbsp(":"); self.print_type(field.ty); @@ -2655,17 +2657,29 @@ impl<'a> State<'a> { } } - fn print_impl_restriction(&mut self, r: &hir::ImplRestriction<'_>) { - match r.kind { + fn print_restriction>>( + &mut self, + k: &hir::RestrictionKind<'_>, + prefix: S, + ) { + match k { hir::RestrictionKind::Unrestricted => {} hir::RestrictionKind::Restricted(path) => { - self.word("impl("); - self.word_nbsp("in"); + self.word(prefix.into()); + self.word_nbsp("(in"); self.print_path(path, false); - self.word(")"); + self.word_nbsp(")"); } } } + + fn print_mut_restriction(&mut self, r: &hir::MutRestriction<'_>) { + self.print_restriction(&r.kind, "mut"); + } + + fn print_impl_restriction(&mut self, r: &hir::ImplRestriction<'_>) { + self.print_restriction(&r.kind, "impl"); + } } /// Does this expression require a semicolon to be treated diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 915a3abd6632e..3e2cb94dc2858 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -8,7 +8,7 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Spanned, Symbol}; use crate::Res; -use crate::late::PatternSource; +use crate::late::{PatternSource, ResolvingRestrictionKind}; #[derive(Diagnostic)] #[diag("can't use {$is_self -> @@ -546,8 +546,17 @@ pub(crate) struct ExpectedModuleFound { pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag("trait implementation can only be restricted to ancestor modules")] -pub(crate) struct RestrictionAncestorOnly(#[primary_span] pub(crate) Span); +#[diag( + "{$kind -> + [impl] trait implementation + *[mut] field mutation +} can only be restricted to ancestor modules" +)] +pub(crate) struct RestrictionAncestorOnly { + #[primary_span] + pub(crate) span: Span, + pub(crate) kind: ResolvingRestrictionKind, +} #[derive(Diagnostic)] #[diag("cannot use a tool module through an import")] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4ae56ac7c6f3d..8c375f6d26611 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -426,6 +426,23 @@ pub(crate) enum AliasPossibility { Maybe, } +/// Whether resolving `impl` or `mut` restriction paths +#[derive(Debug, Clone, Copy)] +pub(crate) enum ResolvingRestrictionKind { + Impl, + Mut, +} + +impl IntoDiagArg for ResolvingRestrictionKind { + fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { + use std::borrow::Cow; + match self { + ResolvingRestrictionKind::Impl => DiagArgValue::Str(Cow::Borrowed("impl")), + ResolvingRestrictionKind::Mut => DiagArgValue::Str(Cow::Borrowed("mut")), + } + } +} + #[derive(Copy, Clone, Debug)] pub(crate) enum PathSource<'a, 'ast, 'ra> { /// Type paths `Path`. @@ -1489,11 +1506,12 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc ty, is_placeholder: _, default, - mut_restriction: _, + mut_restriction, safety: _, } = f; walk_list!(self, visit_attribute, attrs); try_visit!(self.visit_vis(vis)); + self.resolve_restriction_path(&mut_restriction.kind, ResolvingRestrictionKind::Mut); visit_opt!(self, visit_ident, ident); try_visit!(self.visit_ty(ty)); if let Some(v) = &default { @@ -2864,7 +2882,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ItemKind::Trait(Trait { generics, bounds, items, impl_restriction, .. }) => { // resolve paths for `impl` restrictions - self.resolve_impl_restriction_path(impl_restriction); + self.resolve_restriction_path( + &impl_restriction.kind, + ResolvingRestrictionKind::Impl, + ); // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( @@ -4480,8 +4501,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } - fn resolve_impl_restriction_path(&mut self, restriction: &'ast ast::ImplRestriction) { - match &restriction.kind { + fn resolve_restriction_path( + &mut self, + restriction: &'ast ast::RestrictionKind, + kind: ResolvingRestrictionKind, + ) { + match &restriction { ast::RestrictionKind::Unrestricted => (), ast::RestrictionKind::Restricted { path, id, shorthand: _ } => { self.smart_resolve_path(*id, &None, path, PathSource::Module); @@ -4494,7 +4519,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ) { self.r .dcx() - .create_err(crate::diagnostics::RestrictionAncestorOnly(path.span)) + .create_err(crate::diagnostics::RestrictionAncestorOnly { + span: path.span, + kind, + }) .emit(); } } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index f458b3e6b68aa..6813c3bfe5859 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1810,22 +1810,22 @@ pub const unsafe fn read(src: *const T) -> T { pub const unsafe fn read_unaligned(src: *const T) -> T { // Always true thanks to the repr, but to demonstrate const { - assert!(mem::offset_of!(Packed::, 0) == 0); - assert!(size_of::() == size_of::>()); + assert!(mem::offset_of!(Unaligned::, 0) == 0); + assert!(size_of::() == size_of::>()); } - let src = src.cast::>(); + let src = src.cast::>(); // SAFETY: the caller must guarantee that `src` is valid for reads. - // Reading it as `Packed` instead of `T` reads those same bytes because + // Reading it as `Unaligned` instead of `T` reads those same bytes because // it's the same size (thus zero offset), but with alignment 1 instead. // // Similarly, because it's the same bytes it's sound to transmute from the - // `Packed` to `T`. Transmute is a value-based (not a place-based) + // `Unaligned` to `T`. Transmute is a value-based (not a place-based) // operation that doesn't care about alignment. unsafe { - let packed = read(src); + let unaligned = read(src); // Can't just destructure because that's not allowed in const fn - mem::transmute_neo(packed) + mem::transmute_neo(unaligned) } } @@ -2020,14 +2020,14 @@ pub const unsafe fn write(dst: *mut T, src: T) { pub const unsafe fn write_unaligned(dst: *mut T, src: T) { // Always true thanks to the repr, but to demonstrate const { - assert!(mem::offset_of!(Packed::, 0) == 0); - assert!(size_of::() == size_of::>()); + assert!(mem::offset_of!(Unaligned::, 0) == 0); + assert!(size_of::() == size_of::>()); } - let dst = dst.cast::>(); - let src = Packed(src); + let dst = dst.cast::>(); + let src = Unaligned(src); // SAFETY: the caller must guarantee that `dst` is valid for writes. - // Writing it as `Packed` instead of `T` writes those same bytes because + // Writing it as `Unaligned` instead of `T` writes those same bytes because // it's the same size (thus zero offset), but with alignment 1 instead. unsafe { write(dst, src) } } @@ -2828,5 +2828,7 @@ pub macro addr_of_mut($place:expr) { &raw mut $place } -#[repr(C, packed)] -struct Packed(T); +/// Used in [`read_unaligned`] and [`write_unaligned`] to load and store `T` +/// with alignment 1 rather than its usual `align_of::()` alignment. +#[repr(Rust, packed)] +struct Unaligned(T); diff --git a/tests/mir-opt/pre-codegen/unaligned.rs b/tests/mir-opt/pre-codegen/unaligned.rs index 4aeb10c261e21..ef59890b27ce6 100644 --- a/tests/mir-opt/pre-codegen/unaligned.rs +++ b/tests/mir-opt/pre-codegen/unaligned.rs @@ -24,11 +24,11 @@ pub unsafe fn unaligned_copy_generic(src: *const T, dst: *mut T) { // CHECK: debug src => _1; // CHECK: debug dst => _2; // CHECK: debug val => [[VAL:_.+]]; - // CHECK: [[SRC_P:_.+]] = copy _1 as *const {{.+}}::Packed (PtrToPtr); + // CHECK: [[SRC_P:_.+]] = copy _1 as *const {{.+}}::Unaligned (PtrToPtr); // CHECK: [[PACKED1:_.+]] = copy (*[[SRC_P]]); // CHECK: [[VAL]] = copy [[PACKED1]] as T (Transmute); - // CHECK: [[DST_P:_.+]] = copy _2 as *mut {{.+}}::Packed (PtrToPtr); - // CHECK: [[PACKED2:_.+]] = {{.+}}::Packed::(copy [[VAL]]); + // CHECK: [[DST_P:_.+]] = copy _2 as *mut {{.+}}::Unaligned (PtrToPtr); + // CHECK: [[PACKED2:_.+]] = {{.+}}::Unaligned::(copy [[VAL]]); // CHECK: (*[[DST_P]]) = copy [[PACKED2]]; // CHECK-NOT: copy_nonoverlapping // CHECK-NOT: drop diff --git a/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_generic.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_generic.runtime-optimized.after.mir index 4d0cfa6a4dfa3..ffb1fe334b201 100644 --- a/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_generic.runtime-optimized.after.mir +++ b/tests/mir-opt/pre-codegen/unaligned.unaligned_copy_generic.runtime-optimized.after.mir @@ -8,46 +8,46 @@ fn unaligned_copy_generic(_1: *const T, _2: *mut T) -> () { scope 1 { debug val => _5; scope 8 (inlined #[track_caller] write_unaligned::) { - let _6: *mut std::ptr::Packed; + let _6: *mut std::ptr::Unaligned; scope 9 { - let _7: std::ptr::Packed; + let _7: std::ptr::Unaligned; scope 10 { - scope 12 (inlined #[track_caller] std::ptr::write::>) { + scope 12 (inlined #[track_caller] std::ptr::write::>) { } } } - scope 11 (inlined std::ptr::mut_ptr::::cast::>) { + scope 11 (inlined std::ptr::mut_ptr::::cast::>) { } } } scope 2 (inlined #[track_caller] read_unaligned::) { - let _3: *const std::ptr::Packed; + let _3: *const std::ptr::Unaligned; scope 3 { - let _4: std::ptr::Packed; + let _4: std::ptr::Unaligned; scope 4 { - scope 7 (inlined transmute_neo::, T>) { + scope 7 (inlined transmute_neo::, T>) { } } - scope 6 (inlined #[track_caller] std::ptr::read::>) { + scope 6 (inlined #[track_caller] std::ptr::read::>) { } } - scope 5 (inlined std::ptr::const_ptr::::cast::>) { + scope 5 (inlined std::ptr::const_ptr::::cast::>) { } } bb0: { StorageLive(_5); StorageLive(_3); - _3 = copy _1 as *const std::ptr::Packed (PtrToPtr); + _3 = copy _1 as *const std::ptr::Unaligned (PtrToPtr); StorageLive(_4); _4 = copy (*_3); _5 = copy _4 as T (Transmute); StorageDead(_4); StorageDead(_3); StorageLive(_6); - _6 = copy _2 as *mut std::ptr::Packed (PtrToPtr); + _6 = copy _2 as *mut std::ptr::Unaligned (PtrToPtr); StorageLive(_7); - _7 = std::ptr::Packed::(copy _5); + _7 = std::ptr::Unaligned::(copy _5); (*_6) = copy _7; StorageDead(_7); StorageDead(_6); diff --git a/tests/pretty/hir-impl-restriction.pp b/tests/pretty/hir-impl-restriction.pp new file mode 100644 index 0000000000000..ce0de88ca7259 --- /dev/null +++ b/tests/pretty/hir-impl-restriction.pp @@ -0,0 +1,15 @@ +#![attr = Feature([impl_restriction#0])] +extern crate std; +#[attr = PreludeImport] +use ::std::prelude::rust_2015::*; +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-impl-restriction.pp + +impl(in crate) trait T1 { } +impl(in self) trait T2 { } + +mod a { + impl(in crate::a) trait T3 { } + impl(in super) trait T4 { } +} diff --git a/tests/pretty/hir-impl-restriction.rs b/tests/pretty/hir-impl-restriction.rs new file mode 100644 index 0000000000000..b9dbe98640037 --- /dev/null +++ b/tests/pretty/hir-impl-restriction.rs @@ -0,0 +1,12 @@ +#![feature(impl_restriction)] +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-impl-restriction.pp + +impl(crate) trait T1 {} +impl(self) trait T2 {} + +mod a { + impl(in crate::a) trait T3 {} + impl(super) trait T4 {} +} diff --git a/tests/pretty/hir-mut-restriction.pp b/tests/pretty/hir-mut-restriction.pp new file mode 100644 index 0000000000000..e5f101fc3f136 --- /dev/null +++ b/tests/pretty/hir-mut-restriction.pp @@ -0,0 +1,44 @@ +#![attr = Feature([mut_restriction#0, unsafe_fields#0])] +extern crate std; +#[attr = PreludeImport] +use ::std::prelude::rust_2015::*; +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-mut-restriction.pp + +struct FooS { + mut(in crate) x: i32, + mut(in self) y: i32, +} + +enum FooE { + Var { + mut(in crate) x: i32, + }, + Tup(mut(in self) i32), +} + +union FooU { + mut(in crate) x: i32, + mut(in self) y: i32, +} + +mod a { + struct BarS { + mut(in self) x: i32, + mut(in crate::a) y: i32, + } + struct BazS(mut(in super) i32); + + enum BarE { + Var { + mut(in super) x: i32, + }, + Tup(mut(in crate::a) i32), + } + + union BarU { + mut(in super) x: i32, + mut(in crate::a) y: i32, + } +} diff --git a/tests/pretty/hir-mut-restriction.rs b/tests/pretty/hir-mut-restriction.rs new file mode 100644 index 0000000000000..938dd8f24b852 --- /dev/null +++ b/tests/pretty/hir-mut-restriction.rs @@ -0,0 +1,43 @@ +#![feature(mut_restriction, unsafe_fields)] +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-mut-restriction.pp + +struct FooS { + pub(crate) mut(crate) x: i32, + mut(self) unsafe y: i32, +} + +enum FooE { + Var { + mut(crate) unsafe x: i32, + }, + Tup(mut(self) i32), +} + +union FooU { + pub mut(crate) unsafe x: i32, + mut(self) y: i32, +} + +mod a { + struct BarS { + pub(super) mut(self) unsafe x: i32, + mut(in crate::a) y: i32, + } + struct BazS( + pub(in crate::a) mut(super) i32, + ); + + enum BarE { + Var { + mut(super) unsafe x: i32, + }, + Tup(mut(in crate::a) i32), + } + + union BarU { + pub(crate) mut(super) unsafe x: i32, + mut(in crate::a) y: i32, + } +} diff --git a/tests/ui/mut-restriction/auxiliary/external-mut-restriction.rs b/tests/ui/mut-restriction/auxiliary/external-mut-restriction.rs new file mode 100644 index 0000000000000..7b120bfbb3a44 --- /dev/null +++ b/tests/ui/mut-restriction/auxiliary/external-mut-restriction.rs @@ -0,0 +1,11 @@ +#![feature(mut_restriction)] + +pub struct TopLevel { + pub mut(crate) x: i32, +} + +pub mod inner { + pub struct Inner { + pub mut(self) x: i32, + } +} diff --git a/tests/ui/mut-restriction/restriction-resolution-errors.rs b/tests/ui/mut-restriction/restriction-resolution-errors.rs new file mode 100644 index 0000000000000..14b43bfc5ffc8 --- /dev/null +++ b/tests/ui/mut-restriction/restriction-resolution-errors.rs @@ -0,0 +1,64 @@ +//@ aux-build: external-mut-restriction.rs +#![feature(mut_restriction)] + +extern crate external_mut_restriction as external; + +pub mod a { + pub mod b { + pub struct Foo { + pub mut(in a::b) i1: i32, //~ ERROR cannot find module or crate `a` in this scope [E0433] + pub mut(in ::std) i2: i32, //~ ERROR field mutation can only be restricted to ancestor modules + pub mut(in self::c) i3: i32, //~ ERROR field mutation can only be restricted to ancestor modules + pub mut(in super::d) i4: i32, //~ ERROR field mutation can only be restricted to ancestor modules + pub mut(in crate::c) i5: i32, //~ ERROR cannot find module `c` in the crate root [E0433] + pub mut(in super::E) i6: i32, //~ ERROR expected module, found enum `super::E` [E0577] + pub mut(in super::super::super) i7: i32, //~ ERROR too many leading `super` keywords within `crate::a::b` [E0433] + + // OK paths + pub mut(crate) i8: i32, + pub mut(self) i9: i32, + pub mut(super) i10: i32, + pub mut(in crate::a) i11: i32, + pub mut(in super::super) i12: i32, + } + pub mod c {} + } + pub mod d {} + pub enum E {} +} + +pub enum Foo { + Var { + mut(in crate::a) e1: i32, //~ ERROR field mutation can only be restricted to ancestor modules + mut(in crate::a::E) e2: i32, //~ ERROR expected module, found enum `crate::a::E` [E0577] + mut(crate) e3: i32, + mut(self) e4: i32, + mut(super) e5: i32, //~ ERROR too many leading `super` keywords within `crate` [E0433] + }, + Tup(mut(in external) i32), //~ ERROR field mutation can only be restricted to ancestor modules +} + +// Check if we can resolve `use`d paths. +pub mod m1 { + pub union Foo { + pub mut(in crate::m2) x: i32, // OK + } +} +use m1 as m2; + +pub mod m3 { + pub mod m4 { + pub struct Bar ( + pub mut(in crate::m2) i32, //~ ERROR field mutation can only be restricted to ancestor modules + pub mut(in m6) i32, // OK + pub mut(in m6::m5) i32, //~ ERROR field mutation can only be restricted to ancestor modules + pub mut(in m7) i32, //~ ERROR expected module, found enum `m7` [E0577] + ); + use crate::m3 as m6; + use crate::m3::E as m7; + } + mod m5 {} + pub enum E {} +} + +fn main() {} diff --git a/tests/ui/mut-restriction/restriction-resolution-errors.stderr b/tests/ui/mut-restriction/restriction-resolution-errors.stderr new file mode 100644 index 0000000000000..9bf1e4742a619 --- /dev/null +++ b/tests/ui/mut-restriction/restriction-resolution-errors.stderr @@ -0,0 +1,107 @@ +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:10:24 + | +LL | pub mut(in ::std) i2: i32, + | ^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:11:24 + | +LL | pub mut(in self::c) i3: i32, + | ^^^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:12:24 + | +LL | pub mut(in super::d) i4: i32, + | ^^^^^^^^ + +error[E0433]: too many leading `super` keywords within `crate::a::b` + --> $DIR/restriction-resolution-errors.rs:15:38 + | +LL | pub mut(in super::super::super) i7: i32, + | ^^^^^ this `super` would go above the crate root + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:32:16 + | +LL | mut(in crate::a) e1: i32, + | ^^^^^^^^ + +error[E0433]: too many leading `super` keywords within `crate` + --> $DIR/restriction-resolution-errors.rs:36:13 + | +LL | mut(super) e5: i32, + | ^^^^^ this `super` would go above the crate root + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:38:16 + | +LL | Tup(mut(in external) i32), + | ^^^^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:52:24 + | +LL | pub mut(in crate::m2) i32, + | ^^^^^^^^^ + +error: field mutation can only be restricted to ancestor modules + --> $DIR/restriction-resolution-errors.rs:54:24 + | +LL | pub mut(in m6::m5) i32, + | ^^^^^^ + +error[E0433]: cannot find module or crate `a` in this scope + --> $DIR/restriction-resolution-errors.rs:9:24 + | +LL | pub mut(in a::b) i1: i32, + | ^ use of unresolved module or unlinked crate `a` + | +help: there is a crate or module with a similar name + | +LL - pub mut(in a::b) i1: i32, +LL + pub mut(in c::b) i1: i32, + | +help: consider importing this module + | +LL + use a; + | + +error[E0433]: cannot find module `c` in the crate root + --> $DIR/restriction-resolution-errors.rs:13:31 + | +LL | pub mut(in crate::c) i5: i32, + | ^ not found in the crate root + +error[E0577]: expected module, found enum `super::E` + --> $DIR/restriction-resolution-errors.rs:14:24 + | +LL | pub mut(in super::E) i6: i32, + | ^^^^^^^^ not a module + +error[E0577]: expected module, found enum `crate::a::E` + --> $DIR/restriction-resolution-errors.rs:33:16 + | +LL | pub mod b { + | --------- similarly named module `b` defined here +... +LL | mut(in crate::a::E) e2: i32, + | ^^^^^^^^^^^ + | +help: a module with a similar name exists + | +LL - mut(in crate::a::E) e2: i32, +LL + mut(in crate::a::b) e2: i32, + | + +error[E0577]: expected module, found enum `m7` + --> $DIR/restriction-resolution-errors.rs:55:24 + | +LL | pub mut(in m7) i32, + | ^^ not a module + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0433, E0577. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 53ae5bc156c0b..6ffc83774e7d3 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -96,7 +96,7 @@ hir-stats - Trait 256 (NN.N%) 4 hir-stats Attribute 160 (NN.N%) 4 40 hir-stats Variant 144 (NN.N%) 2 72 hir-stats GenericArgs 144 (NN.N%) 3 48 -hir-stats FieldDef 128 (NN.N%) 2 64 +hir-stats FieldDef 144 (NN.N%) 2 72 hir-stats FnDecl 120 (NN.N%) 3 40 hir-stats Stmt 96 (NN.N%) 3 32 hir-stats - Expr 32 (NN.N%) 1 @@ -119,5 +119,5 @@ hir-stats TraitItemId 8 (NN.N%) 2 4 hir-stats ImplItemId 8 (NN.N%) 2 4 hir-stats ForeignItemId 4 (NN.N%) 1 4 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_576 172 +hir-stats Total 8_592 172 hir-stats ================================================================