From cbabd00c12f83ec5ea963d1686bb99342ba28607 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 20 Jul 2023 22:20:53 -0300 Subject: [PATCH 1/7] Add tables to Stable::stable --- compiler/rustc_smir/src/rustc_smir/mod.rs | 208 ++++++++++++---------- 1 file changed, 111 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index f512a98f41a4d..8999d44133dd9 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -49,8 +49,12 @@ impl<'tcx> Context for Tables<'tcx> { .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(), @@ -110,11 +114,13 @@ impl<'tcx> Tables<'tcx> { } 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())) + TyKind::RigidTy(RigidTy::RawPtr(self.intern_ty(*ty), mutbl.stable(self))) } + ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref( + opaque(region), + self.intern_ty(*ty), + mutbl.stable(self), + )), ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( rustc_internal::fn_def(*def_id), self.generic_args(generic_args), @@ -187,20 +193,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 +224,51 @@ impl<'tcx> Stable for mir::Statement<'tcx> { } } -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 +277,21 @@ impl Stable for mir::Mutability { } } -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 +301,28 @@ impl Stable for mir::MutBorrowKind { } } -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 +335,15 @@ impl Stable for mir::CastKind { } } -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 +354,9 @@ impl Stable for ty::adjustment::PointerCoercion { } } -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 +364,28 @@ impl Stable for rustc_hir::Unsafety { } } -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 +393,9 @@ impl<'tcx> Stable for mir::Place<'tcx> { } } -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 +406,48 @@ impl Stable for mir::UnwindAction { } } -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 +476,9 @@ impl Stable for mir::BinOp { } } -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 +487,9 @@ impl Stable for mir::UnOp { } } -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 +505,16 @@ impl Stable for rustc_hir::GeneratorKind { } } -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 +525,15 @@ impl<'tcx> Stable for mir::InlineAsmOperand<'tcx> { } } -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,34 +548,34 @@ impl<'tcx> Stable for mir::Terminator<'tcx> { 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!(), From 93bcc2ef98264de8acb8e9f623a5efadd6bb09d2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 20 Jul 2023 22:33:37 -0300 Subject: [PATCH 2/7] Implement Stable for ty::GenericArgs --- compiler/rustc_smir/src/rustc_smir/mod.rs | 49 +++++++++++------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 8999d44133dd9..b6ef92575d22b 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -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; @@ -103,7 +101,7 @@ impl<'tcx> Tables<'tcx> { }, ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt( rustc_internal::adt_def(adt_def.did()), - self.generic_args(generic_args), + generic_args.stable(self), )), ty::Foreign(def_id) => { TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id))) @@ -123,17 +121,17 @@ impl<'tcx> Tables<'tcx> { )), ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( rustc_internal::fn_def(*def_id), - self.generic_args(generic_args), + generic_args.stable(self), )), 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), + generic_args.stable(self), )), ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator( rustc_internal::generator_def(*def_id), - self.generic_args(generic_args), + generic_args.stable(self), match movability { hir::Movability::Static => Movability::Static, hir::Movability::Movable => Movability::Movable, @@ -164,24 +162,6 @@ impl<'tcx> Tables<'tcx> { 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(®ion)) - } - 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. @@ -582,3 +562,22 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { } } } + +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(®ion)) + } + ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(ty)), + ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)), + }) + .collect(), + ) + } +} From 17b8977f9b3f696c71771224888595367bc96deb Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 20 Jul 2023 23:16:55 -0300 Subject: [PATCH 3/7] Add FnPtr ty to SMIR --- compiler/rustc_smir/src/rustc_internal/mod.rs | 16 +++ compiler/rustc_smir/src/rustc_smir/mod.rs | 97 ++++++++++++++++++- compiler/rustc_smir/src/stable_mir/ty.rs | 79 +++++++++++++++ 3 files changed, 191 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index ccb12c27107e4..a918bc981c03c 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -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 @@ impl<'tcx> Tables<'tcx> { 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() { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index b6ef92575d22b..ced9a102c9a80 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -123,7 +123,7 @@ impl<'tcx> Tables<'tcx> { rustc_internal::fn_def(*def_id), generic_args.stable(self), )), - ty::FnPtr(_) => todo!(), + ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(self))), ty::Dynamic(_, _, _) => todo!(), ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( rustc_internal::closure_def(*def_id), @@ -581,3 +581,98 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> { ) } } + +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, + } + } +} diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index ba120be04b2f5..2b762eab5ef20 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -12,6 +12,7 @@ impl Ty { 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 struct ClosureDef(pub(crate) DefId); #[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; + +#[derive(Clone, Debug)] +pub struct FnSig { + pub inputs_and_output: Vec, + 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 { + pub value: T, + pub bound_vars: Vec, +} + +#[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), + BrNamed(BrNamedDef, String), + BrEnv, +} From 303af36be7c1c9306ea00db7c53308ebfb04d4e4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Jul 2023 13:21:04 +0200 Subject: [PATCH 4/7] new solver: add a separate cache for coherence --- compiler/rustc_middle/src/ty/context.rs | 12 ++++++--- .../src/solve/search_graph/mod.rs | 25 +++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1a23fa802100c..aa1f8e48b1b79 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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 @@ impl<'tcx> TyCtxt<'tcx> { 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, @@ -721,6 +724,7 @@ impl<'tcx> TyCtxt<'tcx> { 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()), } diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index f00456e26df52..98c8a74752c00 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -9,7 +9,9 @@ use cache::ProvisionalCache; 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 @@ impl<'tcx> SearchGraph<'tcx> { /// /// 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 @@ impl<'tcx> SearchGraph<'tcx> { 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 @@ impl<'tcx> SearchGraph<'tcx> { // 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) } } From 3e0389561b8e6145d42c9043e94ae61bc960fa2e Mon Sep 17 00:00:00 2001 From: David Rheinsberg Date: Fri, 21 Jul 2023 10:31:01 +0200 Subject: [PATCH 5/7] rustc_target: drop duplicate code Drop duplicate helper methods on `Layout`, which are already implemented on `LayoutS`. Note that `Layout` has a `Deref` implementation to `LayoutS`, so all accessors are automatically redirected. The methods are identical and have been copied to `rustc_abi` in: commit 390a637e296ccfaac4c6abd1291b0523e8a8e00b Author: hamidreza kalbasi Date: Mon Nov 7 00:36:11 2022 +0330 move things from rustc_target::abi to rustc_abi This commit left behind the original implementation. Drop it now. Signed-off-by: David Rheinsberg --- compiler/rustc_target/src/abi/mod.rs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 589cd3cf96b3e..084c917cc317d 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -140,24 +140,3 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { 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, - } - } -} From b0dadff6de0a0d17b38ebfcae333cc88a8b6e47e Mon Sep 17 00:00:00 2001 From: David Rheinsberg Date: Fri, 21 Jul 2023 09:32:28 +0200 Subject: [PATCH 6/7] error/E0691: include alignment in error message Include the computed alignment of the violating field when rejecting transparent types with non-trivially aligned ZSTs. ZST member fields in transparent types must have an alignment of 1 (to ensure it does not raise the layout requirements of the transparent field). The current error message looks like this: LL | struct Foobar(u32, [u32; 0]); | ^^^^^^^^ has alignment larger than 1 This patch changes the report to include the alignment of the violating field: LL | struct Foobar(u32, [u32; 0]); | ^^^^^^^^ has alignment of 4, which is larger than 1 In case of unknown alignments, it will yield: LL | struct Foobar(u32, [T; 0]); | ^^^^^^ may have alignment larger than 1 This allows developers to get a better grasp why a specific field is rejected. Knowing the alignment of the violating field makes it easier to judge where that alignment-requirement originates, and thus hopefully provide better hints on how to mitigate the problem. This idea was proposed in 2022 in #98071 as part of a bigger change. This commit simply extracts this error-message change, to decouple it from the other diagnostic improvements. --- .../src/error_codes/E0691.md | 3 +- .../rustc_hir_analysis/src/check/check.rs | 29 ++++++++++++------- tests/ui/repr/repr-transparent.stderr | 8 ++--- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0691.md b/compiler/rustc_error_codes/src/error_codes/E0691.md index 60060cacbd60b..483c74c0ff56c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0691.md +++ b/compiler/rustc_error_codes/src/error_codes/E0691.md @@ -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 diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d9e14096954b0..e0698a72335f3 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'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 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'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( diff --git a/tests/ui/repr/repr-transparent.stderr b/tests/ui/repr/repr-transparent.stderr index cb1e233777656..028fc25db46cc 100644 --- a/tests/ui/repr/repr-transparent.stderr +++ b/tests/ui/repr/repr-transparent.stderr @@ -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(ZstAlign32, 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, 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 From 634db101eccf03e4b66d10a39a1fdec0bb0f7bbd Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 21 Jul 2023 11:56:49 -0300 Subject: [PATCH 7/7] Implement Stable for ty::Ty --- compiler/rustc_smir/src/rustc_smir/mod.rs | 164 +++++++++++----------- 1 file changed, 84 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index ced9a102c9a80..c9da752ab773f 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -64,7 +64,8 @@ impl<'tcx> Context for Tables<'tcx> { } 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) } } @@ -75,85 +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()), - generic_args.stable(self), - )), - 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(self))) - } - ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref( - opaque(region), - self.intern_ty(*ty), - mutbl.stable(self), - )), - ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( - rustc_internal::fn_def(*def_id), - generic_args.stable(self), - )), - ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(self))), - ty::Dynamic(_, _, _) => todo!(), - ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( - rustc_internal::closure_def(*def_id), - generic_args.stable(self), - )), - ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator( - rustc_internal::generator_def(*def_id), - generic_args.stable(self), - 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); @@ -676,3 +598,85 @@ impl<'tcx> Stable<'tcx> for ty::BoundVariableKind { } } } + +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!(); + } + } + } +}