1pub(crate) mod refinement_resolver;
2
3use std::collections::hash_map;
4
5use flux_common::result::{ErrorCollector, ResultExt};
6use flux_errors::Errors;
7use flux_middle::{
8 ResolverOutput, Specs,
9 def_id::{FluxDefId, FluxLocalDefId, MaybeExternId},
10 fhir,
11 global_env::GlobalEnv,
12};
13use flux_syntax::{
14 surface::{self, Ident, visit::Visitor as _},
15 symbols::sym,
16};
17use hir::{ItemId, ItemKind, OwnerId, def::DefKind};
18use rustc_data_structures::unord::{ExtendUnord, UnordMap};
19use rustc_errors::ErrorGuaranteed;
20use rustc_hash::FxHashMap;
21use rustc_hir::{
22 self as hir, CRATE_HIR_ID, CRATE_OWNER_ID, ParamName, PrimTy,
23 def::{
24 CtorOf,
25 Namespace::{self, *},
26 PerNS,
27 },
28 def_id::CRATE_DEF_ID,
29};
30use rustc_middle::{metadata::ModChild, ty::TyCtxt};
31use rustc_span::{Span, Symbol, def_id::DefId, symbol::kw};
32
33use self::refinement_resolver::RefinementResolver;
34
35type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
36
37pub(crate) fn resolve_crate(genv: GlobalEnv) -> ResolverOutput {
38 match try_resolve_crate(genv) {
39 Ok(output) => output,
40 Err(err) => genv.sess().abort(err),
41 }
42}
43
44fn try_resolve_crate(genv: GlobalEnv) -> Result<ResolverOutput> {
45 let specs = genv.collect_specs();
46 let mut resolver = CrateResolver::new(genv, specs);
47
48 genv.tcx().hir_walk_toplevel_module(&mut resolver);
49
50 resolver.into_output()
51}
52
53pub(crate) struct CrateResolver<'genv, 'tcx> {
54 genv: GlobalEnv<'genv, 'tcx>,
55 specs: &'genv Specs,
56 output: ResolverOutput,
57 ribs: PerNS<Vec<Rib>>,
58 crates: UnordMap<Symbol, DefId>,
60 prelude: PerNS<Rib>,
61 qualifiers: UnordMap<Symbol, FluxLocalDefId>,
62 func_decls: UnordMap<Symbol, fhir::SpecFuncKind>,
63 sort_decls: UnordMap<Symbol, FluxDefId>,
64 primop_props: UnordMap<Symbol, FluxDefId>,
65 err: Option<ErrorGuaranteed>,
66 current_module: OwnerId,
69}
70
71#[derive(Default)]
73struct DefinitionMap {
74 defined: FxHashMap<Ident, ()>,
75}
76
77impl DefinitionMap {
78 fn define(&mut self, name: Ident) -> std::result::Result<(), errors::DuplicateDefinition> {
79 match self.defined.entry(name) {
80 hash_map::Entry::Occupied(entry) => {
81 Err(errors::DuplicateDefinition {
82 span: name.span,
83 previous_definition: entry.key().span,
84 name,
85 })
86 }
87 hash_map::Entry::Vacant(entry) => {
88 entry.insert(());
89 Ok(())
90 }
91 }
92 }
93}
94
95impl<'genv, 'tcx> CrateResolver<'genv, 'tcx> {
96 pub fn new(genv: GlobalEnv<'genv, 'tcx>, specs: &'genv Specs) -> Self {
97 Self {
98 genv,
99 output: ResolverOutput::default(),
100 specs,
101 ribs: PerNS { type_ns: vec![], value_ns: vec![], macro_ns: vec![] },
102 crates: mk_crate_mapping(genv.tcx()),
103 prelude: PerNS {
104 type_ns: builtin_types_rib(),
105 value_ns: Rib::new(RibKind::Normal),
106 macro_ns: Rib::new(RibKind::Normal),
107 },
108 err: None,
109 qualifiers: Default::default(),
110 func_decls: Default::default(),
111 primop_props: Default::default(),
112 sort_decls: Default::default(),
113 current_module: CRATE_OWNER_ID,
114 }
115 }
116
117 #[allow(clippy::disallowed_methods, reason = "`flux_items_by_parent` is the source of truth")]
118 fn define_flux_global_items(&mut self) {
119 let mut definitions = DefinitionMap::default();
121 for (parent, items) in &self.specs.flux_items_by_parent {
122 for item in items {
123 definitions
126 .define(item.name())
127 .emit(&self.genv)
128 .collect_err(&mut self.err);
129
130 match item {
131 surface::FluxItem::Qualifier(qual) => {
132 let def_id = FluxLocalDefId::new(parent.def_id, qual.name.name);
133 self.qualifiers.insert(qual.name.name, def_id);
134 }
135 surface::FluxItem::FuncDef(defn) => {
136 let parent = parent.def_id.to_def_id();
137 let name = defn.name.name;
138 let def_id = FluxDefId::new(parent, name);
139 let kind = fhir::SpecFuncKind::Def(def_id);
140 self.func_decls.insert(defn.name.name, kind);
141 }
142 surface::FluxItem::PrimOpProp(primop_prop) => {
143 let name = primop_prop.name.name;
144 let parent = parent.def_id.to_def_id();
145 let def_id = FluxDefId::new(parent, name);
146 self.primop_props.insert(name, def_id);
147 }
148 surface::FluxItem::SortDecl(sort_decl) => {
149 let def_id = FluxDefId::new(parent.def_id.to_def_id(), sort_decl.name.name);
150 self.sort_decls.insert(sort_decl.name.name, def_id);
151 }
152 }
153 }
154 }
155
156 self.func_decls.extend_unord(
157 flux_middle::THEORY_FUNCS
158 .items()
159 .map(|(_, itf)| (itf.name, fhir::SpecFuncKind::Thy(itf.itf))),
160 );
161 self.func_decls
162 .insert(Symbol::intern("cast"), fhir::SpecFuncKind::Cast);
163 self.func_decls
164 .insert(sym::ptr_size, fhir::SpecFuncKind::PtrSize);
165 }
166
167 fn define_items(&mut self, item_ids: impl IntoIterator<Item = &'tcx ItemId>) {
168 for item_id in item_ids {
169 let item = self.genv.tcx().hir_item(*item_id);
170 let def_kind = match item.kind {
171 ItemKind::Use(path, kind) => {
172 match kind {
173 hir::UseKind::Single(ident) => {
174 let name = ident.name;
175 if let Some(res) = path.res.value_ns
176 && let Ok(res) = fhir::Res::try_from(res)
177 {
178 self.define_res_in(name, res, ValueNS);
179 }
180 if let Some(res) = path.res.type_ns
181 && let Ok(res) = fhir::Res::try_from(res)
182 {
183 self.define_res_in(name, res, TypeNS);
184 }
185 }
186 hir::UseKind::Glob => {
187 let is_prelude = is_prelude_import(self.genv.tcx(), item);
188 for mod_child in self.glob_imports(path) {
189 if let Ok(res) = fhir::Res::try_from(mod_child.res)
190 && let Some(ns @ (TypeNS | ValueNS)) = res.ns()
191 {
192 let name = mod_child.ident.name;
193 if is_prelude {
194 self.define_in_prelude(name, res, ns);
195 } else {
196 self.define_res_in(name, res, ns);
197 }
198 }
199 }
200 }
201 hir::UseKind::ListStem => {}
202 }
203 continue;
204 }
205 ItemKind::TyAlias(..) => DefKind::TyAlias,
206 ItemKind::Enum(..) => DefKind::Enum,
207 ItemKind::Struct(..) => DefKind::Struct,
208 ItemKind::Trait(..) => DefKind::Trait,
209 ItemKind::Mod(..) => DefKind::Mod,
210 ItemKind::Const(..) => DefKind::Const,
211 ItemKind::ForeignMod { items, .. } => {
212 self.define_foreign_items(items);
213 continue;
214 }
215 _ => continue,
216 };
217 if let Some(ns) = def_kind.ns()
218 && let Some(ident) = item.kind.ident()
219 {
220 self.define_res_in(
221 ident.name,
222 fhir::Res::Def(def_kind, item.owner_id.to_def_id()),
223 ns,
224 );
225 }
226 }
227 }
228
229 fn define_foreign_items(&mut self, items: &[rustc_hir::ForeignItemId]) {
230 for item_id in items {
231 let item = self.genv.tcx().hir_foreign_item(*item_id);
232 match item.kind {
233 rustc_hir::ForeignItemKind::Type => {
234 self.define_res_in(
235 item.ident.name,
236 fhir::Res::Def(DefKind::ForeignTy, item.owner_id.to_def_id()),
237 TypeNS,
238 );
239 }
240 rustc_hir::ForeignItemKind::Fn(..) | rustc_hir::ForeignItemKind::Static(..) => {}
241 }
242 }
243 }
244
245 fn define_res_in(&mut self, name: Symbol, res: fhir::Res, ns: Namespace) {
246 self.ribs[ns].last_mut().unwrap().bindings.insert(name, res);
247 }
248
249 fn define_in_prelude(&mut self, name: Symbol, res: fhir::Res, ns: Namespace) {
250 self.prelude[ns].bindings.insert(name, res);
251 }
252
253 fn push_rib(&mut self, ns: Namespace, kind: RibKind) {
254 self.ribs[ns].push(Rib::new(kind));
255 }
256
257 fn pop_rib(&mut self, ns: Namespace) {
258 self.ribs[ns].pop();
259 }
260
261 fn define_generics(&mut self, def_id: MaybeExternId<OwnerId>) {
262 let generics = self
263 .genv
264 .tcx()
265 .hir_get_generics(def_id.local_id().def_id)
266 .unwrap();
267 for param in generics.params {
268 let def_kind = self.genv.tcx().def_kind(param.def_id);
269 if let ParamName::Plain(name) = param.name
270 && let Some(ns) = def_kind.ns()
271 {
272 debug_assert!(matches!(def_kind, DefKind::TyParam | DefKind::ConstParam));
273 let param_id = self.genv.maybe_extern_id(param.def_id).resolved_id();
274 self.define_res_in(name.name, fhir::Res::Def(def_kind, param_id), ns);
275 }
276 }
277 }
278
279 fn resolve_flux_items(&mut self, parent: OwnerId) {
280 let Some(items) = self.specs.flux_items_by_parent.get(&parent) else { return };
281 for item in items {
282 RefinementResolver::resolve_flux_item(self, item).collect_err(&mut self.err);
283 }
284 }
285
286 fn resolve_item(&mut self, item: &surface::Item) -> Result {
287 ItemResolver::run(self, |item_resolver| item_resolver.visit_item(item))?;
288 RefinementResolver::resolve_item(self, item)
289 }
290
291 fn resolve_trait_item(&mut self, item: &surface::TraitItemFn) -> Result {
292 ItemResolver::run(self, |item_resolver| item_resolver.visit_trait_item(item))?;
293 RefinementResolver::resolve_trait_item(self, item)
294 }
295
296 fn resolve_impl_item(&mut self, item: &surface::ImplItemFn) -> Result {
297 ItemResolver::run(self, |item_resolver| item_resolver.visit_impl_item(item))?;
298 RefinementResolver::resolve_impl_item(self, item)
299 }
300
301 fn resolve_path_with_ribs<S: Segment>(
302 &mut self,
303 segments: &[S],
304 ns: Namespace,
305 ) -> Option<fhir::PartialRes> {
306 let mut module: Option<Module> = None;
307 for (segment_idx, segment) in segments.iter().enumerate() {
308 let is_last = segment_idx + 1 == segments.len();
309 let ns = if is_last { ns } else { TypeNS };
310
311 let base_res = if let Some(module) = &module {
312 self.resolve_ident_in_module(module, segment.ident(), ns)?
313 } else {
314 self.resolve_ident_with_ribs(segment.ident(), ns)?
315 };
316
317 S::record_segment_res(self, segment, base_res);
318
319 if is_last {
320 return Some(fhir::PartialRes::new(base_res));
321 }
322
323 match base_res {
324 fhir::Res::Def(DefKind::Mod, module_id) => {
325 module = Some(Module::new(ModuleKind::Mod, module_id));
326 }
327 fhir::Res::Def(DefKind::Trait, module_id) => {
328 module = Some(Module::new(ModuleKind::Trait, module_id));
329 }
330 fhir::Res::Def(DefKind::Enum, module_id) => {
331 module = Some(Module::new(ModuleKind::Enum, module_id));
332 }
333 _ => {
334 return Some(fhir::PartialRes::with_unresolved_segments(
335 base_res,
336 segments.len() - segment_idx - 1,
337 ));
338 }
339 }
340 }
341 None
342 }
343
344 fn resolve_ident_with_ribs(&self, ident: Ident, ns: Namespace) -> Option<fhir::Res> {
345 for rib in self.ribs[ns].iter().rev() {
346 if let Some(res) = rib.bindings.get(&ident.name) {
347 return Some(*res);
348 }
349 if matches!(rib.kind, RibKind::Module) {
350 break;
351 }
352 }
353 if ns == TypeNS {
354 if let Some(crate_id) = self.crates.get(&ident.name) {
355 return Some(fhir::Res::Def(DefKind::Mod, *crate_id));
356 }
357 if ident.name == kw::Crate {
359 return Some(fhir::Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()));
360 }
361 if ident.name == kw::Super
362 && let Some(parent) = self.genv.tcx().opt_local_parent(self.current_module.def_id)
363 {
364 return Some(fhir::Res::Def(DefKind::Mod, parent.to_def_id()));
365 }
366 }
367
368 if let Some(res) = self.prelude[ns].bindings.get(&ident.name) {
369 return Some(*res);
370 }
371 None
372 }
373
374 fn glob_imports(
375 &mut self,
376 path: &hir::UsePath,
377 ) -> impl Iterator<Item = &'tcx ModChild> + use<'tcx> {
378 let tcx = self.genv.tcx();
382 let curr_mod = self.current_module.to_def_id();
383 self.resolve_path_with_ribs(path.segments, TypeNS)
384 .and_then(|partial_res| partial_res.full_res())
385 .and_then(|res| {
386 if let fhir::Res::Def(DefKind::Mod, module_id) = res {
387 Some(module_id)
388 } else {
389 None
390 }
391 })
392 .into_iter()
393 .flat_map(move |module_id| visible_module_children(tcx, module_id, curr_mod))
394 }
395
396 fn resolve_ident_in_module(
397 &self,
398 module: &Module,
399 ident: Ident,
400 ns: Namespace,
401 ) -> Option<fhir::Res> {
402 let tcx = self.genv.tcx();
403 match module.kind {
404 ModuleKind::Mod => {
405 let module_id = module.def_id;
406 let current_mod = self.current_module.to_def_id();
407 visible_module_children(tcx, module_id, current_mod)
408 .find(|child| {
409 child.res.matches_ns(ns) && tcx.hygienic_eq(ident, child.ident, current_mod)
410 })
411 .and_then(|child| fhir::Res::try_from(child.res).ok())
412 }
413 ModuleKind::Trait => {
414 let trait_id = module.def_id;
415 tcx.associated_items(trait_id)
416 .find_by_ident_and_namespace(tcx, ident, ns, trait_id)
417 .map(|assoc| fhir::Res::Def(assoc.kind.as_def_kind(), assoc.def_id))
418 }
419 ModuleKind::Enum => {
420 tcx.adt_def(module.def_id)
421 .variants()
422 .iter()
423 .find(|data| data.name == ident.name)
424 .and_then(|data| {
425 let (kind, def_id) = match (ns, data.ctor) {
426 (TypeNS, _) => (DefKind::Variant, data.def_id),
427 (ValueNS, Some((ctor_kind, ctor_id))) => {
428 (DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_id)
429 }
430 _ => return None,
431 };
432 Some(fhir::Res::Def(kind, def_id))
433 })
434 }
435 }
436 }
437
438 pub fn into_output(self) -> Result<ResolverOutput> {
439 self.err.into_result()?;
440 Ok(self.output)
441 }
442}
443
444impl<'tcx> hir::intravisit::Visitor<'tcx> for CrateResolver<'_, 'tcx> {
445 type NestedFilter = rustc_middle::hir::nested_filter::All;
446
447 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
448 self.genv.tcx()
449 }
450
451 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _s: Span, hir_id: hir::HirId) {
452 let old_mod = self.current_module;
453 self.current_module = hir_id.expect_owner();
454 self.push_rib(TypeNS, RibKind::Module);
455 self.push_rib(ValueNS, RibKind::Module);
456
457 self.define_items(module.item_ids);
458
459 if hir_id == CRATE_HIR_ID {
461 self.define_flux_global_items();
462 }
463
464 self.resolve_flux_items(hir_id.expect_owner());
466
467 hir::intravisit::walk_mod(self, module);
468
469 self.pop_rib(ValueNS);
470 self.pop_rib(TypeNS);
471 self.current_module = old_mod;
472 }
473
474 fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
475 self.push_rib(TypeNS, RibKind::Normal);
476 self.push_rib(ValueNS, RibKind::Normal);
477
478 let item_ids = block.stmts.iter().filter_map(|stmt| {
479 if let hir::StmtKind::Item(item_id) = &stmt.kind { Some(item_id) } else { None }
480 });
481 self.define_items(item_ids);
482 self.resolve_flux_items(self.genv.tcx().hir_get_parent_item(block.hir_id));
483
484 hir::intravisit::walk_block(self, block);
485
486 self.pop_rib(ValueNS);
487 self.pop_rib(TypeNS);
488 }
489
490 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
491 if self.genv.is_dummy(item.owner_id.def_id) {
492 return;
493 }
494 let def_id = self
495 .genv
496 .maybe_extern_id(item.owner_id.def_id)
497 .map(|def_id| OwnerId { def_id });
498
499 self.push_rib(TypeNS, RibKind::Normal);
500 self.push_rib(ValueNS, RibKind::Normal);
501
502 match item.kind {
503 ItemKind::Trait(..) => {
504 self.define_generics(def_id);
505 self.define_res_in(
506 kw::SelfUpper,
507 fhir::Res::SelfTyParam { trait_: def_id.resolved_id() },
508 TypeNS,
509 );
510 }
511 ItemKind::Impl(hir::Impl { of_trait, .. }) => {
512 self.define_generics(def_id);
513 self.define_res_in(
514 kw::SelfUpper,
515 fhir::Res::SelfTyAlias {
516 alias_to: def_id.resolved_id(),
517 is_trait_impl: of_trait.is_some(),
518 },
519 TypeNS,
520 );
521 }
522 ItemKind::TyAlias(..) => {
523 self.define_generics(def_id);
524 }
525 ItemKind::Enum(..) => {
526 self.define_generics(def_id);
527 self.define_res_in(
528 kw::SelfUpper,
529 fhir::Res::SelfTyAlias { alias_to: def_id.resolved_id(), is_trait_impl: false },
530 TypeNS,
531 );
532 }
533 ItemKind::Struct(..) => {
534 self.define_generics(def_id);
535 self.define_res_in(
536 kw::SelfUpper,
537 fhir::Res::SelfTyAlias { alias_to: def_id.resolved_id(), is_trait_impl: false },
538 TypeNS,
539 );
540 }
541 ItemKind::Fn { .. } => {
542 self.define_generics(def_id);
543 }
544 _ => {}
545 }
546 if let Some(item) = self.specs.get_item(def_id.local_id()) {
547 self.resolve_item(item).collect_err(&mut self.err);
548 }
549
550 hir::intravisit::walk_item(self, item);
551
552 self.pop_rib(ValueNS);
553 self.pop_rib(TypeNS);
554 }
555
556 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
557 let def_id = self
558 .genv
559 .maybe_extern_id(impl_item.owner_id.def_id)
560 .map(|def_id| OwnerId { def_id });
561
562 self.push_rib(TypeNS, RibKind::Normal);
563 if let Some(item) = self.specs.get_impl_item(def_id.local_id()) {
564 self.define_generics(def_id);
565 self.resolve_impl_item(item).collect_err(&mut self.err);
566 }
567 hir::intravisit::walk_impl_item(self, impl_item);
568 self.pop_rib(TypeNS);
569 }
570
571 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
572 let def_id = self
573 .genv
574 .maybe_extern_id(trait_item.owner_id.def_id)
575 .map(|def_id| OwnerId { def_id });
576
577 self.push_rib(TypeNS, RibKind::Normal);
578 if let Some(item) = self.specs.get_trait_item(def_id.local_id()) {
579 self.define_generics(def_id);
580 self.resolve_trait_item(item).collect_err(&mut self.err);
581 }
582 hir::intravisit::walk_trait_item(self, trait_item);
583 self.pop_rib(TypeNS);
584 }
585}
586
587#[derive(Debug)]
589struct Module {
590 kind: ModuleKind,
591 def_id: DefId,
592}
593
594impl Module {
595 fn new(kind: ModuleKind, def_id: DefId) -> Self {
596 Self { kind, def_id }
597 }
598}
599
600#[derive(Debug)]
602enum ModuleKind {
603 Mod,
604 Trait,
605 Enum,
606}
607
608#[derive(Debug)]
609enum RibKind {
610 Normal,
612 Module,
614}
615
616#[derive(Debug)]
617struct Rib {
618 kind: RibKind,
619 bindings: FxHashMap<Symbol, fhir::Res>,
620}
621
622impl Rib {
623 fn new(kind: RibKind) -> Self {
624 Self { kind, bindings: Default::default() }
625 }
626}
627
628fn module_children(tcx: TyCtxt<'_>, def_id: DefId) -> &[ModChild] {
629 #[expect(clippy::disallowed_methods, reason = "modules cannot have extern specs")]
630 if let Some(local_id) = def_id.as_local() {
631 tcx.module_children_local(local_id)
632 } else {
633 tcx.module_children(def_id)
634 }
635}
636
637fn visible_module_children(
639 tcx: TyCtxt<'_>,
640 module_id: DefId,
641 curr_mod: DefId,
642) -> impl Iterator<Item = &ModChild> {
643 module_children(tcx, module_id)
644 .iter()
645 .filter(move |child| child.vis.is_accessible_from(curr_mod, tcx))
646}
647
648fn is_prelude_import(tcx: TyCtxt, item: &hir::Item) -> bool {
650 tcx.hir_attrs(item.hir_id())
651 .iter()
652 .any(|attr| attr.path_matches(&[sym::prelude_import]))
653}
654
655trait Segment: std::fmt::Debug {
658 fn record_segment_res(resolver: &mut CrateResolver, segment: &Self, res: fhir::Res);
659 fn ident(&self) -> Ident;
660}
661
662impl Segment for surface::PathSegment {
663 fn record_segment_res(resolver: &mut CrateResolver, segment: &Self, res: fhir::Res) {
664 resolver
665 .output
666 .path_res_map
667 .insert(segment.node_id, fhir::PartialRes::new(res));
668 }
669
670 fn ident(&self) -> Ident {
671 self.ident
672 }
673}
674
675impl Segment for surface::ExprPathSegment {
676 fn record_segment_res(resolver: &mut CrateResolver, segment: &Self, res: fhir::Res) {
677 resolver
678 .output
679 .expr_path_res_map
680 .insert(segment.node_id, fhir::PartialRes::new(res.map_param_id(|p| p)));
681 }
682
683 fn ident(&self) -> Ident {
684 self.ident
685 }
686}
687
688impl Segment for Ident {
689 fn record_segment_res(_resolver: &mut CrateResolver, _segment: &Self, _res: fhir::Res) {}
690
691 fn ident(&self) -> Ident {
692 *self
693 }
694}
695
696impl Segment for hir::PathSegment<'_> {
697 fn record_segment_res(_resolver: &mut CrateResolver, _segment: &Self, _res: fhir::Res) {}
698
699 fn ident(&self) -> Ident {
700 self.ident
701 }
702}
703
704struct ItemResolver<'a, 'genv, 'tcx> {
705 resolver: &'a mut CrateResolver<'genv, 'tcx>,
706 errors: Errors<'genv>,
707}
708
709impl<'a, 'genv, 'tcx> ItemResolver<'a, 'genv, 'tcx> {
710 fn run(
711 resolver: &'a mut CrateResolver<'genv, 'tcx>,
712 f: impl FnOnce(&mut ItemResolver),
713 ) -> Result {
714 let mut item_resolver = ItemResolver::new(resolver);
715 f(&mut item_resolver);
716 item_resolver.errors.into_result()
717 }
718
719 fn new(resolver: &'a mut CrateResolver<'genv, 'tcx>) -> Self {
720 let errors = Errors::new(resolver.genv.sess());
721 Self { resolver, errors }
722 }
723
724 fn resolve_type_path(&mut self, path: &surface::Path) {
725 self.resolve_path_in(path, TypeNS);
726 }
727
728 fn resolve_path_in(&mut self, path: &surface::Path, ns: Namespace) {
729 if let Some(partial_res) = self.resolver.resolve_path_with_ribs(&path.segments, ns) {
730 self.resolver
731 .output
732 .path_res_map
733 .insert(path.node_id, partial_res);
734 } else {
735 self.errors.emit(errors::UnresolvedPath::new(path));
736 }
737 }
738
739 fn resolve_reveal_and_qualifiers(&mut self, node_id: surface::NodeId, attrs: &[surface::Attr]) {
740 for attr in attrs {
741 match attr {
742 surface::Attr::Qualifiers(names) => self.resolve_qualifiers(node_id, names),
743 surface::Attr::Reveal(names) => self.resolve_reveals(node_id, names),
744 _ => {}
745 }
746 }
747 }
748
749 fn resolve_qualifiers(&mut self, node_id: surface::NodeId, qual_names: &[Ident]) {
750 let mut qualifiers = Vec::with_capacity(qual_names.len());
751 for qual in qual_names {
752 if let Some(def_id) = self.resolver.qualifiers.get(&qual.name) {
753 qualifiers.push(*def_id);
754 } else {
755 self.errors.emit(errors::UnknownQualifier::new(qual.span));
756 }
757 }
758 self.resolver
759 .output
760 .qualifier_res_map
761 .insert(node_id, qualifiers);
762 }
763
764 fn resolve_reveals(&mut self, item_id: surface::NodeId, reveal_names: &[Ident]) {
765 let mut reveals = Vec::with_capacity(reveal_names.len());
766 for reveal in reveal_names {
767 if let Some(spec) = self.resolver.func_decls.get(&reveal.name)
768 && let Some(def_id) = spec.def_id()
769 {
770 reveals.push(def_id);
771 } else {
772 self.errors
773 .emit(errors::UnknownRevealDefinition::new(reveal.span));
774 }
775 }
776 self.resolver.output.reveal_res_map.insert(item_id, reveals);
777 }
778}
779
780impl surface::visit::Visitor for ItemResolver<'_, '_, '_> {
781 fn visit_item(&mut self, item: &surface::Item) {
782 self.resolve_reveal_and_qualifiers(item.node_id, &item.attrs);
783 surface::visit::walk_item(self, item);
784 }
785
786 fn visit_trait_item(&mut self, item: &surface::TraitItemFn) {
787 self.resolve_reveal_and_qualifiers(item.node_id, &item.attrs);
788 surface::visit::walk_trait_item(self, item);
789 }
790
791 fn visit_impl_item(&mut self, item: &surface::ImplItemFn) {
792 self.resolve_reveal_and_qualifiers(item.node_id, &item.attrs);
793 surface::visit::walk_impl_item(self, item);
794 }
795
796 fn visit_trait(&mut self, trait_: &surface::Trait) {
797 let mut definitions = DefinitionMap::default();
798 for assoc_reft in &trait_.assoc_refinements {
799 let _ = definitions.define(assoc_reft.name).emit(&self.errors);
800 }
801 surface::visit::walk_trait(self, trait_);
802 }
803
804 fn visit_impl(&mut self, impl_: &surface::Impl) {
805 let mut definitions = DefinitionMap::default();
806 for assoc_reft in &impl_.assoc_refinements {
807 let _ = definitions.define(assoc_reft.name).emit(&self.errors);
808 }
809 surface::visit::walk_impl(self, impl_);
810 }
811
812 fn visit_generic_arg(&mut self, arg: &surface::GenericArg) {
813 if let surface::GenericArgKind::Type(ty) = &arg.kind
814 && let Some(path) = ty.is_potential_const_arg()
815 {
816 let check_ns = |ns| {
821 self.resolver
822 .resolve_ident_with_ribs(path.last().ident, ns)
823 .is_some()
824 };
825
826 if !check_ns(TypeNS) && check_ns(ValueNS) {
827 self.resolve_path_in(path, ValueNS);
828 return;
829 }
830 }
831 surface::visit::walk_generic_arg(self, arg);
832 }
833
834 fn visit_path(&mut self, path: &surface::Path) {
835 self.resolve_type_path(path);
836 surface::visit::walk_path(self, path);
837 }
838}
839
840fn builtin_types_rib() -> Rib {
841 Rib {
842 kind: RibKind::Normal,
843 bindings: PrimTy::ALL
844 .into_iter()
845 .map(|pty| (pty.name(), fhir::Res::PrimTy(pty)))
846 .collect(),
847 }
848}
849
850fn mk_crate_mapping(tcx: TyCtxt) -> UnordMap<Symbol, DefId> {
851 let mut map = UnordMap::default();
852 for cnum in tcx.crates(()) {
853 let name = tcx.crate_name(*cnum);
854 if let Some(extern_crate) = tcx.extern_crate(*cnum)
855 && extern_crate.is_direct()
856 {
857 map.insert(name, cnum.as_def_id());
858 }
859 }
860 map
861}
862
863mod errors {
864 use flux_errors::E0999;
865 use flux_macros::Diagnostic;
866 use flux_syntax::surface;
867 use itertools::Itertools;
868 use rustc_span::{Ident, Span};
869
870 #[derive(Diagnostic)]
871 #[diag(desugar_unresolved_path, code = E0999)]
872 pub struct UnresolvedPath {
873 #[primary_span]
874 pub span: Span,
875 pub path: String,
876 }
877
878 impl UnresolvedPath {
879 pub fn new(path: &surface::Path) -> Self {
880 Self {
881 span: path.span,
882 path: path.segments.iter().map(|segment| segment.ident).join("::"),
883 }
884 }
885 }
886
887 #[derive(Diagnostic)]
888 #[diag(desugar_unknown_qualifier, code = E0999)]
889 pub(super) struct UnknownQualifier {
890 #[primary_span]
891 span: Span,
892 }
893
894 impl UnknownQualifier {
895 pub(super) fn new(span: Span) -> Self {
896 Self { span }
897 }
898 }
899
900 #[derive(Diagnostic)]
901 #[diag(desugar_unknown_reveal_definition, code = E0999)]
902 pub(super) struct UnknownRevealDefinition {
903 #[primary_span]
904 span: Span,
905 }
906
907 impl UnknownRevealDefinition {
908 pub(super) fn new(span: Span) -> Self {
909 Self { span }
910 }
911 }
912
913 #[derive(Diagnostic)]
914 #[diag(desugar_duplicate_definition, code = E0999)]
915 pub(super) struct DuplicateDefinition {
916 #[primary_span]
917 #[label]
918 pub span: Span,
919 #[label(desugar_previous_definition)]
920 pub previous_definition: Span,
921 pub name: Ident,
922 }
923}