diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 0931713993691..a1b29a4222579 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -107,7 +107,7 @@ pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { return false; } - let tail = tcx.struct_tail_erasing_lifetimes(ty, ParamEnv::reveal_all()); + let tail = tcx.struct_tail_for_codegen(ty, ParamEnv::reveal_all()); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 967aa53abbda5..e09cd16e89a64 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -22,7 +22,7 @@ pub(crate) fn unsized_info<'tcx>( old_info: Option, ) -> Value { let (source, target) = - fx.tcx.struct_lockstep_tails_erasing_lifetimes(source, target, ParamEnv::reveal_all()); + fx.tcx.struct_lockstep_tails_for_codegen(source, target, ParamEnv::reveal_all()); match (&source.kind(), &target.kind()) { (&ty::Array(_, len), &ty::Slice(_)) => fx .bcx diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 77e51f941508c..0f44c5dba5e55 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -12,7 +12,8 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + TyAndLayout, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_sanitizers::{cfi, kcfi}; @@ -531,7 +532,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { #[instrument(level = "trace", skip(self))] fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> { if place.layout.is_unsized() { - let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {}); + let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.param_env()); if matches!(tail.kind(), ty::Foreign(..)) { // Unsized locals and, at least conceptually, even unsized arguments must be copied // around, which requires dynamically determining their size. Therefore, we cannot diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index d51e15d12e2fc..e542aa96e8a23 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -62,7 +62,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, pointee_ty: Ty<'tcx>, ) -> Option { - let pointee_tail_ty = cx.tcx.struct_tail_erasing_lifetimes(pointee_ty, cx.param_env()); + let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env()); let layout = cx.layout_of(pointee_tail_ty); trace!( "fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})", diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f4e44e63d73cc..f1e7f87f56767 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -143,7 +143,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) -> Bx::Value { let cx = bx.cx(); let (source, target) = - cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, bx.param_env()); + cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env()); match (source.kind(), target.kind()) { (&ty::Array(_, len), &ty::Slice(_)) => { cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all())) diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 80dad79179a36..7c042c0c6219a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -91,7 +91,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { return false; } - let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env); + let tail = self.tcx().struct_tail_for_codegen(ty, param_env); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index b5f3d07d90b35..fdbdfc7e1b8b3 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -678,9 +678,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } else { // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. // (For that reason we also cannot use `unpack_dyn_trait`.) - let receiver_tail = self - .tcx - .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env); + let receiver_tail = + self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env); let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index b2f07de0ac4e2..c3d7f2234ed95 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -386,7 +386,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { // A -> A conversion let (src_pointee_ty, dest_pointee_ty) = - self.tcx.struct_lockstep_tails_erasing_lifetimes(source_ty, cast_ty, self.param_env); + self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 460f5448634b5..fadc4ee6c8a0c 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -343,7 +343,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { meta: MemPlaceMeta, pointee: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { - let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); + let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.param_env); match tail.kind() { ty::Dynamic(data, _, ty::Dyn) => { let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 528274e6abac4..5ad55968398eb 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -22,7 +22,7 @@ where }; let ty = place.ty(local_decls, tcx).ty; - let unsized_tail = || tcx.struct_tail_with_normalize(ty, |ty| ty, || {}); + let unsized_tail = || tcx.struct_tail_for_codegen(ty, param_env); match tcx.layout_of(param_env.and(ty)) { Ok(layout) if layout.align.abi <= pack diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c878095ba0d70..a9f8630741a81 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1276,7 +1276,7 @@ fn check_item_type( UnsizedHandling::Forbid => true, UnsizedHandling::Allow => false, UnsizedHandling::AllowIfForeignTail => { - let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env); + let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.param_env); !matches!(tail.kind(), ty::Foreign(_)) } }; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 8c1aa66332fc9..841d25b54cc88 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -404,8 +404,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { code: traits::ObligationCauseCode<'tcx>, ) { if !ty.references_error() { - let tail = - self.tcx.struct_tail_with_normalize(ty, |ty| self.normalize(span, ty), || {}); + let tail = self.tcx.struct_tail_with_normalize( + ty, + |ty| { + if self.next_trait_solver() { + self.try_structurally_resolve_type(span, ty) + } else { + self.normalize(span, ty) + } + }, + || {}, + ); // Sized types have static alignment, and so do slices. if tail.is_trivially_sized(self.tcx) || matches!(tail.kind(), ty::Slice(..)) { // Nothing else is required here. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index d7d27975f60a9..9204405d58f11 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -869,7 +869,7 @@ where metadata } } else { - match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { + match tcx.struct_tail_for_codegen(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()), _ => bug!("TyAndLayout::field({:?}): not applicable", this), @@ -1348,7 +1348,7 @@ impl<'tcx> TyCtxt<'tcx> { layout = layout.field(&cx, index); if !layout.is_sized() { // If it is not sized, then the tail must still have at least a known static alignment. - let tail = self.struct_tail_erasing_lifetimes(layout.ty, param_env); + let tail = self.struct_tail_for_codegen(layout.ty, param_env); if !matches!(tail.kind(), ty::Slice(..)) { bug!( "offset of not-statically-aligned field (type {:?}) cannot be computed statically", diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3cf8531bb62d5..365f434a264e2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -186,11 +186,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Should only be called if `ty` has no inference variables and does not /// need its lifetimes preserved (e.g. as part of codegen); otherwise /// normalization attempt may cause compiler bugs. - pub fn struct_tail_erasing_lifetimes( - self, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Ty<'tcx> { + pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let tcx = self; tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {}) } @@ -203,7 +199,7 @@ impl<'tcx> TyCtxt<'tcx> { /// handle `::Assoc` and `impl Trait`); pass the identity /// function to indicate no normalization should take place. /// - /// See also `struct_tail_erasing_lifetimes`, which is suitable for use + /// See also `struct_tail_for_codegen`, which is suitable for use /// during codegen. pub fn struct_tail_with_normalize( self, @@ -272,13 +268,13 @@ impl<'tcx> TyCtxt<'tcx> { /// Same as applying `struct_tail` on `source` and `target`, but only /// keeps going as long as the two types are instances of the same /// structure definitions. - /// For `(Foo>, Foo)`, the result will be `(Foo, Trait)`, + /// For `(Foo>, Foo)`, the result will be `(Foo, dyn Trait)`, /// whereas struct_tail produces `T`, and `Trait`, respectively. /// /// Should only be called if the types have no inference variables and do /// not need their lifetimes preserved (e.g., as part of codegen); otherwise, /// normalization attempt may cause compiler bugs. - pub fn struct_lockstep_tails_erasing_lifetimes( + pub fn struct_lockstep_tails_for_codegen( self, source: Ty<'tcx>, target: Ty<'tcx>, @@ -296,7 +292,7 @@ impl<'tcx> TyCtxt<'tcx> { /// For `(Foo>, Foo)`, the result will be `(Foo, Trait)`, /// whereas struct_tail produces `T`, and `Trait`, respectively. /// - /// See also `struct_lockstep_tails_erasing_lifetimes`, which is suitable for use + /// See also `struct_lockstep_tails_for_codegen`, which is suitable for use /// during codegen. pub fn struct_lockstep_tails_with_normalize( self, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index df2abf6dc9cc4..0ae635f9b73e5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1019,7 +1019,7 @@ fn find_vtable_types_for_unsizing<'tcx>( if ty.is_sized(tcx.tcx, param_env) { return false; } - let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env); + let tail = tcx.struct_tail_for_codegen(ty, param_env); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, @@ -1029,7 +1029,7 @@ fn find_vtable_types_for_unsizing<'tcx>( if type_has_metadata(inner_source) { (inner_source, inner_target) } else { - tcx.struct_lockstep_tails_erasing_lifetimes(inner_source, inner_target, param_env) + tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, param_env) } }; diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index f1675f80717f0..d90c3bedc7017 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -549,7 +549,7 @@ fn fn_abi_sanity_check<'tcx>( // With metadata. Must be unsized and not on the stack. assert!(arg.layout.is_unsized() && !on_stack); // Also, must not be `extern` type. - let tail = cx.tcx.struct_tail_with_normalize(arg.layout.ty, |ty| ty, || {}); + let tail = cx.tcx.struct_tail_for_codegen(arg.layout.ty, cx.param_env()); if matches!(tail.kind(), ty::Foreign(..)) { // These types do not have metadata, so having `meta_attrs` is bogus. // Conceptually, unsized arguments must be copied around, which requires dynamically diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 3ef10f4e43c4b..1eb03fc3bd6a1 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -244,7 +244,7 @@ fn layout_of_uncached<'tcx>( metadata } else { - let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); + let unsized_part = tcx.struct_tail_for_codegen(pointee, param_env); match unsized_part.kind() { ty::Foreign(..) => { diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index f206b2ceebcb1..553af913ef9df 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -142,7 +142,7 @@ fn check_rvalue<'tcx>( // We cannot allow this for now. return Err((span, "unsizing casts are only allowed for references right now".into())); }; - let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id)); + let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, tcx.param_env(def_id)); if let ty::Slice(_) | ty::Str = unsized_ty.kind() { check_operand(tcx, op, span, body, msrv)?; // Casting/coercing things to slices is fine. diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.current.stderr similarity index 93% rename from tests/ui/lint/unaligned_references.stderr rename to tests/ui/lint/unaligned_references.current.stderr index 328cafbd9864b..0f980c5301f37 100644 --- a/tests/ui/lint/unaligned_references.stderr +++ b/tests/ui/lint/unaligned_references.current.stderr @@ -1,5 +1,5 @@ error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:28:13 + --> $DIR/unaligned_references.rs:32:13 | LL | &self.x; | ^^^^^^^ @@ -9,7 +9,7 @@ LL | &self.x; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:40:24 + --> $DIR/unaligned_references.rs:44:24 | LL | println!("{:?}", &*foo.0); | ^^^^^ @@ -19,7 +19,7 @@ LL | println!("{:?}", &*foo.0); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:42:24 + --> $DIR/unaligned_references.rs:46:24 | LL | println!("{:?}", &*foo.0); | ^^^^^ @@ -29,7 +29,7 @@ LL | println!("{:?}", &*foo.0); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:47:24 + --> $DIR/unaligned_references.rs:51:24 | LL | println!("{:?}", &*foo.0); | ^^^^^ @@ -39,7 +39,7 @@ LL | println!("{:?}", &*foo.0); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:57:17 + --> $DIR/unaligned_references.rs:81:17 | LL | let _ = &good.ptr; | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = &good.ptr; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:58:17 + --> $DIR/unaligned_references.rs:82:17 | LL | let _ = &good.data; | ^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | let _ = &good.data; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:60:17 + --> $DIR/unaligned_references.rs:84:17 | LL | let _ = &good.data as *const _; | ^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | let _ = &good.data as *const _; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:61:27 + --> $DIR/unaligned_references.rs:85:27 | LL | let _: *const _ = &good.data; | ^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | let _: *const _ = &good.data; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:63:17 + --> $DIR/unaligned_references.rs:87:17 | LL | let _ = good.data.clone(); | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = good.data.clone(); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:65:17 + --> $DIR/unaligned_references.rs:89:17 | LL | let _ = &good.data2[0]; | ^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | let _ = &good.data2[0]; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:74:17 + --> $DIR/unaligned_references.rs:98:17 | LL | let _ = &packed2.x; | ^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | let _ = &packed2.x; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:113:20 + --> $DIR/unaligned_references.rs:137:20 | LL | let _ref = &m1.1.a; | ^^^^^^^ @@ -119,7 +119,7 @@ LL | let _ref = &m1.1.a; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:116:20 + --> $DIR/unaligned_references.rs:140:20 | LL | let _ref = &m2.1.a; | ^^^^^^^ diff --git a/tests/ui/lint/unaligned_references.next.stderr b/tests/ui/lint/unaligned_references.next.stderr new file mode 100644 index 0000000000000..0f980c5301f37 --- /dev/null +++ b/tests/ui/lint/unaligned_references.next.stderr @@ -0,0 +1,133 @@ +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:32:13 + | +LL | &self.x; + | ^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:44:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:46:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:51:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:81:17 + | +LL | let _ = &good.ptr; + | ^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:82:17 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:84:17 + | +LL | let _ = &good.data as *const _; + | ^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:85:27 + | +LL | let _: *const _ = &good.data; + | ^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:87:17 + | +LL | let _ = good.data.clone(); + | ^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:89:17 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:98:17 + | +LL | let _ = &packed2.x; + | ^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:137:20 + | +LL | let _ref = &m1.1.a; + | ^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:140:20 + | +LL | let _ref = &m2.1.a; + | ^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0793`. diff --git a/tests/ui/lint/unaligned_references.rs b/tests/ui/lint/unaligned_references.rs index 3f6dab35475e8..321e3ed135c47 100644 --- a/tests/ui/lint/unaligned_references.rs +++ b/tests/ui/lint/unaligned_references.rs @@ -1,5 +1,9 @@ -use std::mem::ManuallyDrop; +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + use std::fmt::Debug; +use std::mem::ManuallyDrop; #[repr(packed)] pub struct Good { @@ -50,6 +54,26 @@ fn packed_dyn() { println!("{:?}", &*foo.0); // no error! } +// Test for #115396 +fn packed_slice_behind_alias() { + trait Mirror { + type Assoc: ?Sized; + } + impl Mirror for T { + type Assoc = T; + } + + struct W(::Assoc); + + #[repr(packed)] + struct Unaligned(ManuallyDrop>); + + // Even if the actual alignment is 1, we cannot know that when looking at `dyn Debug.` + let ref local: Unaligned<[_; 3]> = Unaligned(ManuallyDrop::new(W([3, 5, 8u8]))); + let foo: &Unaligned<[u8]> = local; + let x = &foo.0; // Fine, since the tail of `foo` is `[_]` +} + fn main() { unsafe { let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] }; diff --git a/tests/ui/offset-of/offset-of-slice-normalized.rs b/tests/ui/offset-of/offset-of-slice-normalized.rs new file mode 100644 index 0000000000000..9d1fd9dd2ee14 --- /dev/null +++ b/tests/ui/offset-of/offset-of-slice-normalized.rs @@ -0,0 +1,37 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ run-pass + +#![feature(offset_of_slice)] + +use std::mem::offset_of; + +trait Mirror { + type Assoc: ?Sized; +} +impl Mirror for T { + type Assoc = T; +} + +#[repr(C)] +struct S { + a: u8, + b: (u8, u8), + c: <[i32] as Mirror>::Assoc, +} + +#[repr(C)] +struct T { + x: i8, + y: S, +} + +type Tup = (i16, <[i32] as Mirror>::Assoc); + +fn main() { + assert_eq!(offset_of!(S, c), 4); + assert_eq!(offset_of!(T, y), 4); + assert_eq!(offset_of!(T, y.c), 8); + assert_eq!(offset_of!(Tup, 1), 4); +}