charon_driver/translate/
resolve_path.rs1use std::sync::Arc;
3
4use crate::hax;
5use crate::hax::{BaseState, SInto};
6use anyhow::bail;
7use charon_lib::name_matcher::NamePattern;
8use itertools::Itertools;
9
10use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
11use rustc_middle::ty::{
12 self, FloatTy, IntTy, Mutability, TyCtxt, UintTy, fast_reject::SimplifiedType,
13};
14use rustc_span::symbol::Symbol;
15
16fn find_primitive_impls<'tcx>(
17 tcx: TyCtxt<'tcx>,
18 name: &str,
19) -> impl Iterator<Item = DefId> + use<'tcx> {
20 let ty = match name {
21 "bool" => SimplifiedType::Bool,
22 "char" => SimplifiedType::Char,
23 "str" => SimplifiedType::Str,
24 "array" => SimplifiedType::Array,
25 "slice" => SimplifiedType::Slice,
26 "const_ptr" => SimplifiedType::Ptr(Mutability::Not),
30 "mut_ptr" => SimplifiedType::Ptr(Mutability::Mut),
31 "isize" => SimplifiedType::Int(IntTy::Isize),
32 "i8" => SimplifiedType::Int(IntTy::I8),
33 "i16" => SimplifiedType::Int(IntTy::I16),
34 "i32" => SimplifiedType::Int(IntTy::I32),
35 "i64" => SimplifiedType::Int(IntTy::I64),
36 "i128" => SimplifiedType::Int(IntTy::I128),
37 "usize" => SimplifiedType::Uint(UintTy::Usize),
38 "u8" => SimplifiedType::Uint(UintTy::U8),
39 "u16" => SimplifiedType::Uint(UintTy::U16),
40 "u32" => SimplifiedType::Uint(UintTy::U32),
41 "u64" => SimplifiedType::Uint(UintTy::U64),
42 "u128" => SimplifiedType::Uint(UintTy::U128),
43 "f16" => SimplifiedType::Float(FloatTy::F16),
44 "f32" => SimplifiedType::Float(FloatTy::F32),
45 "f64" => SimplifiedType::Float(FloatTy::F64),
46 "f128" => SimplifiedType::Float(FloatTy::F128),
47 _ => {
48 return [].iter().copied();
49 }
50 };
51 tcx.incoherent_impls(ty).iter().copied()
52}
53
54pub fn def_path_def_ids<'a, 'tcx>(
67 s: &impl BaseState<'tcx>,
68 pat: &'a NamePattern,
69 strict: bool,
70) -> anyhow::Result<Vec<DefId>> {
71 use charon_lib::name_matcher::{PatElem, PatTy};
72 let tcx = s.base().tcx;
73 let mut items: Vec<DefId> = vec![];
74 for (i, elem) in pat.elems.iter().enumerate() {
75 if i == 0 {
76 match elem {
77 PatElem::Ident { name: elem, .. } => {
78 let segment = Symbol::intern(elem);
79 items = tcx
80 .crates(())
81 .iter()
82 .copied()
83 .chain([LOCAL_CRATE])
84 .filter(move |&num| {
86 tcx.crate_name(num) == segment
87 || (num == LOCAL_CRATE && elem == "crate")
88 })
89 .map(CrateNum::as_def_id)
90 .collect_vec();
91 items.extend(find_primitive_impls(tcx, elem));
92 }
93 PatElem::Glob => {
94 items = tcx
95 .crates(())
96 .iter()
97 .copied()
98 .chain([LOCAL_CRATE])
99 .map(CrateNum::as_def_id)
100 .collect_vec();
101 }
102 PatElem::Impl(impl_pat) => match impl_pat.elems.as_slice() {
103 [
104 ..,
105 PatElem::Ident {
106 generics,
107 is_trait: true,
108 ..
109 },
110 ] => match generics.as_slice() {
111 [] => bail!("malformed trait impl pattern"),
112 [PatTy::Pat(self_pat)] => {
113 let impls = def_path_def_ids(s, impl_pat, strict)?
114 .into_iter()
115 .flat_map(|trait_def_id| tcx.all_impls(trait_def_id));
116 match self_pat.elems.as_slice() {
117 [PatElem::Glob] => {
118 items = impls.collect_vec();
119 }
120 _ => {
121 let self_ty_def_ids = def_path_def_ids(s, self_pat, strict)?;
122 items = impls
123 .filter(|impl_def_id| {
124 let impl_self_ty = tcx
125 .impl_trait_ref(*impl_def_id)
126 .skip_binder()
127 .self_ty();
128 if let ty::Adt(adt_def, _) = impl_self_ty.kind() {
129 self_ty_def_ids.contains(&adt_def.did())
130 } else {
131 false
132 }
133 })
134 .collect_vec();
135 }
136 }
137 }
138 [_] => bail!("`--start-from` only supports implementations on named types"),
139 [_, _, ..] => bail!("`--start-from` does not support trait generics"),
140 },
141 [
142 ..,
143 PatElem::Ident {
144 is_trait: false, ..
145 },
146 ] => bail!("`--start-from` does not support inherent impls"),
147 _ => bail!("`--start-from` does not support this impl pattern"),
148 },
149 }
150 } else {
151 let nameable_children = items.iter().copied().flat_map(|def_id| {
152 let hax_def: Arc<hax::FullDef<'tcx>> = def_id.sinto(s).full_def(s);
153 hax_def.nameable_children(s)
154 });
155 match elem {
156 PatElem::Ident { name: elem, .. } => {
157 items = nameable_children
158 .filter(|(child_name, _)| child_name.as_str() == elem)
159 .filter_map(|(_, def_id)| def_id.as_real_def_id())
160 .collect();
161 }
162 PatElem::Glob => {
163 items = nameable_children
164 .filter_map(|(_, def_id)| def_id.as_real_def_id())
165 .collect();
166 }
167 PatElem::Impl(_) => bail!(
168 "`--start-from` only supports impl patterns if they're the first element of the path"
169 ),
170 }
171 }
172 if strict && items.is_empty() {
173 let prefix = NamePattern {
174 elems: pat.elems[..=i].to_vec(),
175 };
176 if i == 0 {
177 bail!(
178 "path `{prefix}` does not correspond to any item; did you mean `crate::{prefix}`?"
179 )
180 } else {
181 bail!("path `{prefix}` does not correspond to any item")
182 }
183 }
184 }
185 Ok(items)
186}