about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-11-17 23:04:23 +0100
committerGitHub <noreply@github.com>2023-11-17 23:04:23 +0100
commit6227455345359fd16e959f45538e652a983da149 (patch)
treeda5412de0353c5716441901b5ce26f5b44749a5e
parentaa2289d3bc4cbf93c517785b3cf1965d271478c4 (diff)
parent92657f163ac3c30af2652c8c7ba5ee7edb14ba01 (diff)
downloadrust-6227455345359fd16e959f45538e652a983da149.tar.gz
rust-6227455345359fd16e959f45538e652a983da149.zip
Rollup merge of #117745 - ouz-a:emit_smir, r=celinval
Emit smir

This adds ability to `-Zunpretty=smir` and get smir output of a Rust file, this is obliviously pretty basic compared to `mir` output but I think we could iteratively improve it, and even at this state this is useful for us.

r? ``@celinval``
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs6
-rw-r--r--compiler/rustc_session/src/config.rs12
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs1
-rw-r--r--compiler/rustc_smir/src/rustc_internal/pretty.rs20
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs7
-rw-r--r--compiler/stable_mir/src/lib.rs14
-rw-r--r--compiler/stable_mir/src/mir.rs1
-rw-r--r--compiler/stable_mir/src/mir/body.rs26
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs258
-rw-r--r--compiler/stable_mir/src/mir/visit.rs2
12 files changed, 340 insertions, 9 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 92bac995bc6..9fe70870140 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3815,6 +3815,7 @@ dependencies = [
  "rustc_query_system",
  "rustc_resolve",
  "rustc_session",
+ "rustc_smir",
  "rustc_span",
  "rustc_symbol_mangling",
  "rustc_target",
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index da7c2440faa..545ff32e598 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -43,6 +43,7 @@ rustc_privacy = { path = "../rustc_privacy" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_resolve = { path = "../rustc_resolve" }
 rustc_session = { path = "../rustc_session" }
+rustc_smir ={ path = "../rustc_smir" }
 rustc_span = { path = "../rustc_span" }
 rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index cc533b9941a..7cd63bc6422 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -9,6 +9,7 @@ use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::config::{OutFileName, PpHirMode, PpMode, PpSourceMode};
 use rustc_session::Session;
+use rustc_smir::rustc_internal::pretty::write_smir_pretty;
 use rustc_span::symbol::Ident;
 use rustc_span::FileName;
 
@@ -325,6 +326,11 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
             write_mir_graphviz(ex.tcx(), None, &mut out).unwrap();
             String::from_utf8(out).unwrap()
         }
+        StableMir => {
+            let mut out = Vec::new();
+            write_smir_pretty(ex.tcx(), &mut out).unwrap();
+            String::from_utf8(out).unwrap()
+        }
         ThirTree => {
             let tcx = ex.tcx();
             let mut out = String::new();
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index add40b83d21..d4f9122e7e3 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2926,12 +2926,13 @@ fn parse_pretty(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) ->
         "thir-tree" => ThirTree,
         "thir-flat" => ThirFlat,
         "mir" => Mir,
+        "stable-mir" => StableMir,
         "mir-cfg" => MirCFG,
         name => handler.early_error(format!(
             "argument to `unpretty` must be one of `normal`, `identified`, \
                             `expanded`, `expanded,identified`, `expanded,hygiene`, \
                             `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
-                            `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir` or \
+                            `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir`, `stable-mir`, or \
                             `mir-cfg`; got {name}"
         )),
     };
@@ -3106,6 +3107,8 @@ pub enum PpMode {
     Mir,
     /// `-Zunpretty=mir-cfg`
     MirCFG,
+    /// `-Zunpretty=stable-mir`
+    StableMir,
 }
 
 impl PpMode {
@@ -3122,7 +3125,8 @@ impl PpMode {
             | ThirTree
             | ThirFlat
             | Mir
-            | MirCFG => true,
+            | MirCFG
+            | StableMir => true,
         }
     }
     pub fn needs_hir(&self) -> bool {
@@ -3130,13 +3134,13 @@ impl PpMode {
         match *self {
             Source(_) | AstTree | AstTreeExpanded => false,
 
-            Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG => true,
+            Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG | StableMir => true,
         }
     }
 
     pub fn needs_analysis(&self) -> bool {
         use PpMode::*;
-        matches!(*self, Hir(PpHirMode::Typed) | Mir | MirCFG | ThirTree | ThirFlat)
+        matches!(*self, Hir(PpHirMode::Typed) | Mir | StableMir | MirCFG | ThirTree | ThirFlat)
     }
 }
 
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index c82f948f195..fa75fd3076c 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -21,6 +21,7 @@ use std::hash::Hash;
 use std::ops::Index;
 
 mod internal;
+pub mod pretty;
 
 pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T {
     with_tables(|tables| item.stable(tables))
diff --git a/compiler/rustc_smir/src/rustc_internal/pretty.rs b/compiler/rustc_smir/src/rustc_internal/pretty.rs
new file mode 100644
index 00000000000..3ef2d28ea47
--- /dev/null
+++ b/compiler/rustc_smir/src/rustc_internal/pretty.rs
@@ -0,0 +1,20 @@
+use std::io;
+
+use super::run;
+use rustc_middle::ty::TyCtxt;
+
+pub fn write_smir_pretty<'tcx, W: io::Write>(tcx: TyCtxt<'tcx>, w: &mut W) -> io::Result<()> {
+    writeln!(
+        w,
+        "// WARNING: This is highly experimental output it's intended for stable-mir developers only."
+    )?;
+    writeln!(
+        w,
+        "// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir."
+    )?;
+    let _ = run(tcx, || {
+        let items = stable_mir::all_local_items();
+        let _ = items.iter().map(|item| -> io::Result<()> { item.dump(w) }).collect::<Vec<_>>();
+    });
+    Ok(())
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 3df09cef1c7..89dbf40c7b4 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -7,7 +7,7 @@
 //!
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
-use crate::rustc_internal::{IndexMap, RustcInternal};
+use crate::rustc_internal::{internal, IndexMap, RustcInternal};
 use crate::rustc_smir::stable_mir::ty::{BoundRegion, Region};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -105,6 +105,10 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         tables.tcx.type_of(item.internal(&mut *tables)).instantiate_identity().stable(&mut *tables)
     }
 
+    fn const_literal(&self, cnst: &stable_mir::ty::Const) -> String {
+        internal(cnst).to_string()
+    }
+
     fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
         let mut tables = self.0.borrow_mut();
         tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
@@ -404,6 +408,7 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
                 .map(|decl| stable_mir::mir::LocalDecl {
                     ty: decl.ty.stable(tables),
                     span: decl.source_info.span.stable(tables),
+                    mutability: decl.mutability.stable(tables),
                 })
                 .collect(),
             self.arg_count,
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index 0262fb536e7..79102dcce35 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -19,9 +19,9 @@
 
 use crate::mir::mono::InstanceDef;
 use crate::mir::Body;
-use std::cell::Cell;
 use std::fmt;
 use std::fmt::Debug;
+use std::{cell::Cell, io};
 
 use self::ty::{
     GenericPredicates, Generics, ImplDef, ImplTrait, IndexedVal, LineInfo, Span, TraitDecl,
@@ -36,10 +36,12 @@ pub mod mir;
 pub mod ty;
 pub mod visitor;
 
+use crate::mir::pretty::function_name;
+use crate::mir::Mutability;
 use crate::ty::{AdtDef, AdtKind, ClosureDef, ClosureKind};
 pub use error::*;
 use mir::mono::Instance;
-use ty::{FnDef, GenericArgs};
+use ty::{Const, FnDef, GenericArgs};
 
 /// Use String for now but we should replace it.
 pub type Symbol = String;
@@ -137,6 +139,11 @@ impl CrateItem {
     pub fn ty(&self) -> Ty {
         with(|cx| cx.def_ty(self.0))
     }
+
+    pub fn dump<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
+        writeln!(w, "{}", function_name(*self))?;
+        self.body().dump(w)
+    }
 }
 
 /// Return the function where execution starts if the current
@@ -223,6 +230,9 @@ pub trait Context {
     /// Returns the type of given crate item.
     fn def_ty(&self, item: DefId) -> Ty;
 
+    /// Returns literal value of a const as a string.
+    fn const_literal(&self, cnst: &Const) -> String;
+
     /// `Span` of an item
     fn span_of_an_item(&self, def_id: DefId) -> Span;
 
diff --git a/compiler/stable_mir/src/mir.rs b/compiler/stable_mir/src/mir.rs
index 2e1714b49c1..2cbe6eb4ad1 100644
--- a/compiler/stable_mir/src/mir.rs
+++ b/compiler/stable_mir/src/mir.rs
@@ -1,5 +1,6 @@
 mod body;
 pub mod mono;
+pub mod pretty;
 pub mod visit;
 
 pub use body::*;
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 351e7bb69c3..fa58a7ffe15 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -1,7 +1,8 @@
+use crate::mir::pretty::{function_body, pretty_statement};
 use crate::ty::{AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, Ty};
 use crate::Opaque;
 use crate::Span;
-
+use std::io;
 /// The SMIR representation of a single function.
 #[derive(Clone, Debug)]
 pub struct Body {
@@ -56,6 +57,28 @@ impl Body {
     pub fn locals(&self) -> &[LocalDecl] {
         &self.locals
     }
+
+    pub fn dump<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
+        writeln!(w, "{}", function_body(self))?;
+        self.blocks
+            .iter()
+            .enumerate()
+            .map(|(index, block)| -> io::Result<()> {
+                writeln!(w, "    bb{}: {{", index)?;
+                let _ = block
+                    .statements
+                    .iter()
+                    .map(|statement| -> io::Result<()> {
+                        writeln!(w, "{}", pretty_statement(&statement.kind))?;
+                        Ok(())
+                    })
+                    .collect::<Vec<_>>();
+                writeln!(w, "    }}").unwrap();
+                Ok(())
+            })
+            .collect::<Result<Vec<_>, _>>()?;
+        Ok(())
+    }
 }
 
 type LocalDecls = Vec<LocalDecl>;
@@ -64,6 +87,7 @@ type LocalDecls = Vec<LocalDecl>;
 pub struct LocalDecl {
     pub ty: Ty,
     pub span: Span,
+    pub mutability: Mutability,
 }
 
 #[derive(Clone, Debug)]
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
new file mode 100644
index 00000000000..e52c3360ce4
--- /dev/null
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -0,0 +1,258 @@
+use crate::mir::{Operand, Rvalue, StatementKind};
+use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy};
+use crate::{with, Body, CrateItem, Mutability};
+
+pub fn function_name(item: CrateItem) -> String {
+    let mut pretty_name = String::new();
+    let body = item.body();
+    pretty_name.push_str("fn ");
+    pretty_name.push_str(item.name().as_str());
+    if body.arg_locals().is_empty() {
+        pretty_name.push_str("()");
+    } else {
+        pretty_name.push_str("(");
+    }
+    body.arg_locals().iter().enumerate().for_each(|(index, local)| {
+        pretty_name.push_str(format!("_{}: ", index).as_str());
+        pretty_name.push_str(&pretty_ty(local.ty.kind()));
+    });
+    if !body.arg_locals().is_empty() {
+        pretty_name.push_str(")");
+    }
+    let return_local = body.ret_local();
+    pretty_name.push_str(" -> ");
+    pretty_name.push_str(&pretty_ty(return_local.ty.kind()));
+    pretty_name.push_str(" {");
+    pretty_name
+}
+
+pub fn function_body(body: &Body) -> String {
+    let mut pretty_body = String::new();
+    body.inner_locals().iter().enumerate().for_each(|(index, local)| {
+        pretty_body.push_str("    ");
+        pretty_body.push_str(format!("let {}", ret_mutability(&local.mutability)).as_str());
+        pretty_body.push_str(format!("_{}: ", index).as_str());
+        pretty_body.push_str(format!("{}", pretty_ty(local.ty.kind())).as_str());
+        pretty_body.push_str(";\n");
+    });
+    pretty_body.push_str("}");
+    pretty_body
+}
+
+pub fn ret_mutability(mutability: &Mutability) -> String {
+    match mutability {
+        Mutability::Not => "".to_string(),
+        Mutability::Mut => "mut ".to_string(),
+    }
+}
+
+pub fn pretty_statement(statement: &StatementKind) -> String {
+    let mut pretty = String::new();
+    match statement {
+        StatementKind::Assign(place, rval) => {
+            pretty.push_str(format!("        _{} = ", place.local).as_str());
+            pretty.push_str(format!("{}", &pretty_rvalue(rval)).as_str());
+        }
+        StatementKind::FakeRead(_, _) => todo!(),
+        StatementKind::SetDiscriminant { .. } => todo!(),
+        StatementKind::Deinit(_) => todo!(),
+        StatementKind::StorageLive(_) => todo!(),
+        StatementKind::StorageDead(_) => todo!(),
+        StatementKind::Retag(_, _) => todo!(),
+        StatementKind::PlaceMention(_) => todo!(),
+        StatementKind::AscribeUserType { .. } => todo!(),
+        StatementKind::Coverage(_) => todo!(),
+        StatementKind::Intrinsic(_) => todo!(),
+        StatementKind::ConstEvalCounter => (),
+        StatementKind::Nop => (),
+    }
+    pretty
+}
+
+pub fn pretty_operand(operand: &Operand) -> String {
+    let mut pretty = String::new();
+    match operand {
+        Operand::Copy(copy) => {
+            pretty.push_str("");
+            pretty.push_str(format!("{}", copy.local).as_str());
+        }
+        Operand::Move(mv) => {
+            pretty.push_str("move ");
+            pretty.push_str(format!("_{}", mv.local).as_str());
+        }
+        Operand::Constant(cnst) => {
+            pretty.push_str("const ");
+            pretty.push_str(with(|cx| cx.const_literal(&cnst.literal)).as_str());
+        }
+    }
+    pretty
+}
+
+pub fn pretty_rvalue(rval: &Rvalue) -> String {
+    let mut pretty = String::new();
+    match rval {
+        Rvalue::AddressOf(muta, addr) => {
+            pretty.push_str("&raw ");
+            pretty.push_str(&ret_mutability(&muta));
+            pretty.push_str(format!("(*_{})", addr.local).as_str());
+        }
+        Rvalue::Aggregate(aggregatekind, operands) => {
+            pretty.push_str(format!("{:#?}", aggregatekind).as_str());
+            pretty.push_str("(");
+            operands.iter().enumerate().for_each(|(i, op)| {
+                pretty.push_str(&pretty_operand(op));
+                if i != operands.len() - 1 {
+                    pretty.push_str(", ");
+                }
+            });
+            pretty.push_str(")");
+        }
+        Rvalue::BinaryOp(bin, op, op2) => {
+            pretty.push_str(&pretty_operand(op));
+            pretty.push_str(" ");
+            pretty.push_str(format!("{:#?}", bin).as_str());
+            pretty.push_str(" ");
+            pretty.push_str(&pretty_operand(op2));
+        }
+        Rvalue::Cast(_, op, ty) => {
+            pretty.push_str(&pretty_operand(op));
+            pretty.push_str(" as ");
+            pretty.push_str(&pretty_ty(ty.kind()));
+        }
+        Rvalue::CheckedBinaryOp(bin, op1, op2) => {
+            pretty.push_str(&pretty_operand(op1));
+            pretty.push_str(" ");
+            pretty.push_str(format!("{:#?}", bin).as_str());
+            pretty.push_str(" ");
+            pretty.push_str(&pretty_operand(op2));
+        }
+        Rvalue::CopyForDeref(deref) => {
+            pretty.push_str("CopyForDeref");
+            pretty.push_str(format!("{}", deref.local).as_str());
+        }
+        Rvalue::Discriminant(place) => {
+            pretty.push_str("discriminant");
+            pretty.push_str(format!("{}", place.local).as_str());
+        }
+        Rvalue::Len(len) => {
+            pretty.push_str("len");
+            pretty.push_str(format!("{}", len.local).as_str());
+        }
+        Rvalue::Ref(_, borrowkind, place) => {
+            pretty.push_str("ref");
+            pretty.push_str(format!("{:#?}", borrowkind).as_str());
+            pretty.push_str(format!("{}", place.local).as_str());
+        }
+        Rvalue::Repeat(op, cnst) => {
+            pretty.push_str(&pretty_operand(op));
+            pretty.push_str(" ");
+            pretty.push_str(&pretty_ty(cnst.ty().kind()));
+        }
+        Rvalue::ShallowInitBox(_, _) => todo!(),
+        Rvalue::ThreadLocalRef(item) => {
+            pretty.push_str("thread_local_ref");
+            pretty.push_str(format!("{:#?}", item).as_str());
+        }
+        Rvalue::NullaryOp(nul, ty) => {
+            pretty.push_str(format!("{:#?}", nul).as_str());
+            pretty.push_str(&&pretty_ty(ty.kind()));
+            pretty.push_str(" ");
+        }
+        Rvalue::UnaryOp(un, op) => {
+            pretty.push_str(&pretty_operand(op));
+            pretty.push_str(" ");
+            pretty.push_str(format!("{:#?}", un).as_str());
+        }
+        Rvalue::Use(op) => pretty.push_str(&pretty_operand(op)),
+    }
+    pretty
+}
+
+pub fn pretty_ty(ty: TyKind) -> String {
+    let mut pretty = String::new();
+    pretty.push_str("");
+    match ty {
+        TyKind::RigidTy(rigid_ty) => match rigid_ty {
+            RigidTy::Bool => "bool".to_string(),
+            RigidTy::Char => "char".to_string(),
+            RigidTy::Int(i) => match i {
+                IntTy::Isize => "isize".to_string(),
+                IntTy::I8 => "i8".to_string(),
+                IntTy::I16 => "i16".to_string(),
+                IntTy::I32 => "i32".to_string(),
+                IntTy::I64 => "i64".to_string(),
+                IntTy::I128 => "i128".to_string(),
+            },
+            RigidTy::Uint(u) => match u {
+                UintTy::Usize => "usize".to_string(),
+                UintTy::U8 => "u8".to_string(),
+                UintTy::U16 => "u16".to_string(),
+                UintTy::U32 => "u32".to_string(),
+                UintTy::U64 => "u64".to_string(),
+                UintTy::U128 => "u128".to_string(),
+            },
+            RigidTy::Float(f) => match f {
+                FloatTy::F32 => "f32".to_string(),
+                FloatTy::F64 => "f64".to_string(),
+            },
+            RigidTy::Adt(def, _) => {
+                format!("{:#?}", with(|cx| cx.def_ty(def.0)))
+            }
+            RigidTy::Str => "str".to_string(),
+            RigidTy::Array(ty, len) => {
+                format!("[{}; {}]", pretty_ty(ty.kind()), with(|cx| cx.const_literal(&len)))
+            }
+            RigidTy::Slice(ty) => {
+                format!("[{}]", pretty_ty(ty.kind()))
+            }
+            RigidTy::RawPtr(ty, mutability) => {
+                pretty.push_str("*");
+                match mutability {
+                    Mutability::Not => pretty.push_str("const "),
+                    Mutability::Mut => pretty.push_str("mut "),
+                }
+                pretty.push_str(&pretty_ty(ty.kind()));
+                pretty
+            }
+            RigidTy::Ref(_, ty, _) => pretty_ty(ty.kind()),
+            RigidTy::FnDef(_, _) => format!("{:#?}", rigid_ty),
+            RigidTy::FnPtr(_) => format!("{:#?}", rigid_ty),
+            RigidTy::Closure(_, _) => format!("{:#?}", rigid_ty),
+            RigidTy::Coroutine(_, _, _) => format!("{:#?}", rigid_ty),
+            RigidTy::Dynamic(data, region, repr) => {
+                // FIXME: Fix binder printing, it looks ugly now
+                pretty.push_str("(");
+                match repr {
+                    DynKind::Dyn => pretty.push_str("dyn "),
+                    DynKind::DynStar => pretty.push_str("dyn* "),
+                }
+                pretty.push_str(format!("{:#?}", data).as_str());
+                pretty.push_str(format!(" +  {:#?} )", region).as_str());
+                pretty
+            }
+            RigidTy::Never => "!".to_string(),
+            RigidTy::Tuple(tuple) => {
+                if tuple.is_empty() {
+                    "()".to_string()
+                } else {
+                    let mut tuple_str = String::new();
+                    tuple_str.push_str("(");
+                    tuple.iter().enumerate().for_each(|(i, ty)| {
+                        tuple_str.push_str(&pretty_ty(ty.kind()));
+                        if i != tuple.len() - 1 {
+                            tuple_str.push_str(", ");
+                        }
+                    });
+                    tuple_str.push_str(")");
+                    tuple_str
+                }
+            }
+            _ => format!("{:#?}", rigid_ty),
+        },
+        TyKind::Alias(_, _) => format!("{:#?}", ty),
+        TyKind::Param(param_ty) => {
+            format!("{:#?}", param_ty.name)
+        }
+        TyKind::Bound(_, _) => format!("{:#?}", ty),
+    }
+}
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index d6304d3ea39..40bedd67352 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -157,7 +157,7 @@ pub trait MirVisitor {
 
     fn super_local_decl(&mut self, local: Local, decl: &LocalDecl) {
         let _ = local;
-        let LocalDecl { ty, span } = decl;
+        let LocalDecl { ty, span, .. } = decl;
         self.visit_ty(ty, Location(*span));
     }