Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2024-11-29"
channel = "nightly-2025-07-05"
components = ["llvm-tools", "rustc-dev", "rust-src", "rust-analyzer"]
216 changes: 216 additions & 0 deletions src/compat/indexed_val.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
//! Compat shim for `IndexedVal::to_index()` and `IndexedVal::to_val()`.
//!
//! In nightlies < 2025-07-05 (commit-date < 2025-07-04), `IndexedVal` is a
//! public trait on `stable_mir::ty` providing `to_index(&self) -> usize` and
//! `to_val(usize) -> Self`. In later nightlies the trait became `pub(crate)`,
//! so external code can no longer call these methods.
//!
//! This module provides free functions `to_index` and `to_val` that work on
//! both sides of the breakpoint:
//!
//! - **Old nightlies**: delegate to the trait methods directly.
//! - **New nightlies**: extract the inner `usize` via a minimal serde
//! `Serializer` (for `to_index`), or construct the newtype via `transmute`
//! with a compile-time size assertion (for `to_val`).
//!
//! All affected types (`Ty`, `Span`, `AllocId`, `VariantIdx`, etc.) are
//! single-field newtypes around `usize` with `#[derive(Serialize)]`.

use super::stable_mir;

// ---- Old nightlies: IndexedVal is public, just delegate ----

#[cfg(not(smir_no_indexed_val))]
pub use stable_mir::ty::IndexedVal;

#[cfg(not(smir_no_indexed_val))]
pub fn to_index<T: IndexedVal>(val: &T) -> usize {
val.to_index()
}

#[cfg(not(smir_no_indexed_val))]
pub fn to_val<T: IndexedVal>(index: usize) -> T {
T::to_val(index)
}

// ---- New nightlies: IndexedVal is pub(crate), use serde/transmute ----

#[cfg(smir_no_indexed_val)]
pub fn to_index<T: super::serde::Serialize>(val: &T) -> usize {
super::serde::Serialize::serialize(val, UsizeExtractor)
.expect("to_index: type did not serialize as a usize newtype")
}

#[cfg(smir_no_indexed_val)]
pub fn to_val<T>(index: usize) -> T {
// These types are #[derive(Serialize, Copy, Clone)] newtypes around usize.
// A single-field struct has the same layout as its field.
assert!(
std::mem::size_of::<T>() == std::mem::size_of::<usize>(),
"to_val: type is not usize-sized"
);
unsafe { std::mem::transmute_copy(&index) }
}

// Minimal Serializer that extracts a usize from a newtype(usize) chain.
#[cfg(smir_no_indexed_val)]
struct UsizeExtractor;

#[cfg(smir_no_indexed_val)]
impl super::serde::Serializer for UsizeExtractor {
type Ok = usize;
type Error = UsizeExtractError;
type SerializeSeq = super::serde::ser::Impossible<usize, Self::Error>;
type SerializeTuple = super::serde::ser::Impossible<usize, Self::Error>;
type SerializeTupleStruct = super::serde::ser::Impossible<usize, Self::Error>;
type SerializeTupleVariant = super::serde::ser::Impossible<usize, Self::Error>;
type SerializeMap = super::serde::ser::Impossible<usize, Self::Error>;
type SerializeStruct = super::serde::ser::Impossible<usize, Self::Error>;
type SerializeStructVariant = super::serde::ser::Impossible<usize, Self::Error>;

fn serialize_newtype_struct<T: ?Sized + super::serde::Serialize>(
self,
_name: &'static str,
value: &T,
) -> Result<usize, Self::Error> {
// Recurse: the inner value should serialize as u64/usize.
value.serialize(UsizeExtractor)
}

fn serialize_u64(self, v: u64) -> Result<usize, Self::Error> {
Ok(v as usize)
}

// All other methods are unsupported; the types we care about only hit
// serialize_newtype_struct -> serialize_u64.
fn serialize_bool(self, _: bool) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_i8(self, _: i8) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_i16(self, _: i16) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_i32(self, _: i32) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_i64(self, _: i64) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_u8(self, _: u8) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_u16(self, _: u16) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_u32(self, _: u32) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_f32(self, _: f32) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_f64(self, _: f64) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_char(self, _: char) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_str(self, _: &str) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_bytes(self, _: &[u8]) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_none(self) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_some<T: ?Sized + super::serde::Serialize>(self, _: &T) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_unit(self) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_unit_struct(self, _: &'static str) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_unit_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_newtype_variant<T: ?Sized + super::serde::Serialize>(
self,
_: &'static str,
_: u32,
_: &'static str,
_: &T,
) -> Result<usize, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_tuple_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Err(UsizeExtractError)
}
fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(UsizeExtractError)
}
}

