Skip to content

Commit

Permalink
Add trait implementations to the list of items
Browse files Browse the repository at this point in the history
The only thing missing is incoherent implementations for primitive
types
  • Loading branch information
celinval committed Nov 3, 2024
1 parent e4a47ad commit 987e1e0
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 42 deletions.
41 changes: 16 additions & 25 deletions compiler/rustc_smir/src/rustc_smir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_middle::mir;
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::ty::data_structures::HashSet;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_span::def_id::{CRATE_DEF_INDEX, CrateNum, DefId, LOCAL_CRATE};
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
use stable_mir::abi::Layout;
use stable_mir::mir::mono::{InstanceDef, StaticDef};
use stable_mir::ty::{FnDef, MirConstId, Span, TyConstId};
Expand Down Expand Up @@ -97,34 +97,25 @@ impl<'tcx> Tables<'tcx> {
where
F: Fn(&mut Tables<'tcx>, TyCtxt<'tcx>, DefId) -> Option<T>,
{
let crate_def = rustc_span::def_id::DefId { index: CRATE_DEF_INDEX, krate };
let crate_def = krate.as_def_id();
let mut queue = vec![crate_def];
queue.extend_from_slice(tcx.trait_impls_in_crate(krate));
let mut visited = HashSet::default();
let mut result = vec![];
while let Some(next) = queue.pop() {
for def_id in tcx.module_children(next).iter().filter_map(|item| item.res.opt_def_id())
{
if !visited.contains(&def_id) {
visited.insert(def_id);
result.extend(func(self, tcx, def_id));
match tcx.def_kind(def_id) {
DefKind::Mod | DefKind::ForeignMod => queue.push(def_id),
DefKind::Struct | DefKind::Enum | DefKind::Union => {
for associated_item in tcx
.inherent_impls(def_id)
.iter()
.flat_map(|impl_id| tcx.associated_item_def_ids(impl_id))
{
result.extend(func(self, tcx, *associated_item));
}
}
DefKind::Trait => {
for associated_item in tcx.associated_item_def_ids(def_id) {
result.extend(func(self, tcx, *associated_item));
}
}
_ => {}
while let Some(def_id) = queue.pop() {
if visited.insert(def_id) {
result.extend(func(self, tcx, def_id));
match tcx.def_kind(def_id) {
DefKind::Mod | DefKind::ForeignMod | DefKind::Trait => queue.extend(
tcx.module_children(def_id).iter().filter_map(|item| item.res.opt_def_id()),
),
DefKind::Impl { .. } => queue.extend(
tcx.associated_items(def_id).in_definition_order().map(|item| item.def_id),
),
DefKind::Struct | DefKind::Enum | DefKind::Union => {
queue.extend(tcx.inherent_impls(def_id));
}
_ => {}
}
}
}
Expand Down
32 changes: 15 additions & 17 deletions tests/ui-fulldeps/stable-mir/check_crate_defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extern crate stable_mir;

use rustc_smir::rustc_internal;
use stable_mir::CrateDef;
use std::collections::HashSet;
use std::io::Write;
use std::ops::ControlFlow;

Expand Down Expand Up @@ -47,7 +48,12 @@ fn test_stable_mir() -> ControlFlow<()> {
let core = stable_mir::find_crates("core").pop().expect("Cannot find `core` crate");
contains(
&core.fn_defs(),
&["std::fmt::Debug::fmt", "std::option::Option::<T>::is_some", "std::ptr::swap"],
&[
"std::fmt::Debug::fmt",
"std::option::Option::<T>::is_some",
"std::ptr::swap",
"<std::slice::Iter<'a, T> as std::iter::Iterator>::next",
],
);
// Ensure nothing crashes. There is no public static in core that we can test here.
let _ = core.statics();
Expand All @@ -58,25 +64,17 @@ fn test_stable_mir() -> ControlFlow<()> {
/// Check if the list of definitions matches the expected list.
/// Note that order doesn't matter.
fn check_items<T: CrateDef>(items: &[T], expected: &[&str]) {
let item_names: Vec<_> = items.iter().map(|item| item.name()).collect();
let unexpected: Vec<_> =
item_names.iter().filter(|item| !expected.contains(&item.as_str())).collect();
assert!(unexpected.is_empty(), "Unexpected items: {:?}", unexpected);
assert_eq!(items.len(), expected.len(), "Expected items: {expected:?}\nFound: {item_names:?}");
let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect();
let item_names: HashSet<_> = items.iter().map(|item| item.name()).collect();
assert_eq!(item_names, expected);
}

/// Check that the list contains the expected items.
fn contains<T: CrateDef>(items: &[T], expected: &[&str]) {
let item_names: Vec<_> = items.iter().map(|item| item.name()).collect();
let found: Vec<_> =
item_names.iter().filter(|item| expected.contains(&item.as_str())).collect();
assert!(items.len() >= expected.len(), "Missing items: {:?}", item_names);
assert_eq!(
found.len(),
expected.len(),
"Expected items: {:?}\nFound: {found:?}",
&item_names[0..10]
);
fn contains<T: CrateDef + std::fmt::Debug>(items: &[T], expected: &[&str]) {
let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect();
let item_names = items.iter().map(|item| item.name()).collect();
let not_found: Vec<_> = expected.difference(&item_names).collect();
assert!(not_found.is_empty(), "Missing items: {:?}", not_found);
}

/// This test will generate and analyze a dummy crate using the stable mir.
Expand Down

0 comments on commit 987e1e0

Please sign in to comment.