File: check_normalization.rs

package info (click to toggle)
rustc 1.85.0%2Bdfsg3-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 893,396 kB
  • sloc: xml: 158,127; python: 35,830; javascript: 19,497; cpp: 19,002; sh: 17,245; ansic: 13,127; asm: 4,376; makefile: 1,051; perl: 29; lisp: 29; ruby: 19; sql: 11
file content (96 lines) | stat: -rw-r--r-- 2,733 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//@ run-pass
//! Test that types are normalized in an instance body.

//@ ignore-stage1
//@ ignore-cross-compile
//@ ignore-remote
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
//@ edition: 2021

#![feature(rustc_private)]

extern crate rustc_middle;
#[macro_use]
extern crate rustc_smir;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate stable_mir;

use mir::mono::Instance;
use ty::{Ty, TyKind, RigidTy};
use rustc_smir::rustc_internal;
use stable_mir::*;
use std::io::Write;
use std::ops::ControlFlow;

const CRATE_NAME: &str = "input";

/// This function uses the Stable MIR APIs to get information about the test crate.
fn test_stable_mir() -> ControlFlow<()> {
    let items = stable_mir::all_local_items();

    // Get all items and split generic vs monomorphic items.
    let instances: Vec<_> =
        items.into_iter().filter_map(|item| (!item.requires_monomorphization()).then(|| {
            Instance::try_from(item).unwrap()
        })).collect();
    assert_eq!(instances.len(), 1, "Expected one constant");

    for instance in instances {
        check_ty(instance.ty());
    }
    ControlFlow::Continue(())
}

fn check_ty(ty: Ty) {
    match ty.kind() {
        TyKind::RigidTy(RigidTy::Adt(def, args)) if def.kind().is_struct() => {
            // Ensure field type is also normalized
            def.variants_iter().next().unwrap().fields().into_iter().for_each(|f| {
                check_ty(f.ty_with_args(&args))
            });
        }
        TyKind::RigidTy(RigidTy::Uint(..)) => {}
        kind => unreachable!("Unexpected kind: {kind:?}")
    }
}


/// This test will generate and analyze a dummy crate using the stable mir.
/// For that, it will first write the dummy crate into a file.
/// Then it will create a `StableMir` using custom arguments and then
/// it will run the compiler.
fn main() {
    let path = "normalization_input.rs";
    generate_input(&path).unwrap();
    let args = vec![
        "rustc".to_string(),
        "-Cpanic=abort".to_string(),
        "--crate-type=lib".to_string(),
        "--crate-name".to_string(),
        CRATE_NAME.to_string(),
        path.to_string(),
    ];
    run!(args, test_stable_mir).unwrap();
}

fn generate_input(path: &str) -> std::io::Result<()> {
    let mut file = std::fs::File::create(path)?;
    write!(
        file,
        r#"
        pub trait Primitive {{
            type Base;
        }}

        impl Primitive for char {{
            type Base = u32;
        }}

        pub struct Wrapper<T: Primitive>(T::Base);
        pub type WrapperChar = Wrapper<char>;
        pub const NULL_CHAR: WrapperChar = Wrapper::<char>(0);
        "#
    )?;
    Ok(())
}