#[cfg(smir_no_indexed_val)]
#[derive(Debug)]
struct UsizeExtractError;

#[cfg(smir_no_indexed_val)]
impl std::fmt::Display for UsizeExtractError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "type did not serialize as a usize newtype")
}
}

#[cfg(smir_no_indexed_val)]
impl std::error::Error for UsizeExtractError {}

#[cfg(smir_no_indexed_val)]
impl super::serde::ser::Error for UsizeExtractError {
fn custom<T: std::fmt::Display>(_msg: T) -> Self {
UsizeExtractError
}
}
1 change: 1 addition & 0 deletions src/compat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub use rustc_smir::rustc_internal::internal;
pub use rustc_span::def_id::DefId;

pub mod bridge;
pub mod indexed_val;
pub mod mono_collect;
pub mod output;
pub mod spans;
Expand Down
7 changes: 4 additions & 3 deletions src/mk_graph/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use stable_mir::mir::{
BorrowKind, ConstOperand, NonDivergingIntrinsic, Operand, Rvalue, Statement, StatementKind,
Terminator, TerminatorKind,
};
use stable_mir::ty::{ConstantKind, IndexedVal, MirConst, Ty};
use stable_mir::ty::{ConstantKind, MirConst, Ty};
use crate::compat::indexed_val::to_index;

use crate::printer::SmirJson;

