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