Skip to main content

ide/
view_mir.rs

1use hir::{DefWithBody, Semantics};
2use ide_db::{FilePosition, RootDatabase};
3use syntax::{AstNode, algo::ancestors_at_offset, ast};
4
5// Feature: View Mir
6//
7// | Editor  | Action Name |
8// |---------|-------------|
9// | VS Code | **rust-analyzer: View Mir**
10pub(crate) fn view_mir(db: &RootDatabase, position: FilePosition) -> String {
11    body_mir(db, position).unwrap_or_else(|| "Not inside a function body".to_owned())
12}
13
14fn body_mir(db: &RootDatabase, position: FilePosition) -> Option<String> {
15    let sema = Semantics::new(db);
16    let source_file = sema.parse_guess_edition(position.file_id);
17
18    let item = ancestors_at_offset(source_file.syntax(), position.offset)
19        .filter(|it| !ast::MacroCall::can_cast(it.kind()))
20        .find_map(ast::Item::cast)?;
21    let def: DefWithBody = match item {
22        ast::Item::Fn(it) => sema.to_def(&it)?.into(),
23        ast::Item::Const(it) => sema.to_def(&it)?.into(),
24        ast::Item::Static(it) => sema.to_def(&it)?.into(),
25        _ => return None,
26    };
27    Some(def.debug_mir(db))
28}
29
30#[cfg(test)]
31mod tests {
32    use crate::fixture;
33
34    fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
35        let (analysis, position) = fixture::position(ra_fixture);
36        let mir = analysis.view_mir(position);
37        assert!(mir.is_ok());
38    }
39
40    #[test]
41    fn tuple_field_projection_uses_base_type() {
42        check(
43            r#"
44//- minicore: sized
45struct Inner { value: u32 }
46fn test$0(value: (u32, Inner)) -> Inner { value.1 }
47"#,
48        );
49    }
50
51    #[test]
52    fn nested_struct_field_projection_uses_base_type() {
53        check(
54            r#"
55//- minicore: sized
56struct Inner { value: u32 }
57struct Outer { first: u32, second: Inner }
58fn test$0(value: Outer) -> u32 { value.second.value }
59"#,
60        );
61    }
62
63    #[test]
64    fn enum_field_projection_uses_base_variant() {
65        check(
66            r#"
67//- minicore: sized
68struct Inner { value: u32 }
69enum Outer { Variant { first: u32, second: Inner } }
70fn test$0(value: Outer) -> Inner {
71    match value { Outer::Variant { second, .. } => second }
72}
73"#,
74        );
75    }
76}