Auto merge of #113922 - matthiaskrgr:rollup-90cj2vv, r=matthiaskrgr

Rollup of 4 pull requests

Successful merges:

 - #113887 (new solver: add a separate cache for coherence)
 - #113910 (Add FnPtr ty to SMIR)
 - #113913 (error/E0691: include alignment in error message)
 - #113914 (rustc_target: drop duplicate code)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-07-21 16:52:21 +00:00
commit c3c5a5c5f7
9 changed files with 444 additions and 245 deletions

View file

@ -11,7 +11,8 @@ struct ForceAlign32;
#[repr(transparent)]
struct Wrapper(f32, ForceAlign32); // error: zero-sized field in transparent
// struct has alignment larger than 1
// struct has alignment of 32, which
// is larger than 1
```
A transparent struct, enum, or union is supposed to be represented exactly like

View file

@ -1078,9 +1078,9 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
// We are currently checking the type this field came from, so it must be local
let span = tcx.hir().span_if_local(field.did).unwrap();
let zst = layout.is_ok_and(|layout| layout.is_zst());
let align1 = layout.is_ok_and(|layout| layout.align.abi.bytes() == 1);
let align = layout.ok().map(|layout| layout.align.abi.bytes());
if !zst {
return (span, zst, align1, None);
return (span, zst, align, None);
}
fn check_non_exhaustive<'tcx>(
@ -1115,12 +1115,12 @@ fn check_non_exhaustive<'tcx>(
}
}
(span, zst, align1, check_non_exhaustive(tcx, ty).break_value())
(span, zst, align, check_non_exhaustive(tcx, ty).break_value())
});
let non_zst_fields = field_infos
.clone()
.filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None });
.filter_map(|(span, zst, _align, _non_exhaustive)| if !zst { Some(span) } else { None });
let non_zst_count = non_zst_fields.clone().count();
if non_zst_count >= 2 {
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, tcx.def_span(adt.did()));
@ -1128,17 +1128,26 @@ fn check_non_exhaustive<'tcx>(
let incompatible_zst_fields =
field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count();
let incompat = incompatible_zst_fields + non_zst_count >= 2 && non_zst_count < 2;
for (span, zst, align1, non_exhaustive) in field_infos {
if zst && !align1 {
struct_span_err!(
for (span, zst, align, non_exhaustive) in field_infos {
if zst && align != Some(1) {
let mut err = struct_span_err!(
tcx.sess,
span,
E0691,
"zero-sized field in transparent {} has alignment larger than 1",
adt.descr(),
)
.span_label(span, "has alignment larger than 1")
.emit();
);
if let Some(align_bytes) = align {
err.span_label(
span,
format!("has alignment of {align_bytes}, which is larger than 1"),
);
} else {
err.span_label(span, "may have alignment larger than 1");
}
err.emit();
}
if incompat && let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive {
tcx.struct_span_lint_hir(

View file

@ -569,6 +569,7 @@ pub struct GlobalCtxt<'tcx> {
/// Caches the results of goal evaluation in the new solver.
pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>,
pub new_solver_coherence_evaluation_cache: solve::EvaluationCache<'tcx>,
/// Data layout specification for the current target.
pub data_layout: TargetDataLayout,
@ -680,10 +681,12 @@ pub fn lift<T: Lift<'tcx>>(self, value: T) -> Option<T::Lifted> {
value.lift_to_tcx(self)
}
/// Creates a type context and call the closure with a `TyCtxt` reference
/// to the context. The closure enforces that the type context and any interned
/// value (types, args, etc.) can only be used while `ty::tls` has a valid
/// reference to the context, to allow formatting values that need it.
/// Creates a type context. To use the context call `fn enter` which
/// provides a `TyCtxt`.
///
/// By only providing the `TyCtxt` inside of the closure we enforce that the type
/// context and any interned alue (types, args, etc.) can only be used while `ty::tls`
/// has a valid reference to the context, to allow formatting values that need it.
pub fn create_global_ctxt(
s: &'tcx Session,
lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
@ -721,6 +724,7 @@ pub fn create_global_ctxt(
selection_cache: Default::default(),
evaluation_cache: Default::default(),
new_solver_evaluation_cache: Default::default(),
new_solver_coherence_evaluation_cache: Default::default(),
data_layout,
alloc_map: Lock::new(interpret::AllocMap::new()),
}

View file

@ -47,6 +47,14 @@ pub fn generator_def(did: DefId) -> stable_mir::ty::GeneratorDef {
with_tables(|t| t.generator_def(did))
}
pub fn param_def(did: DefId) -> stable_mir::ty::ParamDef {
with_tables(|t| t.param_def(did))
}
pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef {
with_tables(|t| t.br_named_def(did))
}
impl<'tcx> Tables<'tcx> {
pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
self.def_ids[item.0]
@ -76,6 +84,14 @@ pub fn generator_def(&mut self, did: DefId) -> stable_mir::ty::GeneratorDef {
stable_mir::ty::GeneratorDef(self.create_def_id(did))
}
pub fn param_def(&mut self, did: DefId) -> stable_mir::ty::ParamDef {
stable_mir::ty::ParamDef(self.create_def_id(did))
}
pub fn br_named_def(&mut self, did: DefId) -> stable_mir::ty::BrNamedDef {
stable_mir::ty::BrNamedDef(self.create_def_id(did))
}
fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
// FIXME: this becomes inefficient when we have too many ids
for (i, &d) in self.def_ids.iter().enumerate() {

View file

@ -8,9 +8,7 @@
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
use crate::rustc_internal::{self, opaque};
use crate::stable_mir::ty::{
FloatTy, GenericArgKind, GenericArgs, IntTy, Movability, RigidTy, TyKind, UintTy,
};
use crate::stable_mir::ty::{FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy};
use crate::stable_mir::{self, Context};
use rustc_hir as hir;
use rustc_middle::mir;
@ -49,8 +47,12 @@ fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
.basic_blocks
.iter()
.map(|block| stable_mir::mir::BasicBlock {
terminator: block.terminator().stable(),
statements: block.statements.iter().map(mir::Statement::stable).collect(),
terminator: block.terminator().stable(self),
statements: block
.statements
.iter()
.map(|statement| statement.stable(self))
.collect(),
})
.collect(),
locals: mir.local_decls.iter().map(|decl| self.intern_ty(decl.ty)).collect(),
@ -62,7 +64,8 @@ fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>)) {
}
fn ty_kind(&mut self, ty: crate::stable_mir::ty::Ty) -> TyKind {
self.rustc_ty_to_ty(self.types[ty.0])
let ty = self.types[ty.0];
ty.stable(self)
}
}
@ -73,83 +76,6 @@ pub struct Tables<'tcx> {
}
impl<'tcx> Tables<'tcx> {
fn rustc_ty_to_ty(&mut self, ty: Ty<'tcx>) -> TyKind {
match ty.kind() {
ty::Bool => TyKind::RigidTy(RigidTy::Bool),
ty::Char => TyKind::RigidTy(RigidTy::Char),
ty::Int(int_ty) => match int_ty {
ty::IntTy::Isize => TyKind::RigidTy(RigidTy::Int(IntTy::Isize)),
ty::IntTy::I8 => TyKind::RigidTy(RigidTy::Int(IntTy::I8)),
ty::IntTy::I16 => TyKind::RigidTy(RigidTy::Int(IntTy::I16)),
ty::IntTy::I32 => TyKind::RigidTy(RigidTy::Int(IntTy::I32)),
ty::IntTy::I64 => TyKind::RigidTy(RigidTy::Int(IntTy::I64)),
ty::IntTy::I128 => TyKind::RigidTy(RigidTy::Int(IntTy::I128)),
},
ty::Uint(uint_ty) => match uint_ty {
ty::UintTy::Usize => TyKind::RigidTy(RigidTy::Uint(UintTy::Usize)),
ty::UintTy::U8 => TyKind::RigidTy(RigidTy::Uint(UintTy::U8)),
ty::UintTy::U16 => TyKind::RigidTy(RigidTy::Uint(UintTy::U16)),
ty::UintTy::U32 => TyKind::RigidTy(RigidTy::Uint(UintTy::U32)),
ty::UintTy::U64 => TyKind::RigidTy(RigidTy::Uint(UintTy::U64)),
ty::UintTy::U128 => TyKind::RigidTy(RigidTy::Uint(UintTy::U128)),
},
ty::Float(float_ty) => match float_ty {
ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
},
ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
rustc_internal::adt_def(adt_def.did()),
self.generic_args(generic_args),
)),
ty::Foreign(def_id) => {
TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id)))
}
ty::Str => TyKind::RigidTy(RigidTy::Str),
ty::Array(ty, constant) => {
TyKind::RigidTy(RigidTy::Array(self.intern_ty(*ty), opaque(constant)))
}
ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(self.intern_ty(*ty))),
ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
TyKind::RigidTy(RigidTy::RawPtr(self.intern_ty(*ty), mutbl.stable()))
}
ty::Ref(region, ty, mutbl) => {
TyKind::RigidTy(RigidTy::Ref(opaque(region), self.intern_ty(*ty), mutbl.stable()))
}
ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
rustc_internal::fn_def(*def_id),
self.generic_args(generic_args),
)),
ty::FnPtr(_) => todo!(),
ty::Dynamic(_, _, _) => todo!(),
ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
rustc_internal::closure_def(*def_id),
self.generic_args(generic_args),
)),
ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
rustc_internal::generator_def(*def_id),
self.generic_args(generic_args),
match movability {
hir::Movability::Static => Movability::Static,
hir::Movability::Movable => Movability::Movable,
},
)),
ty::Never => TyKind::RigidTy(RigidTy::Never),
ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
fields.iter().map(|ty| self.intern_ty(ty)).collect(),
)),
ty::Alias(_, _) => todo!(),
ty::Param(_) => todo!(),
ty::Bound(_, _) => todo!(),
ty::Placeholder(..)
| ty::GeneratorWitness(_)
| ty::GeneratorWitnessMIR(_, _)
| ty::Infer(_)
| ty::Error(_) => {
unreachable!();
}
}
}
fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
if let Some(id) = self.types.iter().position(|&t| t == ty) {
return stable_mir::ty::Ty(id);
@ -158,24 +84,6 @@ fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
self.types.push(ty);
stable_mir::ty::Ty(id)
}
fn generic_args(
&mut self,
generic_args: &ty::GenericArgs<'tcx>,
) -> stable_mir::ty::GenericArgs {
GenericArgs(
generic_args
.iter()
.map(|arg| match arg.unpack() {
ty::GenericArgKind::Lifetime(region) => {
GenericArgKind::Lifetime(opaque(&region))
}
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(self.intern_ty(ty)),
ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)),
})
.collect(),
)
}
}
/// Build a stable mir crate from a given crate number.
@ -187,20 +95,20 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
}
/// Trait used to convert between an internal MIR type to a Stable MIR type.
pub(crate) trait Stable {
pub(crate) trait Stable<'tcx> {
/// The stable representation of the type implementing Stable.
type T;
/// Converts an object to the equivalent Stable MIR representation.
fn stable(&self) -> Self::T;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T;
}
impl<'tcx> Stable for mir::Statement<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
type T = stable_mir::mir::Statement;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::StatementKind::*;
match &self.kind {
Assign(assign) => {
stable_mir::mir::Statement::Assign(assign.0.stable(), assign.1.stable())
stable_mir::mir::Statement::Assign(assign.0.stable(tables), assign.1.stable(tables))
}
FakeRead(_) => todo!(),
SetDiscriminant { .. } => todo!(),
@ -218,45 +126,51 @@ fn stable(&self) -> Self::T {
}
}
impl<'tcx> Stable for mir::Rvalue<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
type T = stable_mir::mir::Rvalue;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use mir::Rvalue::*;
match self {
Use(op) => stable_mir::mir::Rvalue::Use(op.stable()),
Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
Repeat(_, _) => todo!(),
Ref(region, kind, place) => {
stable_mir::mir::Rvalue::Ref(opaque(region), kind.stable(), place.stable())
}
Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
opaque(region),
kind.stable(tables),
place.stable(tables),
),
ThreadLocalRef(def_id) => {
stable_mir::mir::Rvalue::ThreadLocalRef(rustc_internal::crate_item(*def_id))
}
AddressOf(mutability, place) => {
stable_mir::mir::Rvalue::AddressOf(mutability.stable(), place.stable())
stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables))
}
Len(place) => stable_mir::mir::Rvalue::Len(place.stable()),
Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)),
Cast(_, _, _) => todo!(),
BinaryOp(bin_op, ops) => {
stable_mir::mir::Rvalue::BinaryOp(bin_op.stable(), ops.0.stable(), ops.1.stable())
}
BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp(
bin_op.stable(tables),
ops.0.stable(tables),
ops.1.stable(tables),
),
CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
bin_op.stable(),
ops.0.stable(),
ops.1.stable(),
bin_op.stable(tables),
ops.0.stable(tables),
ops.1.stable(tables),
),
NullaryOp(_, _) => todo!(),
UnaryOp(un_op, op) => stable_mir::mir::Rvalue::UnaryOp(un_op.stable(), op.stable()),
Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable()),
UnaryOp(un_op, op) => {
stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables))
}
Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables)),
Aggregate(_, _) => todo!(),
ShallowInitBox(_, _) => todo!(),
CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable()),
CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables)),
}
}
}
impl Stable for mir::Mutability {
impl<'tcx> Stable<'tcx> for mir::Mutability {
type T = stable_mir::mir::Mutability;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use mir::Mutability::*;
match *self {
Not => stable_mir::mir::Mutability::Not,
@ -265,21 +179,21 @@ fn stable(&self) -> Self::T {
}
}
impl Stable for mir::BorrowKind {
impl<'tcx> Stable<'tcx> for mir::BorrowKind {
type T = stable_mir::mir::BorrowKind;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use mir::BorrowKind::*;
match *self {
Shared => stable_mir::mir::BorrowKind::Shared,
Shallow => stable_mir::mir::BorrowKind::Shallow,
Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable() },
Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
}
}
}
impl Stable for mir::MutBorrowKind {
impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
type T = stable_mir::mir::MutBorrowKind;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use mir::MutBorrowKind::*;
match *self {
Default => stable_mir::mir::MutBorrowKind::Default,
@ -289,28 +203,28 @@ fn stable(&self) -> Self::T {
}
}
impl<'tcx> Stable for mir::NullOp<'tcx> {
impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
type T = stable_mir::mir::NullOp;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use mir::NullOp::*;
match self {
SizeOf => stable_mir::mir::NullOp::SizeOf,
AlignOf => stable_mir::mir::NullOp::AlignOf,
OffsetOf(indices) => {
stable_mir::mir::NullOp::OffsetOf(indices.iter().map(|idx| idx.stable()).collect())
}
OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf(
indices.iter().map(|idx| idx.stable(tables)).collect(),
),
}
}
}
impl Stable for mir::CastKind {
impl<'tcx> Stable<'tcx> for mir::CastKind {
type T = stable_mir::mir::CastKind;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use mir::CastKind::*;
match self {
PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress,
PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress,
PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable()),
PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
DynStar => stable_mir::mir::CastKind::DynStar,
IntToInt => stable_mir::mir::CastKind::IntToInt,
FloatToInt => stable_mir::mir::CastKind::FloatToInt,
@ -323,15 +237,15 @@ fn stable(&self) -> Self::T {
}
}
impl Stable for ty::adjustment::PointerCoercion {
impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
type T = stable_mir::mir::PointerCoercion;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use ty::adjustment::PointerCoercion;
match self {
PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer,
PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer,
PointerCoercion::ClosureFnPointer(unsafety) => {
stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable())
stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable(tables))
}
PointerCoercion::MutToConstPointer => {
stable_mir::mir::PointerCoercion::MutToConstPointer
@ -342,9 +256,9 @@ fn stable(&self) -> Self::T {
}
}
impl Stable for rustc_hir::Unsafety {
impl<'tcx> Stable<'tcx> for rustc_hir::Unsafety {
type T = stable_mir::mir::Safety;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
match self {
rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe,
rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal,
@ -352,28 +266,28 @@ fn stable(&self) -> Self::T {
}
}
impl Stable for FieldIdx {
impl<'tcx> Stable<'tcx> for FieldIdx {
type T = usize;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
self.as_usize()
}
}
impl<'tcx> Stable for mir::Operand<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
type T = stable_mir::mir::Operand;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use mir::Operand::*;
match self {
Copy(place) => stable_mir::mir::Operand::Copy(place.stable()),
Move(place) => stable_mir::mir::Operand::Move(place.stable()),
Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)),
Move(place) => stable_mir::mir::Operand::Move(place.stable(tables)),
Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()),
}
}
}
impl<'tcx> Stable for mir::Place<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
type T = stable_mir::mir::Place;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
stable_mir::mir::Place {
local: self.local.as_usize(),
projection: format!("{:?}", self.projection),
@ -381,9 +295,9 @@ fn stable(&self) -> Self::T {
}
}
impl Stable for mir::UnwindAction {
impl<'tcx> Stable<'tcx> for mir::UnwindAction {
type T = stable_mir::mir::UnwindAction;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::UnwindAction;
match self {
UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
@ -394,46 +308,48 @@ fn stable(&self) -> Self::T {
}
}
impl<'tcx> Stable for mir::AssertMessage<'tcx> {
impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
type T = stable_mir::mir::AssertMessage;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::AssertKind;
match self {
AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
len: len.stable(),
index: index.stable(),
len: len.stable(tables),
index: index.stable(tables),
},
AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
bin_op.stable(),
op1.stable(),
op2.stable(),
bin_op.stable(tables),
op1.stable(tables),
op2.stable(tables),
),
AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()),
AssertKind::OverflowNeg(op) => {
stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables))
}
AssertKind::DivisionByZero(op) => {
stable_mir::mir::AssertMessage::DivisionByZero(op.stable())
stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables))
}
AssertKind::RemainderByZero(op) => {
stable_mir::mir::AssertMessage::RemainderByZero(op.stable())
stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
}
AssertKind::ResumedAfterReturn(generator) => {
stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable())
stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable(tables))
}
AssertKind::ResumedAfterPanic(generator) => {
stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable())
stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable(tables))
}
AssertKind::MisalignedPointerDereference { required, found } => {
stable_mir::mir::AssertMessage::MisalignedPointerDereference {
required: required.stable(),
found: found.stable(),
required: required.stable(tables),
found: found.stable(tables),
}
}
}
}
}
impl Stable for mir::BinOp {
impl<'tcx> Stable<'tcx> for mir::BinOp {
type T = stable_mir::mir::BinOp;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use mir::BinOp;
match self {
BinOp::Add => stable_mir::mir::BinOp::Add,
@ -462,9 +378,9 @@ fn stable(&self) -> Self::T {
}
}
impl Stable for mir::UnOp {
impl<'tcx> Stable<'tcx> for mir::UnOp {
type T = stable_mir::mir::UnOp;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use mir::UnOp;
match self {
UnOp::Not => stable_mir::mir::UnOp::Not,
@ -473,9 +389,9 @@ fn stable(&self) -> Self::T {
}
}
impl Stable for rustc_hir::GeneratorKind {
impl<'tcx> Stable<'tcx> for rustc_hir::GeneratorKind {
type T = stable_mir::mir::GeneratorKind;
fn stable(&self) -> Self::T {
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
match self {
GeneratorKind::Async(async_gen) => {
@ -491,16 +407,16 @@ fn stable(&self) -> Self::T {
}
}
impl<'tcx> Stable for mir::InlineAsmOperand<'tcx> {
impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
type T = stable_mir::mir::InlineAsmOperand;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::InlineAsmOperand;
let (in_value, out_place) = match self {
InlineAsmOperand::In { value, .. } => (Some(value.stable()), None),
InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable())),
InlineAsmOperand::In { value, .. } => (Some(value.stable(tables)), None),
InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable(tables))),
InlineAsmOperand::InOut { in_value, out_place, .. } => {
(Some(in_value.stable()), out_place.map(|place| place.stable()))
(Some(in_value.stable(tables)), out_place.map(|place| place.stable(tables)))
}
InlineAsmOperand::Const { .. }
| InlineAsmOperand::SymFn { .. }
@ -511,15 +427,15 @@ fn stable(&self) -> Self::T {
}
}
impl<'tcx> Stable for mir::Terminator<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
type T = stable_mir::mir::Terminator;
fn stable(&self) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::TerminatorKind::*;
use stable_mir::mir::Terminator;
match &self.kind {
Goto { target } => Terminator::Goto { target: target.as_usize() },
SwitchInt { discr, targets } => Terminator::SwitchInt {
discr: discr.stable(),
discr: discr.stable(tables),
targets: targets
.iter()
.map(|(value, target)| stable_mir::mir::SwitchTarget {
@ -534,37 +450,233 @@ fn stable(&self) -> Self::T {
Return => Terminator::Return,
Unreachable => Terminator::Unreachable,
Drop { place, target, unwind, replace: _ } => Terminator::Drop {
place: place.stable(),
place: place.stable(tables),
target: target.as_usize(),
unwind: unwind.stable(),
unwind: unwind.stable(tables),
},
Call { func, args, destination, target, unwind, call_source: _, fn_span: _ } => {
Terminator::Call {
func: func.stable(),
args: args.iter().map(|arg| arg.stable()).collect(),
destination: destination.stable(),
func: func.stable(tables),
args: args.iter().map(|arg| arg.stable(tables)).collect(),
destination: destination.stable(tables),
target: target.map(|t| t.as_usize()),
unwind: unwind.stable(),
unwind: unwind.stable(tables),
}
}
Assert { cond, expected, msg, target, unwind } => Terminator::Assert {
cond: cond.stable(),
cond: cond.stable(tables),
expected: *expected,
msg: msg.stable(),
msg: msg.stable(tables),
target: target.as_usize(),
unwind: unwind.stable(),
unwind: unwind.stable(tables),
},
InlineAsm { template, operands, options, line_spans, destination, unwind } => {
Terminator::InlineAsm {
template: format!("{:?}", template),
operands: operands.iter().map(|operand| operand.stable()).collect(),
operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
options: format!("{:?}", options),
line_spans: format!("{:?}", line_spans),
destination: destination.map(|d| d.as_usize()),
unwind: unwind.stable(),
unwind: unwind.stable(tables),
}
}
Yield { .. } | GeneratorDrop | FalseEdge { .. } | FalseUnwind { .. } => unreachable!(),
}
}
}
impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
type T = stable_mir::ty::GenericArgs;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use stable_mir::ty::{GenericArgKind, GenericArgs};
GenericArgs(
self.iter()
.map(|arg| match arg.unpack() {
ty::GenericArgKind::Lifetime(region) => {
GenericArgKind::Lifetime(opaque(&region))
}
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(ty)),
ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)),
})
.collect(),
)
}
}
impl<'tcx> Stable<'tcx> for ty::PolyFnSig<'tcx> {
type T = stable_mir::ty::PolyFnSig;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use stable_mir::ty::Binder;
Binder {
value: self.skip_binder().stable(tables),
bound_vars: self
.bound_vars()
.iter()
.map(|bound_var| bound_var.stable(tables))
.collect(),
}
}
}
impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
type T = stable_mir::ty::FnSig;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_target::spec::abi;
use stable_mir::ty::{Abi, FnSig, Unsafety};
FnSig {
inputs_and_output: self
.inputs_and_output
.iter()
.map(|ty| tables.intern_ty(ty))
.collect(),
c_variadic: self.c_variadic,
unsafety: match self.unsafety {
hir::Unsafety::Normal => Unsafety::Normal,
hir::Unsafety::Unsafe => Unsafety::Unsafe,
},
abi: match self.abi {
abi::Abi::Rust => Abi::Rust,
abi::Abi::C { unwind } => Abi::C { unwind },
abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind },
abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind },
abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind },
abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind },
abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind },
abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind },
abi::Abi::Win64 { unwind } => Abi::Win64 { unwind },
abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind },
abi::Abi::PtxKernel => Abi::PtxKernel,
abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt,
abi::Abi::X86Interrupt => Abi::X86Interrupt,
abi::Abi::AmdGpuKernel => Abi::AmdGpuKernel,
abi::Abi::EfiApi => Abi::EfiApi,
abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
abi::Abi::Wasm => Abi::Wasm,
abi::Abi::System { unwind } => Abi::System { unwind },
abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
abi::Abi::RustCall => Abi::RustCall,
abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
abi::Abi::Unadjusted => Abi::Unadjusted,
abi::Abi::RustCold => Abi::RustCold,
},
}
}
}
impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
type T = stable_mir::ty::BoundVariableKind;
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
use stable_mir::ty::{BoundRegionKind, BoundTyKind, BoundVariableKind};
match self {
ty::BoundVariableKind::Ty(bound_ty_kind) => {
BoundVariableKind::Ty(match bound_ty_kind {
ty::BoundTyKind::Anon => BoundTyKind::Anon,
ty::BoundTyKind::Param(def_id, symbol) => {
BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string())
}
})
}
ty::BoundVariableKind::Region(bound_region_kind) => {
BoundVariableKind::Region(match bound_region_kind {
ty::BoundRegionKind::BrAnon(option_span) => {
BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span)))
}
ty::BoundRegionKind::BrNamed(def_id, symbol) => BoundRegionKind::BrNamed(
rustc_internal::br_named_def(*def_id),
symbol.to_string(),
),
ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv,
})
}
ty::BoundVariableKind::Const => BoundVariableKind::Const,
}
}
}
impl<'tcx> Stable<'tcx> for Ty<'tcx> {
type T = stable_mir::ty::TyKind;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
match self.kind() {
ty::Bool => TyKind::RigidTy(RigidTy::Bool),
ty::Char => TyKind::RigidTy(RigidTy::Char),
ty::Int(int_ty) => match int_ty {
ty::IntTy::Isize => TyKind::RigidTy(RigidTy::Int(IntTy::Isize)),
ty::IntTy::I8 => TyKind::RigidTy(RigidTy::Int(IntTy::I8)),
ty::IntTy::I16 => TyKind::RigidTy(RigidTy::Int(IntTy::I16)),
ty::IntTy::I32 => TyKind::RigidTy(RigidTy::Int(IntTy::I32)),
ty::IntTy::I64 => TyKind::RigidTy(RigidTy::Int(IntTy::I64)),
ty::IntTy::I128 => TyKind::RigidTy(RigidTy::Int(IntTy::I128)),
},
ty::Uint(uint_ty) => match uint_ty {
ty::UintTy::Usize => TyKind::RigidTy(RigidTy::Uint(UintTy::Usize)),
ty::UintTy::U8 => TyKind::RigidTy(RigidTy::Uint(UintTy::U8)),
ty::UintTy::U16 => TyKind::RigidTy(RigidTy::Uint(UintTy::U16)),
ty::UintTy::U32 => TyKind::RigidTy(RigidTy::Uint(UintTy::U32)),
ty::UintTy::U64 => TyKind::RigidTy(RigidTy::Uint(UintTy::U64)),
ty::UintTy::U128 => TyKind::RigidTy(RigidTy::Uint(UintTy::U128)),
},
ty::Float(float_ty) => match float_ty {
ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
},
ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
rustc_internal::adt_def(adt_def.did()),
generic_args.stable(tables),
)),
ty::Foreign(def_id) => {
TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id)))
}
ty::Str => TyKind::RigidTy(RigidTy::Str),
ty::Array(ty, constant) => {
TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), opaque(constant)))
}
ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(tables.intern_ty(*ty))),
ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
TyKind::RigidTy(RigidTy::RawPtr(tables.intern_ty(*ty), mutbl.stable(tables)))
}
ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
opaque(region),
tables.intern_ty(*ty),
mutbl.stable(tables),
)),
ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
rustc_internal::fn_def(*def_id),
generic_args.stable(tables),
)),
ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
ty::Dynamic(_, _, _) => todo!(),
ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
rustc_internal::closure_def(*def_id),
generic_args.stable(tables),
)),
ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
rustc_internal::generator_def(*def_id),
generic_args.stable(tables),
match movability {
hir::Movability::Static => Movability::Static,
hir::Movability::Movable => Movability::Movable,
},
)),
ty::Never => TyKind::RigidTy(RigidTy::Never),
ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
fields.iter().map(|ty| tables.intern_ty(ty)).collect(),
)),
ty::Alias(_, _) => todo!(),
ty::Param(_) => todo!(),
ty::Bound(_, _) => todo!(),
ty::Placeholder(..)
| ty::GeneratorWitness(_)
| ty::GeneratorWitnessMIR(_, _)
| ty::Infer(_)
| ty::Error(_) => {
unreachable!();
}
}
}
}

View file

@ -12,6 +12,7 @@ pub fn kind(&self) -> TyKind {
type Const = Opaque;
pub(crate) type Region = Opaque;
type Span = Opaque;
#[derive(Clone, Debug)]
pub enum TyKind {
@ -33,6 +34,7 @@ pub enum RigidTy {
RawPtr(Ty, Mutability),
Ref(Region, Ty, Mutability),
FnDef(FnDef, GenericArgs),
FnPtr(PolyFnSig),
Closure(ClosureDef, GenericArgs),
Generator(GeneratorDef, GenericArgs, Movability),
Never,
@ -83,6 +85,12 @@ pub enum Movability {
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct GeneratorDef(pub(crate) DefId);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct ParamDef(pub(crate) DefId);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct BrNamedDef(pub(crate) DefId);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct AdtDef(pub(crate) DefId);
@ -95,3 +103,74 @@ pub enum GenericArgKind {
Type(Ty),
Const(Const),
}
pub type PolyFnSig = Binder<FnSig>;
#[derive(Clone, Debug)]
pub struct FnSig {
pub inputs_and_output: Vec<Ty>,
pub c_variadic: bool,
pub unsafety: Unsafety,
pub abi: Abi,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Unsafety {
Unsafe,
Normal,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Abi {
Rust,
C { unwind: bool },
Cdecl { unwind: bool },
Stdcall { unwind: bool },
Fastcall { unwind: bool },
Vectorcall { unwind: bool },
Thiscall { unwind: bool },
Aapcs { unwind: bool },
Win64 { unwind: bool },
SysV64 { unwind: bool },
PtxKernel,
Msp430Interrupt,
X86Interrupt,
AmdGpuKernel,
EfiApi,
AvrInterrupt,
AvrNonBlockingInterrupt,
CCmseNonSecureCall,
Wasm,
System { unwind: bool },
RustIntrinsic,
RustCall,
PlatformIntrinsic,
Unadjusted,
RustCold,
}
#[derive(Clone, Debug)]
pub struct Binder<T> {
pub value: T,
pub bound_vars: Vec<BoundVariableKind>,
}
#[derive(Clone, Debug)]
pub enum BoundVariableKind {
Ty(BoundTyKind),
Region(BoundRegionKind),
Const,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum BoundTyKind {
Anon,
Param(ParamDef, String),
}
#[derive(Clone, Debug)]
pub enum BoundRegionKind {
BrAnon(Option<Span>),
BrNamed(BrNamedDef, String),
BrEnv,
}

View file

@ -144,24 +144,3 @@ pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>)
offset
}
}
impl<'a, Ty> TyAndLayout<'a, Ty> {
/// Returns `true` if the layout corresponds to an unsized type.
pub fn is_unsized(&self) -> bool {
self.abi.is_unsized()
}
#[inline]
pub fn is_sized(&self) -> bool {
self.abi.is_sized()
}
/// Returns `true` if the type is a ZST and not unsized.
pub fn is_zst(&self) -> bool {
match self.abi {
Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
Abi::Uninhabited => self.size.bytes() == 0,
Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
}
}
}

View file

@ -9,7 +9,9 @@
use overflow::OverflowData;
use rustc_index::IndexVec;
use rustc_middle::dep_graph::DepKind;
use rustc_middle::traits::solve::{CanonicalInput, Certainty, MaybeCause, QueryResult};
use rustc_middle::traits::solve::{
CanonicalInput, Certainty, EvaluationCache, MaybeCause, QueryResult,
};
use rustc_middle::ty::TyCtxt;
use std::{collections::hash_map::Entry, mem};
@ -58,10 +60,10 @@ pub(super) fn solver_mode(&self) -> SolverMode {
///
/// We could add another global cache for coherence instead,
/// but that's effort so let's only do it if necessary.
pub(super) fn should_use_global_cache(&self) -> bool {
pub(super) fn global_cache(&self, tcx: TyCtxt<'tcx>) -> &'tcx EvaluationCache<'tcx> {
match self.mode {
SolverMode::Normal => true,
SolverMode::Coherence => false,
SolverMode::Normal => &tcx.new_solver_evaluation_cache,
SolverMode::Coherence => &tcx.new_solver_coherence_evaluation_cache,
}
}
@ -213,8 +215,8 @@ pub(super) fn with_new_goal(
inspect: &mut ProofTreeBuilder<'tcx>,
mut loop_body: impl FnMut(&mut Self, &mut ProofTreeBuilder<'tcx>) -> QueryResult<'tcx>,
) -> QueryResult<'tcx> {
if self.should_use_global_cache() && inspect.use_global_cache() {
if let Some(result) = tcx.new_solver_evaluation_cache.get(&canonical_input, tcx) {
if inspect.use_global_cache() {
if let Some(result) = self.global_cache(tcx).get(&canonical_input, tcx) {
debug!(?canonical_input, ?result, "cache hit");
inspect.cache_hit(CacheHit::Global);
return result;
@ -278,13 +280,10 @@ pub(super) fn with_new_goal(
// dependencies, our non-root goal may no longer appear as child of the root goal.
//
// See https://github.com/rust-lang/rust/pull/108071 for some additional context.
let can_cache = !self.overflow_data.did_overflow() || self.stack.is_empty();
if self.should_use_global_cache() && can_cache {
tcx.new_solver_evaluation_cache.insert(
current_goal.input,
dep_node,
current_goal.response,
);
let can_cache = inspect.use_global_cache()
&& (!self.overflow_data.did_overflow() || self.stack.is_empty());
if can_cache {
self.global_cache(tcx).insert(current_goal.input, dep_node, current_goal.response)
}
}

View file

@ -20,13 +20,13 @@ error[E0691]: zero-sized field in transparent struct has alignment larger than 1
--> $DIR/repr-transparent.rs:36:32
|
LL | struct NontrivialAlignZst(u32, [u16; 0]);
| ^^^^^^^^ has alignment larger than 1
| ^^^^^^^^ has alignment of 2, which is larger than 1
error[E0691]: zero-sized field in transparent struct has alignment larger than 1
--> $DIR/repr-transparent.rs:42:24
|
LL | struct GenericAlign<T>(ZstAlign32<T>, u32);
| ^^^^^^^^^^^^^ has alignment larger than 1
| ^^^^^^^^^^^^^ has alignment of 32, which is larger than 1
error[E0084]: unsupported representation for zero-variant enum
--> $DIR/repr-transparent.rs:44:1
@ -66,13 +66,13 @@ error[E0691]: zero-sized field in transparent enum has alignment larger than 1
--> $DIR/repr-transparent.rs:71:14
|
LL | Foo(u32, [u16; 0]),
| ^^^^^^^^ has alignment larger than 1
| ^^^^^^^^ has alignment of 2, which is larger than 1
error[E0691]: zero-sized field in transparent enum has alignment larger than 1
--> $DIR/repr-transparent.rs:76:11
|
LL | Foo { bar: ZstAlign32<T>, baz: u32 }
| ^^^^^^^^^^^^^^^^^^ has alignment larger than 1
| ^^^^^^^^^^^^^^^^^^ has alignment of 32, which is larger than 1
error[E0690]: transparent union needs at most one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:85:1