Expand Down Expand Up @@ -57,7 +58,7 @@ impl GraphContext {
.provenance
.ptrs
.iter()
.map(|(_offset, prov)| self.allocs.describe(prov.0.to_index() as u64))
.map(|(_offset, prov)| self.allocs.describe(to_index(&prov.0) as u64))
.collect();
format!("const [{}]", alloc_refs.join(", "))
} else {
Expand Down Expand Up @@ -141,7 +142,7 @@ impl GraphContext {
} => format!(
"set discriminant {}({})",
place.label(),
variant_index.to_index()
to_index(variant_index)
),
Deinit(p) => format!("Deinit {}", p.label()),
StorageLive(l) => format!("Storage Live _{}", &l),
Expand Down
13 changes: 7 additions & 6 deletions src/mk_graph/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use std::collections::HashMap;
use crate::compat::stable_mir;
use stable_mir::abi::{FieldsShape, LayoutShape};
use stable_mir::mir::alloc::GlobalAlloc;
use stable_mir::ty::{IndexedVal, Ty};
use stable_mir::ty::Ty;
use crate::compat::indexed_val::to_index;
use stable_mir::CrateDef;

use crate::printer::{AllocInfo, TypeMetadata};
Expand Down Expand Up @@ -151,7 +152,7 @@ impl AllocIndex {

impl AllocEntry {
pub fn from_alloc_info(info: &AllocInfo, type_index: &TypeIndex) -> Self {
let alloc_id = info.alloc_id().to_index() as u64;
let alloc_id = to_index(&info.alloc_id()) as u64;
let ty = info.ty();
let ty_name = type_index.get_name(ty);

Expand Down Expand Up @@ -253,25 +254,25 @@ impl TypeIndex {
let mut index = Self::new();
for (ty, metadata) in types {
let entry = TypeEntry::from_metadata(metadata, *ty);
index.by_id.insert(ty.to_index() as u64, entry);
index.by_id.insert(to_index(ty) as u64, entry);
}
index
}

pub fn get(&self, ty: Ty) -> Option<&TypeEntry> {
self.by_id.get(&(ty.to_index() as u64))
self.by_id.get(&(to_index(&ty) as u64))
}

pub fn get_name(&self, ty: Ty) -> String {
self.by_id
.get(&(ty.to_index() as u64))
.get(&(to_index(&ty) as u64))
.map(|e| e.name.clone())
.unwrap_or_else(|| format!("{}", ty))
}

pub fn get_layout(&self, ty: Ty) -> Option<&LayoutInfo> {
self.by_id
.get(&(ty.to_index() as u64))
.get(&(to_index(&ty) as u64))
.and_then(|e| e.layout.as_ref())
}

Expand Down
7 changes: 4 additions & 3 deletions src/mk_graph/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use stable_mir::mir::{
AggregateKind, BorrowKind, ConstOperand, Mutability, NonDivergingIntrinsic, NullOp, Operand,
Place, ProjectionElem, Rvalue, Terminator, TerminatorKind, UnwindAction,
};
use stable_mir::ty::{IndexedVal, RigidTy};
use stable_mir::ty::RigidTy;
use crate::compat::indexed_val::to_index;

use crate::printer::FnSymType;

Expand Down Expand Up @@ -57,7 +58,7 @@ impl GraphLabelString for AggregateKind {
match &self {
Array(_ty) => "Array".to_string(),
Tuple => "Tuple".to_string(),
Adt(_, idx, _, _, _) => format!("Adt{{{}}}", idx.to_index()),
Adt(_, idx, _, _, _) => format!("Adt{{{}}}", to_index(idx)),
Closure(_, _) => "Closure".to_string(),
Coroutine(_, _, _) => "Coroutine".to_string(),

Expand Down Expand Up @@ -167,7 +168,7 @@ fn decorate(thing: String, p: &ProjectionElem) -> String {
to
)
}
ProjectionElem::Downcast(i) => format!("({thing} as variant {})", i.to_index()),
ProjectionElem::Downcast(i) => format!("({thing} as variant {})", to_index(i)),
ProjectionElem::OpaqueCast(ty) => format!("{thing} as type {ty}"),
ProjectionElem::Subtype(i) => format!("{thing} :> {i}"),
}
Expand Down
6 changes: 3 additions & 3 deletions src/printer/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::collections::{HashMap, HashSet};
use stable_mir::mir::alloc::GlobalAlloc;
use stable_mir::mir::mono::MonoItem;
use stable_mir::mir::visit::MirVisitor;
use stable_mir::ty::IndexedVal;
use crate::compat::indexed_val::to_index;
use stable_mir::CrateDef;

use super::items::{get_foreign_module_details, mk_item};
Expand Down Expand Up @@ -274,13 +274,13 @@ fn assemble_smir(tcx: TyCtxt<'_>, collected: CollectedCrate, derived: DerivedInf
let b_kind = b.0 .1.as_ref().map(|k| format!("{k}"));
a_kind.cmp(&b_kind)
})
.then_with(|| a.0 .0.to_index().cmp(&b.0 .0.to_index()))
.then_with(|| to_index(&a.0 .0).cmp(&to_index(&b.0 .0)))
});
items.sort();
types.sort_by(|a, b| {
format!("{}", a.0)
.cmp(&format!("{}", b.0))
.then_with(|| a.0.to_index().cmp(&b.0.to_index()))
.then_with(|| to_index(&a.0).cmp(&to_index(&b.0)))
});
spans.sort_by(|a, b| a.1.cmp(&b.1));

Expand Down
7 changes: 4 additions & 3 deletions src/printer/mir_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ use stable_mir::mir::alloc::GlobalAlloc;
use stable_mir::mir::mono::Instance;
use stable_mir::mir::visit::MirVisitor;
use stable_mir::mir::{LocalDecl, Rvalue, Terminator, TerminatorKind};
use stable_mir::ty::{ConstDef, IndexedVal};
use stable_mir::ty::ConstDef;
use crate::compat::indexed_val::{to_index, to_val};
use stable_mir::visitor::Visitable;
use stable_mir::CrateDef;

Expand Down Expand Up @@ -115,7 +116,7 @@ fn field_containing_offset(l: &LayoutShape, offset: usize) -> Option<(usize, usi
}

fn opaque_placeholder_ty() -> stable_mir::ty::Ty {
stable_mir::ty::Ty::to_val(0)
to_val::<stable_mir::ty::Ty>(0)
}

fn get_prov_ty(ty: stable_mir::ty::Ty, offset: &usize) -> Option<stable_mir::ty::Ty> {
Expand Down Expand Up @@ -305,7 +306,7 @@ fn collect_alloc(
impl MirVisitor for BodyAnalyzer<'_, '_> {
fn visit_span(&mut self, span: &stable_mir::ty::Span) {
self.spans.insert(
span.to_index(),
to_index(span),
crate::compat::spans::resolve_span(self.tcx, span),
);
}
Expand Down
Loading