-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Refactor StableMIR #140643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Refactor StableMIR #140643
Conversation
This comment has been minimized.
This comment has been minimized.
- rewrite all `SmirInterface` apis. - add `BridgeTys` to impl those associated types in `Bridge`. - move `**_def()` stuffs living in `impl Tables` from `rustc_internal` to `stable_mir`.
The previous `rustc_smir::alloc` had many direct calls to rustc queries. This commit splits it into two parts: `rustc_smir::alloc` and `stable_mir::alloc`. Following the same pattern as `SmirCtxt` and `SmirInterface`, the `rustc_smir::alloc` handles all direct interactions with rustc queries and performs the actual memory allocations, while the `stable_mir::alloc` is responsible for constructing stable components.
This commit removes the `Tables` field from `SmirCtxt`, since borrows of `tables` should only be managed by `SmirInterface`. This change prevents `SmirCtxt` from holding separate borrows and requires passing `tables` explicitly when needed. We use the `traits.rs` file to define traits that are used for encapsulating the associated functions in the rustc's internals. This is much easier to use and maintain than directly cramming everything into `SmirCtxt`.
note that this commit delete `convert/error.rs`, we would use `SmirError::from_internal` instead. **Unresolved questions:** - There are still a few direct calls to rustc's internals scattered across `impl Stable`s, but most of them appear to be relatively stable, e.g., `mir::interpret::ConstAllocation::inner(self)` and `mir::syntax::SwitchTargets::otherwise(self)`.
28f5ec1
to
a169e52
Compare
/// Trait used to convert between an internal MIR type to a Stable MIR type. | ||
pub trait Stable<'cx> { | ||
/// The stable representation of the type implementing Stable. | ||
type T; | ||
/// Converts an object to the equivalent Stable MIR representation. | ||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T; | ||
} | ||
|
||
impl<'tcx, T> Stable<'tcx> for &T | ||
where | ||
T: Stable<'tcx>, | ||
{ | ||
type T = T::T; | ||
|
||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T { | ||
(*self).stable(tables) | ||
} | ||
} | ||
|
||
impl<'tcx, T> Stable<'tcx> for Option<T> | ||
where | ||
T: Stable<'tcx>, | ||
{ | ||
type T = Option<T::T>; | ||
|
||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T { | ||
self.as_ref().map(|value| value.stable(tables)) | ||
} | ||
} | ||
|
||
impl<'tcx, T, E> Stable<'tcx> for Result<T, E> | ||
where | ||
T: Stable<'tcx>, | ||
E: Stable<'tcx>, | ||
{ | ||
type T = Result<T::T, E::T>; | ||
|
||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T { | ||
match self { | ||
Ok(val) => Ok(val.stable(tables)), | ||
Err(error) => Err(error.stable(tables)), | ||
} | ||
} | ||
} | ||
|
||
impl<'tcx, T> Stable<'tcx> for &[T] | ||
where | ||
T: Stable<'tcx>, | ||
{ | ||
type T = Vec<T::T>; | ||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T { | ||
self.iter().map(|e| e.stable(tables)).collect() | ||
} | ||
} | ||
|
||
impl<'tcx, T, U> Stable<'tcx> for (T, U) | ||
where | ||
T: Stable<'tcx>, | ||
U: Stable<'tcx>, | ||
{ | ||
type T = (T::T, U::T); | ||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T { | ||
(self.0.stable(tables), self.1.stable(tables)) | ||
} | ||
} | ||
|
||
impl<'tcx, T> Stable<'tcx> for RangeInclusive<T> | ||
where | ||
T: Stable<'tcx>, | ||
{ | ||
type T = RangeInclusive<T::T>; | ||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T { | ||
RangeInclusive::new(self.start().stable(tables), self.end().stable(tables)) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! I accidentally included these changes in this commit, they should have been part of the 'move convert
module to stable_mir
' commit instead. Sorry for the confusion🥲
/// Implement error handling for extracting function ABI information. | ||
impl<'tcx, B: Bridge> FnAbiOfHelpers<'tcx> for Tables<'tcx, B> { | ||
type FnAbiOfResult = Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, B::Error>; | ||
|
||
#[inline] | ||
fn handle_fn_abi_err( | ||
&self, | ||
err: ty::layout::FnAbiError<'tcx>, | ||
_span: rustc_span::Span, | ||
fn_abi_request: ty::layout::FnAbiRequest<'tcx>, | ||
) -> B::Error { | ||
B::Error::new(format!("Failed to get ABI for `{fn_abi_request:?}`: {err:?}")) | ||
} | ||
} | ||
|
||
impl<'tcx, B: Bridge> LayoutOfHelpers<'tcx> for Tables<'tcx, B> { | ||
type LayoutOfResult = Result<ty::layout::TyAndLayout<'tcx>, B::Error>; | ||
|
||
#[inline] | ||
fn handle_layout_err( | ||
&self, | ||
err: ty::layout::LayoutError<'tcx>, | ||
_span: rustc_span::Span, | ||
ty: Ty<'tcx>, | ||
) -> B::Error { | ||
B::Error::new(format!("Failed to get layout for `{ty}`: {err}")) | ||
} | ||
} | ||
|
||
impl<'tcx, B: Bridge> HasTypingEnv<'tcx> for Tables<'tcx, B> { | ||
fn typing_env(&self) -> ty::TypingEnv<'tcx> { | ||
ty::TypingEnv::fully_monomorphized() | ||
} | ||
} | ||
|
||
impl<'tcx, B: Bridge> HasTyCtxt<'tcx> for Tables<'tcx, B> { | ||
fn tcx(&self) -> TyCtxt<'tcx> { | ||
self.tcx | ||
} | ||
} | ||
|
||
impl<'tcx, B: Bridge> HasDataLayout for Tables<'tcx, B> { | ||
fn data_layout(&self) -> &rustc_abi::TargetDataLayout { | ||
self.tcx.data_layout() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we should implement these traits for SmirCtxt
instead of Tables
?
impl<'tcx> Tables<'tcx> { | ||
pub(crate) fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty { | ||
pub struct Tables<'tcx, B: Bridge> { | ||
tcx: TyCtxt<'tcx>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I should remove this tcx
.
the only functionality of `Tables` is caching results. this commit moves calls to rustc queries from `Tables` to `SmirCtxt`.
This PR refactors stable-mir according to the guidance in this doc. It reverses the dependency between
rustc_smir
andstable_mir
, makingrustc_smir
completely agnostic ofstable_mir
.Under the new architecture, the
rustc_smir
crate would retain direct access to rustc queries, whilestable_mir
should proxy all such requests throughrustc_smir
instead of accessing rustc's internals directly.stable_mir
would only be responsible for the conversion between internal and stable constructs.This PR mainly introduces these changes:
Since
rustc_smir
needs these stable types somewhere, using associated types is a good approach.This PR moves
Tables
fromSmirCtxt
to a newSmirContainer
struct, since mutable borrows oftables
should only be managed bySmirInterface
. This change preventsSmirCtxt
from holding separate borrows and requires passingtables
explicitly when needed:This PR introduces
SmirContainer
as a separate struct rather than bundling it into aSmirInterface
struct. This separation makes the architecture more modular and easier to reason about.We use this file to define traits that are used for encapsulating the associated functions in the rustc's internals. This is much easier to use and maintain than directly cramming everything into
SmirCtxt
. Here is a real-world use case:rustc_smir::alloc
The previous
rustc_smir::alloc
had many direct calls to rustc queries. This PR splits it into two parts:rustc_smir::alloc
andstable_mir::alloc
. Following the same pattern asSmirCtxt
andSmirInterface
, therustc_smir::alloc
handles all direct interactions with rustc queries and performs the actual memory allocations, while thestable_mir::alloc
is responsible for constructing stable components.convert/error.rs
We use
SmirError::from_internal
instead, since implementingStable
for these internal errors would be redundant—tables
is not actually used. If we later need to add something likeLayoutError
tostable_mir
, we could implement it as follows:Unresolved questions:
impl Stable
s, but most of them appear to be relatively stable, e.g.,mir::interpret::ConstAllocation::inner(self)
andmir::syntax::SwitchTargets::otherwise(self)
.r? @celinval