Auto merge of #128703 - compiler-errors:normalizing-tails, r=lcnr
Miscellaneous improvements to struct tail normalization 1. Make checks for foreign tails more accurate by normalizing the struct tail. I didn't write a test for this one. 2. Normalize when computing struct tail for `offset_of` for slice/str. This fixes the new solver only. 3. Normalizing when computing tails for disaligned reference check. This fixes both solvers. r? lcnr
This commit is contained in:
commit
899eb03926
22 changed files with 245 additions and 46 deletions
|
@ -107,7 +107,7 @@ pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
return false;
|
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() {
|
match tail.kind() {
|
||||||
ty::Foreign(..) => false,
|
ty::Foreign(..) => false,
|
||||||
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
|
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) fn unsized_info<'tcx>(
|
||||||
old_info: Option<Value>,
|
old_info: Option<Value>,
|
||||||
) -> Value {
|
) -> Value {
|
||||||
let (source, target) =
|
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()) {
|
match (&source.kind(), &target.kind()) {
|
||||||
(&ty::Array(_, len), &ty::Slice(_)) => fx
|
(&ty::Array(_, len), &ty::Slice(_)) => fx
|
||||||
.bcx
|
.bcx
|
||||||
|
|
|
@ -12,7 +12,8 @@ use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||||
use rustc_middle::ty::layout::{
|
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_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||||
use rustc_sanitizers::{cfi, kcfi};
|
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))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
|
fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
|
||||||
if place.layout.is_unsized() {
|
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(..)) {
|
if matches!(tail.kind(), ty::Foreign(..)) {
|
||||||
// Unsized locals and, at least conceptually, even unsized arguments must be copied
|
// Unsized locals and, at least conceptually, even unsized arguments must be copied
|
||||||
// around, which requires dynamically determining their size. Therefore, we cannot
|
// around, which requires dynamically determining their size. Therefore, we cannot
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
pointee_ty: Ty<'tcx>,
|
pointee_ty: Ty<'tcx>,
|
||||||
) -> Option<FatPtrKind> {
|
) -> Option<FatPtrKind> {
|
||||||
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);
|
let layout = cx.layout_of(pointee_tail_ty);
|
||||||
trace!(
|
trace!(
|
||||||
"fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
"fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
||||||
|
|
|
@ -143,7 +143,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
) -> Bx::Value {
|
) -> Bx::Value {
|
||||||
let cx = bx.cx();
|
let cx = bx.cx();
|
||||||
let (source, target) =
|
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()) {
|
match (source.kind(), target.kind()) {
|
||||||
(&ty::Array(_, len), &ty::Slice(_)) => {
|
(&ty::Array(_, len), &ty::Slice(_)) => {
|
||||||
cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
|
cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
|
||||||
|
|
|
@ -91,7 +91,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
|
||||||
return false;
|
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() {
|
match tail.kind() {
|
||||||
ty::Foreign(..) => false,
|
ty::Foreign(..) => false,
|
||||||
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
|
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
|
||||||
|
|
|
@ -678,9 +678,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
} else {
|
} else {
|
||||||
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
|
// 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`.)
|
// (For that reason we also cannot use `unpack_dyn_trait`.)
|
||||||
let receiver_tail = self
|
let receiver_tail =
|
||||||
.tcx
|
self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env);
|
||||||
.struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
|
|
||||||
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
|
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
self.cur_span(),
|
self.cur_span(),
|
||||||
|
|
|
@ -386,7 +386,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
// A<Struct> -> A<Trait> conversion
|
// A<Struct> -> A<Trait> conversion
|
||||||
let (src_pointee_ty, dest_pointee_ty) =
|
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()) {
|
match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) {
|
||||||
(&ty::Array(_, length), &ty::Slice(_)) => {
|
(&ty::Array(_, length), &ty::Slice(_)) => {
|
||||||
|
|
|
@ -343,7 +343,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
||||||
meta: MemPlaceMeta<M::Provenance>,
|
meta: MemPlaceMeta<M::Provenance>,
|
||||||
pointee: TyAndLayout<'tcx>,
|
pointee: TyAndLayout<'tcx>,
|
||||||
) -> InterpResult<'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() {
|
match tail.kind() {
|
||||||
ty::Dynamic(data, _, ty::Dyn) => {
|
ty::Dynamic(data, _, ty::Dyn) => {
|
||||||
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
|
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
|
||||||
|
|
|
@ -22,7 +22,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty = place.ty(local_decls, tcx).ty;
|
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)) {
|
match tcx.layout_of(param_env.and(ty)) {
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
if layout.align.abi <= pack
|
if layout.align.abi <= pack
|
||||||
|
|
|
@ -1276,7 +1276,7 @@ fn check_item_type(
|
||||||
UnsizedHandling::Forbid => true,
|
UnsizedHandling::Forbid => true,
|
||||||
UnsizedHandling::Allow => false,
|
UnsizedHandling::Allow => false,
|
||||||
UnsizedHandling::AllowIfForeignTail => {
|
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(_))
|
!matches!(tail.kind(), ty::Foreign(_))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -404,8 +404,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
code: traits::ObligationCauseCode<'tcx>,
|
code: traits::ObligationCauseCode<'tcx>,
|
||||||
) {
|
) {
|
||||||
if !ty.references_error() {
|
if !ty.references_error() {
|
||||||
let tail =
|
let tail = self.tcx.struct_tail_with_normalize(
|
||||||
self.tcx.struct_tail_with_normalize(ty, |ty| self.normalize(span, ty), || {});
|
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.
|
// Sized types have static alignment, and so do slices.
|
||||||
if tail.is_trivially_sized(self.tcx) || matches!(tail.kind(), ty::Slice(..)) {
|
if tail.is_trivially_sized(self.tcx) || matches!(tail.kind(), ty::Slice(..)) {
|
||||||
// Nothing else is required here.
|
// Nothing else is required here.
|
||||||
|
|
|
@ -869,7 +869,7 @@ where
|
||||||
metadata
|
metadata
|
||||||
}
|
}
|
||||||
} else {
|
} 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::Slice(_) | ty::Str => tcx.types.usize,
|
||||||
ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()),
|
ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()),
|
||||||
_ => bug!("TyAndLayout::field({:?}): not applicable", this),
|
_ => bug!("TyAndLayout::field({:?}): not applicable", this),
|
||||||
|
@ -1348,7 +1348,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
layout = layout.field(&cx, index);
|
layout = layout.field(&cx, index);
|
||||||
if !layout.is_sized() {
|
if !layout.is_sized() {
|
||||||
// If it is not sized, then the tail must still have at least a known static alignment.
|
// 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(..)) {
|
if !matches!(tail.kind(), ty::Slice(..)) {
|
||||||
bug!(
|
bug!(
|
||||||
"offset of not-statically-aligned field (type {:?}) cannot be computed statically",
|
"offset of not-statically-aligned field (type {:?}) cannot be computed statically",
|
||||||
|
|
|
@ -186,11 +186,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Should only be called if `ty` has no inference variables and does not
|
/// Should only be called if `ty` has no inference variables and does not
|
||||||
/// need its lifetimes preserved (e.g. as part of codegen); otherwise
|
/// need its lifetimes preserved (e.g. as part of codegen); otherwise
|
||||||
/// normalization attempt may cause compiler bugs.
|
/// normalization attempt may cause compiler bugs.
|
||||||
pub fn struct_tail_erasing_lifetimes(
|
pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
|
||||||
self,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
) -> Ty<'tcx> {
|
|
||||||
let tcx = self;
|
let tcx = self;
|
||||||
tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {})
|
tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {})
|
||||||
}
|
}
|
||||||
|
@ -203,7 +199,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
|
/// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
|
||||||
/// function to indicate no normalization should take place.
|
/// 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.
|
/// during codegen.
|
||||||
pub fn struct_tail_with_normalize(
|
pub fn struct_tail_with_normalize(
|
||||||
self,
|
self,
|
||||||
|
@ -272,13 +268,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Same as applying `struct_tail` on `source` and `target`, but only
|
/// Same as applying `struct_tail` on `source` and `target`, but only
|
||||||
/// keeps going as long as the two types are instances of the same
|
/// keeps going as long as the two types are instances of the same
|
||||||
/// structure definitions.
|
/// structure definitions.
|
||||||
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
|
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, dyn Trait)`,
|
||||||
/// whereas struct_tail produces `T`, and `Trait`, respectively.
|
/// whereas struct_tail produces `T`, and `Trait`, respectively.
|
||||||
///
|
///
|
||||||
/// Should only be called if the types have no inference variables and do
|
/// 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,
|
/// not need their lifetimes preserved (e.g., as part of codegen); otherwise,
|
||||||
/// normalization attempt may cause compiler bugs.
|
/// normalization attempt may cause compiler bugs.
|
||||||
pub fn struct_lockstep_tails_erasing_lifetimes(
|
pub fn struct_lockstep_tails_for_codegen(
|
||||||
self,
|
self,
|
||||||
source: Ty<'tcx>,
|
source: Ty<'tcx>,
|
||||||
target: Ty<'tcx>,
|
target: Ty<'tcx>,
|
||||||
|
@ -296,7 +292,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
|
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
|
||||||
/// whereas struct_tail produces `T`, and `Trait`, respectively.
|
/// 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.
|
/// during codegen.
|
||||||
pub fn struct_lockstep_tails_with_normalize(
|
pub fn struct_lockstep_tails_with_normalize(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -1019,7 +1019,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
|
||||||
if ty.is_sized(tcx.tcx, param_env) {
|
if ty.is_sized(tcx.tcx, param_env) {
|
||||||
return false;
|
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() {
|
match tail.kind() {
|
||||||
ty::Foreign(..) => false,
|
ty::Foreign(..) => false,
|
||||||
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
|
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
|
||||||
|
@ -1029,7 +1029,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
|
||||||
if type_has_metadata(inner_source) {
|
if type_has_metadata(inner_source) {
|
||||||
(inner_source, inner_target)
|
(inner_source, inner_target)
|
||||||
} else {
|
} 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)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -549,7 +549,7 @@ fn fn_abi_sanity_check<'tcx>(
|
||||||
// With metadata. Must be unsized and not on the stack.
|
// With metadata. Must be unsized and not on the stack.
|
||||||
assert!(arg.layout.is_unsized() && !on_stack);
|
assert!(arg.layout.is_unsized() && !on_stack);
|
||||||
// Also, must not be `extern` type.
|
// 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(..)) {
|
if matches!(tail.kind(), ty::Foreign(..)) {
|
||||||
// These types do not have metadata, so having `meta_attrs` is bogus.
|
// These types do not have metadata, so having `meta_attrs` is bogus.
|
||||||
// Conceptually, unsized arguments must be copied around, which requires dynamically
|
// Conceptually, unsized arguments must be copied around, which requires dynamically
|
||||||
|
|
|
@ -244,7 +244,7 @@ fn layout_of_uncached<'tcx>(
|
||||||
|
|
||||||
metadata
|
metadata
|
||||||
} else {
|
} 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() {
|
match unsized_part.kind() {
|
||||||
ty::Foreign(..) => {
|
ty::Foreign(..) => {
|
||||||
|
|
|
@ -142,7 +142,7 @@ fn check_rvalue<'tcx>(
|
||||||
// We cannot allow this for now.
|
// We cannot allow this for now.
|
||||||
return Err((span, "unsizing casts are only allowed for references right now".into()));
|
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() {
|
if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
|
||||||
check_operand(tcx, op, span, body, msrv)?;
|
check_operand(tcx, op, span, body, msrv)?;
|
||||||
// Casting/coercing things to slices is fine.
|
// Casting/coercing things to slices is fine.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0793]: reference to packed field is unaligned
|
error[E0793]: reference to packed field is unaligned
|
||||||
--> $DIR/unaligned_references.rs:28:13
|
--> $DIR/unaligned_references.rs:32:13
|
||||||
|
|
|
|
||||||
LL | &self.x;
|
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)
|
= 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
|
error[E0793]: reference to packed field is unaligned
|
||||||
--> $DIR/unaligned_references.rs:40:24
|
--> $DIR/unaligned_references.rs:44:24
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", &*foo.0);
|
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)
|
= 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
|
error[E0793]: reference to packed field is unaligned
|
||||||
--> $DIR/unaligned_references.rs:42:24
|
--> $DIR/unaligned_references.rs:46:24
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", &*foo.0);
|
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)
|
= 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
|
error[E0793]: reference to packed field is unaligned
|
||||||
--> $DIR/unaligned_references.rs:47:24
|
--> $DIR/unaligned_references.rs:51:24
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", &*foo.0);
|
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)
|
= 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
|
error[E0793]: reference to packed field is unaligned
|
||||||
--> $DIR/unaligned_references.rs:57:17
|
--> $DIR/unaligned_references.rs:81:17
|
||||||
|
|
|
|
||||||
LL | let _ = &good.ptr;
|
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)
|
= 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
|
error[E0793]: reference to packed field is unaligned
|
||||||
--> $DIR/unaligned_references.rs:58:17
|
--> $DIR/unaligned_references.rs:82:17
|
||||||
|
|
|
|
||||||
LL | let _ = &good.data;
|
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)
|
= 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
|
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 _;
|
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)
|
= 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
|
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;
|
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)
|
= 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
|
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();
|
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)
|
= 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
|
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];
|
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)
|
= 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
|
error[E0793]: reference to packed field is unaligned
|
||||||
--> $DIR/unaligned_references.rs:74:17
|
--> $DIR/unaligned_references.rs:98:17
|
||||||
|
|
|
|
||||||
LL | let _ = &packed2.x;
|
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)
|
= 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
|
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;
|
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)
|
= 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
|
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;
|
LL | let _ref = &m2.1.a;
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
133
tests/ui/lint/unaligned_references.next.stderr
Normal file
133
tests/ui/lint/unaligned_references.next.stderr
Normal file
|
@ -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`.
|
|
@ -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::fmt::Debug;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
|
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
pub struct Good {
|
pub struct Good {
|
||||||
|
@ -50,6 +54,26 @@ fn packed_dyn() {
|
||||||
println!("{:?}", &*foo.0); // no error!
|
println!("{:?}", &*foo.0); // no error!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test for #115396
|
||||||
|
fn packed_slice_behind_alias() {
|
||||||
|
trait Mirror {
|
||||||
|
type Assoc: ?Sized;
|
||||||
|
}
|
||||||
|
impl<T: ?Sized> Mirror for T {
|
||||||
|
type Assoc = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct W<T: ?Sized>(<T as Mirror>::Assoc);
|
||||||
|
|
||||||
|
#[repr(packed)]
|
||||||
|
struct Unaligned<T: ?Sized>(ManuallyDrop<W<T>>);
|
||||||
|
|
||||||
|
// 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() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };
|
let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };
|
||||||
|
|
37
tests/ui/offset-of/offset-of-slice-normalized.rs
Normal file
37
tests/ui/offset-of/offset-of-slice-normalized.rs
Normal file
|
@ -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<T: ?Sized> 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);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue