| 
 | 1 | +//@ run-pass  | 
 | 2 | +//! Test that types are normalized in an instance body.  | 
 | 3 | +
  | 
 | 4 | +//@ ignore-stage1  | 
 | 5 | +//@ ignore-cross-compile  | 
 | 6 | +//@ ignore-remote  | 
 | 7 | +//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837  | 
 | 8 | +//@ edition: 2021  | 
 | 9 | + | 
 | 10 | +#![feature(rustc_private)]  | 
 | 11 | + | 
 | 12 | +#[macro_use]  | 
 | 13 | +extern crate rustc_smir;  | 
 | 14 | +extern crate rustc_driver;  | 
 | 15 | +extern crate rustc_interface;  | 
 | 16 | +extern crate stable_mir;  | 
 | 17 | + | 
 | 18 | +use mir::mono::Instance;  | 
 | 19 | +use ty::{Ty, TyKind, RigidTy};  | 
 | 20 | +use rustc_smir::rustc_internal;  | 
 | 21 | +use stable_mir::*;  | 
 | 22 | +use std::io::Write;  | 
 | 23 | +use std::ops::ControlFlow;  | 
 | 24 | + | 
 | 25 | +const CRATE_NAME: &str = "input";  | 
 | 26 | + | 
 | 27 | +/// This function uses the Stable MIR APIs to get information about the test crate.  | 
 | 28 | +fn test_stable_mir() -> ControlFlow<()> {  | 
 | 29 | + let items = stable_mir::all_local_items();  | 
 | 30 | + | 
 | 31 | + // Get all items and split generic vs monomorphic items.  | 
 | 32 | + let instances: Vec<_> =  | 
 | 33 | + items.into_iter().filter_map(|item| (!item.requires_monomorphization()).then(|| {  | 
 | 34 | + Instance::try_from(item).unwrap()  | 
 | 35 | + })).collect();  | 
 | 36 | + assert_eq!(instances.len(), 1, "Expected one constant");  | 
 | 37 | + | 
 | 38 | + for instance in instances {  | 
 | 39 | + check_ty(instance.ty());  | 
 | 40 | + }  | 
 | 41 | + ControlFlow::Continue(())  | 
 | 42 | +}  | 
 | 43 | + | 
 | 44 | +fn check_ty(ty: Ty) {  | 
 | 45 | + match ty.kind() {  | 
 | 46 | + TyKind::RigidTy(RigidTy::Adt(def, args)) if def.kind().is_struct() => {  | 
 | 47 | + // Ensure field type is also normalized  | 
 | 48 | + def.variants_iter().next().unwrap().fields().into_iter().for_each(|f| {  | 
 | 49 | + check_ty(f.ty_with_args(&args))  | 
 | 50 | + });  | 
 | 51 | + }  | 
 | 52 | + TyKind::RigidTy(RigidTy::Uint(..)) => {}  | 
 | 53 | + kind => unreachable!("Unexpected kind: {kind:?}")  | 
 | 54 | + }  | 
 | 55 | +}  | 
 | 56 | + | 
 | 57 | + | 
 | 58 | +/// This test will generate and analyze a dummy crate using the stable mir.  | 
 | 59 | +/// For that, it will first write the dummy crate into a file.  | 
 | 60 | +/// Then it will create a `StableMir` using custom arguments and then  | 
 | 61 | +/// it will run the compiler.  | 
 | 62 | +fn main() {  | 
 | 63 | + let path = "normalization_input.rs";  | 
 | 64 | + generate_input(&path).unwrap();  | 
 | 65 | + let args = vec![  | 
 | 66 | + "rustc".to_string(),  | 
 | 67 | + "-Cpanic=abort".to_string(),  | 
 | 68 | + "--crate-type=lib".to_string(),  | 
 | 69 | + "--crate-name".to_string(),  | 
 | 70 | + CRATE_NAME.to_string(),  | 
 | 71 | + path.to_string(),  | 
 | 72 | + ];  | 
 | 73 | + run!(args, test_stable_mir).unwrap();  | 
 | 74 | +}  | 
 | 75 | + | 
 | 76 | +fn generate_input(path: &str) -> std::io::Result<()> {  | 
 | 77 | + let mut file = std::fs::File::create(path)?;  | 
 | 78 | + write!(  | 
 | 79 | + file,  | 
 | 80 | + r#"  | 
 | 81 | + pub trait Primitive {{  | 
 | 82 | + type Base;  | 
 | 83 | + }}  | 
 | 84 | +
  | 
 | 85 | + impl Primitive for char {{  | 
 | 86 | + type Base = u32;  | 
 | 87 | + }}  | 
 | 88 | +
  | 
 | 89 | + pub struct Wrapper<T: Primitive>(T::Base);  | 
 | 90 | + pub type WrapperChar = Wrapper<char>;  | 
 | 91 | + pub const NULL_CHAR: WrapperChar = Wrapper::<char>(0);  | 
 | 92 | + "#  | 
 | 93 | + )?;  | 
 | 94 | + Ok(())  | 
 | 95 | +}  | 
0 commit comments