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