use super::exposure::*;
use crate::finding::*;
use crate::resolve::*;
use crate::syn_util::{GenericsPosition, impl_generics_positions};
pub(crate) fn collect_trait_impl_exposures(
item: &syn::Item,
module: &str,
uses: &UseMap,
ordinal: usize,
out: &mut Vec<PathExposure>,
) {
let syn::Item::Impl(item) = item else { return };
let Some((_, trait_path, _)) = &item.trait_ else {
return; };
let trait_label = path_to_string(trait_path).unwrap_or_else(|| format!("trait_#{ordinal}"));
let params = type_param_names(&item.generics);
let self_label = canonical_self_owner(&item.self_ty, uses, module, ordinal, ¶ms);
let seam = |position: TraitImplPosition| PublicSeam::TraitImpl {
trait_ref: trait_label.clone(),
owner: self_label.clone(),
position,
};
if let Some(syn::PathArguments::AngleBracketed(args)) =
trait_path.segments.last().map(|s| &s.arguments)
{
let seam = seam(TraitImplPosition::TraitArg);
for arg in &args.args {
match arg {
syn::GenericArgument::Type(ty) => {
out.extend(tag_paths(paths_in_type_scoped(ty, ¶ms), &seam))
}
syn::GenericArgument::AssocType(at) => {
out.extend(tag_paths(paths_in_type_scoped(&at.ty, ¶ms), &seam))
}
_ => {}
}
}
}
out.extend(tag_paths(
paths_in_type_scoped(&item.self_ty, ¶ms),
&seam(TraitImplPosition::SelfType),
));
for (key, positions) in impl_generics_positions(&item.generics, ordinal) {
let seam = seam(TraitImplPosition::Where(key));
for position in positions {
let paths = match position {
GenericsPosition::Bounds(bounds) => paths_in_bounds_scoped(bounds, ¶ms),
GenericsPosition::Type(ty) => paths_in_type_scoped(ty, ¶ms),
};
out.extend(tag_paths(paths, &seam));
}
}
for impl_item in &item.items {
match impl_item {
syn::ImplItem::Type(assoc) => {
let seam = seam(TraitImplPosition::Assoc(strip_raw(
&assoc.ident.to_string(),
)));
out.extend(tag_paths(paths_in_type_scoped(&assoc.ty, ¶ms), &seam));
}
syn::ImplItem::Const(assoc) => {
let seam = seam(TraitImplPosition::Assoc(strip_raw(
&assoc.ident.to_string(),
)));
out.extend(tag_paths(paths_in_type_scoped(&assoc.ty, ¶ms), &seam));
}
syn::ImplItem::Fn(method) => {
let seam = seam(TraitImplPosition::MethodReturn(strip_raw(
&method.sig.ident.to_string(),
)));
out.extend(tag_paths(
paths_in_return_scoped(&method.sig, ¶ms),
&seam,
));
}
_ => {}
}
}
}