Skip to content

Commit af3c2c9

Browse files
committed
Fix all_trait* methods to return all trait available
Also provide a mechanism to retrieve traits and implementations for a given crate.
1 parent 090d5ea commit af3c2c9

File tree

6 files changed

+184
-15
lines changed

6 files changed

+184
-15
lines changed

compiler/rustc_smir/src/rustc_internal/internal.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use stable_mir::ty::{
1717
GenericArgKind, GenericArgs, IndexedVal, IntTy, Movability, Region, RigidTy, Span, TermKind,
1818
TraitRef, Ty, UintTy, VariantDef, VariantIdx,
1919
};
20-
use stable_mir::{CrateItem, DefId};
20+
use stable_mir::{CrateItem, CrateNum, DefId};
2121

2222
use super::RustcInternal;
2323

@@ -28,6 +28,13 @@ impl<'tcx> RustcInternal<'tcx> for CrateItem {
2828
}
2929
}
3030

31+
impl<'tcx> RustcInternal<'tcx> for CrateNum {
32+
type T = rustc_span::def_id::CrateNum;
33+
fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
34+
rustc_span::def_id::CrateNum::from_usize(*self)
35+
}
36+
}
37+
3138
impl<'tcx> RustcInternal<'tcx> for DefId {
3239
type T = rustc_span::def_id::DefId;
3340
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {

compiler/rustc_smir/src/rustc_smir/context.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ use stable_mir::ty::{
2525
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs,
2626
LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, VariantDef,
2727
};
28-
use stable_mir::{Crate, CrateItem, DefId, Error, Filename, ItemKind, Symbol};
28+
use stable_mir::{Crate, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol};
2929
use std::cell::RefCell;
30+
use std::iter;
3031

3132
use crate::rustc_internal::{internal, RustcInternal};
3233
use crate::rustc_smir::builder::BodyBuilder;
@@ -67,10 +68,15 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
6768
}
6869

6970
fn all_trait_decls(&self) -> stable_mir::TraitDecls {
71+
let mut tables = self.0.borrow_mut();
72+
tables.tcx.all_traits().map(|trait_def_id| tables.trait_def(trait_def_id)).collect()
73+
}
74+
75+
fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls {
7076
let mut tables = self.0.borrow_mut();
7177
tables
7278
.tcx
73-
.traits(LOCAL_CRATE)
79+
.traits(crate_num.internal(&mut *tables))
7480
.iter()
7581
.map(|trait_def_id| tables.trait_def(*trait_def_id))
7682
.collect()
@@ -84,10 +90,20 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
8490
}
8591

8692
fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
93+
let mut tables = self.0.borrow_mut();
94+
let tcx = tables.tcx;
95+
iter::once(LOCAL_CRATE)
96+
.chain(tables.tcx.crates(()).iter().copied())
97+
.flat_map(|cnum| tcx.trait_impls_in_crate(cnum).iter())
98+
.map(|impl_def_id| tables.impl_def(*impl_def_id))
99+
.collect()
100+
}
101+
102+
fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls {
87103
let mut tables = self.0.borrow_mut();
88104
tables
89105
.tcx
90-
.trait_impls_in_crate(LOCAL_CRATE)
106+
.trait_impls_in_crate(crate_num.internal(&mut *tables))
91107
.iter()
92108
.map(|impl_def_id| tables.impl_def(*impl_def_id))
93109
.collect()

compiler/stable_mir/src/compiler_interface.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use crate::ty::{
1616
TraitDef, Ty, TyKind, VariantDef,
1717
};
1818
use crate::{
19-
mir, Crate, CrateItem, CrateItems, DefId, Error, Filename, ImplTraitDecls, ItemKind, Symbol,
20-
TraitDecls,
19+
mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind,
20+
Symbol, TraitDecls,
2121
};
2222

2323
/// This trait defines the interface between stable_mir and the Rust compiler.
@@ -32,8 +32,10 @@ pub trait Context {
3232
/// Check whether the body of a function is available.
3333
fn has_body(&self, item: DefId) -> bool;
3434
fn all_trait_decls(&self) -> TraitDecls;
35+
fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls;
3536
fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
3637
fn all_trait_impls(&self) -> ImplTraitDecls;
38+
fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls;
3739
fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
3840
fn generics_of(&self, def_id: DefId) -> Generics;
3941
fn predicates_of(&self, def_id: DefId) -> GenericPredicates;

compiler/stable_mir/src/lib.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub use crate::error::*;
3131
use crate::mir::pretty::function_name;
3232
use crate::mir::Body;
3333
use crate::mir::Mutability;
34-
use crate::ty::{ImplDef, ImplTrait, IndexedVal, Span, TraitDecl, TraitDef, Ty};
34+
use crate::ty::{ImplDef, IndexedVal, Span, TraitDef, Ty};
3535

3636
pub mod abi;
3737
#[macro_use]
@@ -86,6 +86,18 @@ pub struct Crate {
8686
pub is_local: bool,
8787
}
8888

89+
impl Crate {
90+
/// The list of traits declared in this crate.
91+
pub fn trait_decls(&self) -> TraitDecls {
92+
with(|cx| cx.trait_decls(self.id))
93+
}
94+
95+
/// The list of trait implementations in this crate.
96+
pub fn trait_impls(&self) -> ImplTraitDecls {
97+
with(|cx| cx.trait_impls(self.id))
98+
}
99+
}
100+
89101
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
90102
pub enum ItemKind {
91103
Fn,
@@ -169,18 +181,10 @@ pub fn all_trait_decls() -> TraitDecls {
169181
with(|cx| cx.all_trait_decls())
170182
}
171183

172-
pub fn trait_decl(trait_def: &TraitDef) -> TraitDecl {
173-
with(|cx| cx.trait_decl(trait_def))
174-
}
175-
176184
pub fn all_trait_impls() -> ImplTraitDecls {
177185
with(|cx| cx.all_trait_impls())
178186
}
179187

180-
pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
181-
with(|cx| cx.trait_impl(trait_impl))
182-
}
183-
184188
/// A type that provides internal information but that can still be used for debug purpose.
185189
#[derive(Clone, PartialEq, Eq, Hash)]
186190
pub struct Opaque(String);

compiler/stable_mir/src/ty.rs

+15
Original file line numberDiff line numberDiff line change
@@ -714,9 +714,16 @@ crate_def! {
714714
}
715715

716716
crate_def! {
717+
/// A trait's definition.
717718
pub TraitDef;
718719
}
719720

721+
impl TraitDef {
722+
pub fn declaration(trait_def: &TraitDef) -> TraitDecl {
723+
with(|cx| cx.trait_decl(trait_def))
724+
}
725+
}
726+
720727
crate_def! {
721728
pub GenericDef;
722729
}
@@ -726,9 +733,17 @@ crate_def! {
726733
}
727734

728735
crate_def! {
736+
/// A trait impl definition.
729737
pub ImplDef;
730738
}
731739

740+
impl ImplDef {
741+
/// Retrieve information about this implementation.
742+
pub fn trait_impl(&self) -> ImplTrait {
743+
with(|cx| cx.trait_impl(self))
744+
}
745+
}
746+
732747
crate_def! {
733748
pub RegionDef;
734749
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// run-pass
2+
//! Test that users are able to retrieve information about trait declarations and implementations.
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+
#![feature(assert_matches)]
12+
#![feature(control_flow_enum)]
13+
14+
extern crate rustc_middle;
15+
#[macro_use]
16+
extern crate rustc_smir;
17+
extern crate rustc_driver;
18+
extern crate rustc_interface;
19+
extern crate stable_mir;
20+
21+
use rustc_middle::ty::TyCtxt;
22+
use rustc_smir::rustc_internal;
23+
use stable_mir::CrateDef;
24+
use std::collections::HashSet;
25+
use std::io::Write;
26+
use std::ops::ControlFlow;
27+
28+
const CRATE_NAME: &str = "trait_test";
29+
30+
/// This function uses the Stable MIR APIs to get information about the test crate.
31+
fn test_traits() -> ControlFlow<()> {
32+
let local_crate = stable_mir::local_crate();
33+
let local_traits = local_crate.trait_decls();
34+
assert_eq!(local_traits.len(), 1, "Expected `Max` trait, but found {:?}", local_traits);
35+
assert_eq!(&local_traits[0].name(), "Max");
36+
37+
let local_impls = local_crate.trait_impls();
38+
let impl_names = local_impls.iter().map(|trait_impl| trait_impl.name()).collect::<HashSet<_>>();
39+
assert_impl(&impl_names, "<Positive as Max>");
40+
assert_impl(&impl_names, "<Positive as std::marker::Copy>");
41+
assert_impl(&impl_names, "<Positive as std::clone::Clone>");
42+
assert_impl(&impl_names, "<Positive as std::fmt::Debug>");
43+
assert_impl(&impl_names, "<Positive as std::cmp::PartialEq>");
44+
assert_impl(&impl_names, "<Positive as std::cmp::Eq>");
45+
assert_impl(&impl_names, "<Positive as std::convert::TryFrom<u64>>");
46+
assert_impl(&impl_names, "<u64 as Max>");
47+
assert_impl(&impl_names, "<impl std::convert::From<Positive> for u64>");
48+
49+
let all_traits = stable_mir::all_trait_decls();
50+
assert!(all_traits.len() > local_traits.len());
51+
assert!(
52+
local_traits.iter().all(|t| all_traits.contains(t)),
53+
"Local: {local_traits:#?}, All: {all_traits:#?}"
54+
);
55+
56+
let all_impls = stable_mir::all_trait_impls();
57+
assert!(all_impls.len() > local_impls.len());
58+
assert!(
59+
local_impls.iter().all(|t| all_impls.contains(t)),
60+
"Local: {local_impls:#?}, All: {all_impls:#?}"
61+
);
62+
ControlFlow::Continue(())
63+
}
64+
65+
fn assert_impl(impl_names: &HashSet<String>, target: &str) {
66+
assert!(
67+
impl_names.contains(target),
68+
"Failed to find `{target}`. Implementations available: {impl_names:?}",
69+
);
70+
}
71+
72+
/// This test will generate and analyze a dummy crate using the stable mir.
73+
/// For that, it will first write the dummy crate into a file.
74+
/// Then it will create a `StableMir` using custom arguments and then
75+
/// it will run the compiler.
76+
fn main() {
77+
let path = "trait_queries.rs";
78+
generate_input(&path).unwrap();
79+
let args = vec![
80+
"rustc".to_string(),
81+
"--crate-type=lib".to_string(),
82+
"--crate-name".to_string(),
83+
CRATE_NAME.to_string(),
84+
path.to_string(),
85+
];
86+
run!(args, test_traits()).unwrap();
87+
}
88+
89+
fn generate_input(path: &str) -> std::io::Result<()> {
90+
let mut file = std::fs::File::create(path)?;
91+
write!(
92+
file,
93+
r#"
94+
use std::convert::TryFrom;
95+
96+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
97+
pub struct Positive(u64);
98+
99+
impl TryFrom<u64> for Positive {{
100+
type Error = ();
101+
fn try_from(val: u64) -> Result<Positive, Self::Error> {{
102+
if val > 0 {{ Ok(Positive(val)) }} else {{ Err(()) }}
103+
}}
104+
}}
105+
106+
impl From<Positive> for u64 {{
107+
fn from(val: Positive) -> u64 {{ val.0 }}
108+
}}
109+
110+
pub trait Max {{
111+
fn is_max(&self) -> bool;
112+
}}
113+
114+
impl Max for u64 {{
115+
fn is_max(&self) -> bool {{ *self == u64::MAX }}
116+
}}
117+
118+
impl Max for Positive {{
119+
fn is_max(&self) -> bool {{ self.0.is_max() }}
120+
}}
121+
122+
"#
123+
)?;
124+
Ok(())
125+
}

0 commit comments

Comments
 (0)