1pub(crate) mod refinement_resolver;
2
3use std::collections::hash_map;
4
5use flux_common::{
6 bug,
7 result::{ErrorCollector, ResultExt},
8};
9use flux_errors::{Errors, FluxSession};
10use flux_middle::{
11 ResolverOutput, Specs,
12 def_id::{FluxDefId, FluxLocalDefId, MaybeExternId},
13 fhir,
14 global_env::GlobalEnv,
15};
16use flux_syntax::surface::{self, Ident, visit::Visitor as _};
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, AmbigArg, CRATE_HIR_ID, CRATE_OWNER_ID, ParamName, PrimTy,
23 def::{
24 CtorOf,
25 Namespace::{self, *},
26 PerNS,
27 },
28 def_id::{CRATE_DEF_ID, LocalDefId},
29};
30use rustc_middle::{metadata::ModChild, ty::TyCtxt};
31use rustc_span::{Span, Symbol, def_id::DefId, sym, 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>,
61 prelude: PerNS<Rib>,
62 qualifiers: UnordMap<Symbol, FluxLocalDefId>,
63 func_decls: UnordMap<Symbol, fhir::SpecFuncKind>,
64 sort_decls: UnordMap<Symbol, fhir::SortDecl>,
65 primop_props: UnordMap<Symbol, FluxDefId>,
66 err: Option<ErrorGuaranteed>,
67 current_module: OwnerId,
70}
71
72#[derive(Default)]
74struct DefinitionMap {
75 defined: FxHashMap<Ident, ()>,
76}
77
78impl DefinitionMap {
79 fn define(&mut self, name: Ident) -> std::result::Result<(), errors::DuplicateDefinition> {
80 match self.defined.entry(name) {
81 hash_map::Entry::Occupied(entry) => {
82 Err(errors::DuplicateDefinition {
83 span: name.span,
84 previous_definition: entry.key().span,
85 name,
86 })
87 }
88 hash_map::Entry::Vacant(entry) => {
89 entry.insert(());
90 Ok(())
91 }
92 }
93 }
94}
95
96impl<'genv, 'tcx> CrateResolver<'genv, 'tcx> {
97 pub fn new(genv: GlobalEnv<'genv, 'tcx>, specs: &'genv Specs) -> Self {
98 Self {
99 genv,
100 output: ResolverOutput::default(),
101 specs,
102 ribs: PerNS { type_ns: vec![], value_ns: vec![], macro_ns: vec![] },
103 crates: mk_crate_mapping(genv.tcx()),
104 prelude: PerNS {
105 type_ns: builtin_types_rib(),
106 value_ns: Rib::new(RibKind::Normal),
107 macro_ns: Rib::new(RibKind::Normal),
108 },
109 err: None,
110 qualifiers: Default::default(),
111 func_decls: Default::default(),
112 primop_props: Default::default(),
113 sort_decls: Default::default(),
114 current_module: CRATE_OWNER_ID,
115 }
116 }
117
118 #[allow(clippy::disallowed_methods, reason = "`flux_items_by_parent` is the source of truth")]
119 fn define_flux_global_items(&mut self) {
120 let mut definitions = DefinitionMap::default();
122 for (parent, items) in &self.specs.flux_items_by_parent {
123 for item in items {
124 definitions
127 .define(item.name())
128 .emit(&self.genv)
129 .collect_err(&mut self.err);
130
131 match item {
132 surface::FluxItem::Qualifier(qual) => {
133 let def_id = FluxLocalDefId::new(parent.def_id, qual.name.name);
134 self.qualifiers.insert(qual.name.name, def_id);
135 }
136 surface::FluxItem::FuncDef(defn) => {
137 let parent = parent.def_id.to_def_id();
138 let name = defn.name.name;
139 let def_id = FluxDefId::new(parent, name);
140 let kind = if defn.body.is_some() {
141 fhir::SpecFuncKind::Def(def_id)
142 } else {
143 fhir::SpecFuncKind::Uif(def_id)
144 };
145 self.func_decls.insert(defn.name.name, kind);
146 }
147 surface::FluxItem::PrimOpProp(primop_prop) => {
148 let name = primop_prop.name.name;
149 let parent = parent.def_id.to_def_id();
150 let def_id = FluxDefId::new(parent, name);
151 self.primop_props.insert(name, def_id);
152 }
153 surface::FluxItem::SortDecl(sort_decl) => {
154 self.sort_decls.insert(
155 sort_decl.name.name,
156 fhir::SortDecl { name: sort_decl.name.name, span: sort_decl.name.span },
157 );
158 }
159 }
160 }
161 }
162
163 self.func_decls.extend_unord(
164 flux_middle::THEORY_FUNCS
165 .items()
166 .map(|(_, itf)| (itf.name, fhir::SpecFuncKind::Thy(itf.itf))),
167 );
168 self.func_decls
169 .insert(Symbol::intern("cast"), fhir::SpecFuncKind::Cast);
170 }
171
172 fn define_items(&mut self, item_ids: impl IntoIterator<Item = &'tcx ItemId>) {
173 for item_id in item_ids {
174 let item = self.genv.tcx().hir_item(*item_id);
175 let def_kind = match item.kind {
176 ItemKind::Use(path, kind) => {
177 match kind {
178 hir::UseKind::Single(ident) => {
179 let name = ident.name;
180 if let Some(res) = path.res.value_ns
181 && let Ok(res) = fhir::Res::try_from(res)
182 {
183 self.define_res_in(name, res, ValueNS);
184 }
185 if let Some(res) = path.res.type_ns
186 && let Ok(res) = fhir::Res::try_from(res)
187 {
188 self.define_res_in(name, res, TypeNS);
189 }
190 }
191 hir::UseKind::Glob => {
192 let is_prelude = is_prelude_import(self.genv.tcx(), item);
193 for mod_child in self.glob_imports(path) {
194 if let Ok(res) = fhir::Res::try_from(mod_child.res)
195 && let Some(ns @ (TypeNS | ValueNS)) = res.ns()
196 {
197 let name = mod_child.ident.name;
198 if is_prelude {
199 self.define_in_prelude(name, res, ns);
200 } else {
201 self.define_res_in(name, res, ns);
202 }
203 }
204 }
205 }
206 hir::UseKind::ListStem => {}
207 }
208 continue;
209 }
210 ItemKind::TyAlias(..) => DefKind::TyAlias,
211 ItemKind::Enum(..) => DefKind::Enum,
212 ItemKind::Struct(..) => DefKind::Struct,
213 ItemKind::Trait(..) => DefKind::Trait,
214 ItemKind::Mod(..) => DefKind::Mod,
215 ItemKind::Const(..) => DefKind::Const,
216 ItemKind::ForeignMod { items, .. } => {
217 self.define_foreign_items(items);
218 continue;
219 }
220 _ => continue,
221 };
222 if let Some(ns) = def_kind.ns()
223 && let Some(ident) = item.kind.ident()
224 {
225 self.define_res_in(
226 ident.name,
227 fhir::Res::Def(def_kind, item.owner_id.to_def_id()),
228 ns,
229 );
230 }
231 }
232 }
233
234 fn define_foreign_items(&mut self, items: &[rustc_hir::ForeignItemId]) {
235 for item_id in items {
236 let item = self.genv.tcx().hir_foreign_item(*item_id);
237 match item.kind {
238 rustc_hir::ForeignItemKind::Type => {
239 self.define_res_in(
240 item.ident.name,
241 fhir::Res::Def(DefKind::ForeignTy, item.owner_id.to_def_id()),
242 TypeNS,
243 );
244 }
245 rustc_hir::ForeignItemKind::Fn(..) | rustc_hir::ForeignItemKind::Static(..) => {}
246 }
247 }
248 }
249
250 fn define_res_in(&mut self, name: Symbol, res: fhir::Res, ns: Namespace) {
251 self.ribs[ns].last_mut().unwrap().bindings.insert(name, res);
252 }
253
254 fn define_in_prelude(&mut self, name: Symbol, res: fhir::Res, ns: Namespace) {
255 self.prelude[ns].bindings.insert(name, res);
256 }
257
258 fn push_rib(&mut self, ns: Namespace, kind: RibKind) {
259 self.ribs[ns].push(Rib::new(kind));
260 }
261
262 fn pop_rib(&mut self, ns: Namespace) {
263 self.ribs[ns].pop();
264 }
265
266 fn define_generics(&mut self, def_id: MaybeExternId<OwnerId>) {
267 let generics = self
268 .genv
269 .tcx()
270 .hir_get_generics(def_id.local_id().def_id)
271 .unwrap();
272 for param in generics.params {
273 let def_kind = self.genv.tcx().def_kind(param.def_id);
274 if let ParamName::Plain(name) = param.name
275 && let Some(ns) = def_kind.ns()
276 {
277 debug_assert!(matches!(def_kind, DefKind::TyParam | DefKind::ConstParam));
278 let param_id = self.genv.maybe_extern_id(param.def_id).resolved_id();
279 self.define_res_in(name.name, fhir::Res::Def(def_kind, param_id), ns);
280 }
281 }
282 }
283
284 fn resolve_flux_items(&mut self, parent: OwnerId) {
285 let Some(items) = self.specs.flux_items_by_parent.get(&parent) else { return };
286 for item in items {
287 match item {
288 surface::FluxItem::Qualifier(qual) => {
289 RefinementResolver::resolve_qualifier(self, qual).collect_err(&mut self.err);
290 }
291 surface::FluxItem::FuncDef(defn) => {
292 RefinementResolver::resolve_defn(self, defn).collect_err(&mut self.err);
293 }
294 surface::FluxItem::SortDecl(_) => {}
295 surface::FluxItem::PrimOpProp(primop_prop) => {
296 RefinementResolver::resolve_primop_prop(self, primop_prop)
297 .collect_err(&mut self.err);
298 }
299 }
300 }
301 }
302
303 fn resolve_trait(&mut self, owner_id: MaybeExternId<OwnerId>) -> Result {
304 let trait_ = &self.specs.traits[&owner_id.local_id()];
305
306 let mut definitions = DefinitionMap::default();
307 for assoc_reft in &trait_.assoc_refinements {
308 definitions
309 .define(assoc_reft.name)
310 .emit(&self.genv)
311 .collect_err(&mut self.err);
312 }
313
314 ItemResolver::run(self, owner_id, |item_resolver| {
315 item_resolver.visit_trait(trait_);
316 })?;
317 RefinementResolver::resolve_trait(self, trait_)
318 }
319
320 fn resolve_impl(&mut self, owner_id: MaybeExternId<OwnerId>) -> Result {
321 let impl_ = &self.specs.impls[&owner_id.local_id()];
322
323 let mut definitions = DefinitionMap::default();
324 for assoc_reft in &impl_.assoc_refinements {
325 definitions
326 .define(assoc_reft.name)
327 .emit(&self.genv)
328 .collect_err(&mut self.err);
329 }
330
331 ItemResolver::run(self, owner_id, |item_resolver| {
332 item_resolver.visit_impl(impl_);
333 })?;
334 RefinementResolver::resolve_impl(self, impl_)
335 }
336
337 fn resolve_type_alias(&mut self, owner_id: MaybeExternId<OwnerId>) -> Result {
338 if let Some(ty_alias) = &self.specs.ty_aliases[&owner_id.local_id()] {
339 ItemResolver::run(self, owner_id, |item_resolver| {
340 item_resolver.visit_ty_alias(ty_alias);
341 })?;
342 RefinementResolver::resolve_ty_alias(self, ty_alias)?;
343 }
344 Ok(())
345 }
346
347 fn resolve_struct_def(&mut self, owner_id: MaybeExternId<OwnerId>) -> Result {
348 let struct_def = &self.specs.structs[&owner_id.local_id()];
349 ItemResolver::run(self, owner_id, |item_resolver| {
350 item_resolver.visit_struct_def(struct_def);
351 })?;
352 RefinementResolver::resolve_struct_def(self, struct_def)
353 }
354
355 fn resolve_enum_def(&mut self, owner_id: MaybeExternId<OwnerId>) -> Result {
356 let enum_def = &self.specs.enums[&owner_id.local_id()];
357 ItemResolver::run(self, owner_id, |item_resolver| {
358 item_resolver.visit_enum_def(enum_def);
359 })?;
360 RefinementResolver::resolve_enum_def(self, enum_def)
361 }
362
363 fn resolve_constant(&mut self, owner_id: MaybeExternId<OwnerId>) -> Result {
364 if let Some(constant) = self.specs.constants.get(&owner_id.local_id()) {
365 ItemResolver::run(self, owner_id, |item_resolver| {
366 item_resolver.visit_constant(constant);
367 })?;
368 RefinementResolver::resolve_constant(self, constant)?;
369 }
370 Ok(())
371 }
372
373 fn resolve_fn_sig(&mut self, owner_id: MaybeExternId<OwnerId>) -> Result {
374 let fn_spec = &self.specs.fn_sigs[&owner_id.local_id()];
375
376 if let Some(owner_id) = owner_id.as_local() {
377 self.resolve_qualifiers(owner_id, fn_spec.qual_names.as_ref())?;
378 self.resolve_reveals(owner_id, fn_spec.reveal_names.as_ref())?;
379 }
380 if let Some(fn_sig) = &fn_spec.fn_sig {
381 ItemResolver::run(self, owner_id, |item_resolver| {
382 item_resolver.visit_fn_sig(fn_sig);
383 })?;
384 RefinementResolver::resolve_fn_sig(self, fn_sig)?;
385 }
386 Ok(())
387 }
388
389 fn resolve_qualifiers(
390 &mut self,
391 owner_id: OwnerId,
392 quals: Option<&surface::QualNames>,
393 ) -> Result {
394 let qual_names = quals.map_or(&[][..], |q| &q.names[..]);
395 let mut qualifiers = Vec::with_capacity(qual_names.len());
396 for qual in qual_names {
397 if let Some(def_id) = self.qualifiers.get(&qual.name) {
398 qualifiers.push(*def_id);
399 } else {
400 return Err(self
401 .genv
402 .sess()
403 .emit_err(errors::UnknownQualifier::new(qual.span)));
404 }
405 }
406 self.output.qualifier_res_map.insert(owner_id, qualifiers);
407 Ok(())
408 }
409
410 fn resolve_reveals(
411 &mut self,
412 owner_id: OwnerId,
413 reveals: Option<&surface::RevealNames>,
414 ) -> Result {
415 let reveal_names = reveals.map_or(&[][..], |q| &q.names[..]);
416 let mut reveals = Vec::with_capacity(reveal_names.len());
417 for reveal in reveal_names {
418 if let Some(spec) = self.func_decls.get(&reveal.name)
419 && let Some(def_id) = spec.def_id()
420 {
421 reveals.push(def_id);
422 } else {
423 return Err(self
424 .genv
425 .sess()
426 .emit_err(errors::UnknownRevealDefinition::new(reveal.span)));
427 }
428 }
429 self.output.reveal_res_map.insert(owner_id, reveals);
430 Ok(())
431 }
432
433 fn resolve_path_with_ribs<S: Segment>(
434 &mut self,
435 segments: &[S],
436 ns: Namespace,
437 ) -> Option<fhir::PartialRes> {
438 let mut module: Option<Module> = None;
439 for (segment_idx, segment) in segments.iter().enumerate() {
440 let is_last = segment_idx + 1 == segments.len();
441 let ns = if is_last { ns } else { TypeNS };
442
443 let base_res = if let Some(module) = &module {
444 self.resolve_ident_in_module(module, segment.ident(), ns)?
445 } else {
446 self.resolve_ident_with_ribs(segment.ident(), ns)?
447 };
448
449 S::record_segment_res(self, segment, base_res);
450
451 if is_last {
452 return Some(fhir::PartialRes::new(base_res));
453 }
454
455 match base_res {
456 fhir::Res::Def(DefKind::Mod, module_id) => {
457 module = Some(Module::new(ModuleKind::Mod, module_id));
458 }
459 fhir::Res::Def(DefKind::Trait, module_id) => {
460 module = Some(Module::new(ModuleKind::Trait, module_id));
461 }
462 fhir::Res::Def(DefKind::Enum, module_id) => {
463 module = Some(Module::new(ModuleKind::Enum, module_id));
464 }
465 _ => {
466 return Some(fhir::PartialRes::with_unresolved_segments(
467 base_res,
468 segments.len() - segment_idx - 1,
469 ));
470 }
471 }
472 }
473 None
474 }
475
476 fn resolve_ident_with_ribs(&self, ident: Ident, ns: Namespace) -> Option<fhir::Res> {
477 for rib in self.ribs[ns].iter().rev() {
478 if let Some(res) = rib.bindings.get(&ident.name) {
479 return Some(*res);
480 }
481 if matches!(rib.kind, RibKind::Module) {
482 break;
483 }
484 }
485 if ns == TypeNS
486 && let Some(crate_id) = self.crates.get(&ident.name)
487 {
488 return Some(fhir::Res::Def(DefKind::Mod, *crate_id));
489 }
490
491 if let Some(res) = self.prelude[ns].bindings.get(&ident.name) {
492 return Some(*res);
493 }
494 None
495 }
496
497 fn glob_imports(
498 &mut self,
499 path: &hir::UsePath,
500 ) -> impl Iterator<Item = &'tcx ModChild> + use<'tcx> {
501 let tcx = self.genv.tcx();
505 let curr_mod = self.current_module.to_def_id();
506 self.resolve_path_with_ribs(path.segments, TypeNS)
507 .and_then(|partial_res| partial_res.full_res())
508 .and_then(|res| {
509 if let fhir::Res::Def(DefKind::Mod, module_id) = res {
510 Some(module_id)
511 } else {
512 None
513 }
514 })
515 .into_iter()
516 .flat_map(move |module_id| visible_module_children(tcx, module_id, curr_mod))
517 }
518
519 fn resolve_ident_in_module(
520 &self,
521 module: &Module,
522 ident: Ident,
523 ns: Namespace,
524 ) -> Option<fhir::Res> {
525 let tcx = self.genv.tcx();
526 match module.kind {
527 ModuleKind::Mod => {
528 let module_id = module.def_id;
529 let current_mod = self.current_module.to_def_id();
530 visible_module_children(tcx, module_id, current_mod)
531 .find(|child| {
532 child.res.matches_ns(ns) && tcx.hygienic_eq(ident, child.ident, current_mod)
533 })
534 .and_then(|child| fhir::Res::try_from(child.res).ok())
535 }
536 ModuleKind::Trait => {
537 let trait_id = module.def_id;
538 tcx.associated_items(trait_id)
539 .find_by_ident_and_namespace(tcx, ident, ns, trait_id)
540 .map(|assoc| fhir::Res::Def(assoc.kind.as_def_kind(), assoc.def_id))
541 }
542 ModuleKind::Enum => {
543 tcx.adt_def(module.def_id)
544 .variants()
545 .iter()
546 .find(|data| data.name == ident.name)
547 .and_then(|data| {
548 let (kind, def_id) = match (ns, data.ctor) {
549 (TypeNS, _) => (DefKind::Variant, data.def_id),
550 (ValueNS, Some((ctor_kind, ctor_id))) => {
551 (DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_id)
552 }
553 _ => return None,
554 };
555 Some(fhir::Res::Def(kind, def_id))
556 })
557 }
558 }
559 }
560
561 pub fn into_output(self) -> Result<ResolverOutput> {
562 self.err.into_result()?;
563 Ok(self.output)
564 }
565}
566
567impl<'tcx> hir::intravisit::Visitor<'tcx> for CrateResolver<'_, 'tcx> {
568 type NestedFilter = rustc_middle::hir::nested_filter::All;
569
570 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
571 self.genv.tcx()
572 }
573
574 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _s: Span, hir_id: hir::HirId) {
575 let old_mod = self.current_module;
576 self.current_module = hir_id.expect_owner();
577 self.push_rib(TypeNS, RibKind::Module);
578 self.push_rib(ValueNS, RibKind::Module);
579
580 self.define_items(module.item_ids);
581
582 if hir_id == CRATE_HIR_ID {
584 self.define_flux_global_items();
585 }
586
587 self.resolve_flux_items(hir_id.expect_owner());
589
590 hir::intravisit::walk_mod(self, module);
591
592 self.pop_rib(ValueNS);
593 self.pop_rib(TypeNS);
594 self.current_module = old_mod;
595 }
596
597 fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
598 self.push_rib(TypeNS, RibKind::Normal);
599 self.push_rib(ValueNS, RibKind::Normal);
600
601 let item_ids = block.stmts.iter().filter_map(|stmt| {
602 if let hir::StmtKind::Item(item_id) = &stmt.kind { Some(item_id) } else { None }
603 });
604 self.define_items(item_ids);
605 self.resolve_flux_items(self.genv.tcx().hir_get_parent_item(block.hir_id));
606
607 hir::intravisit::walk_block(self, block);
608
609 self.pop_rib(ValueNS);
610 self.pop_rib(TypeNS);
611 }
612
613 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
614 if self.genv.is_dummy(item.owner_id.def_id) {
615 return;
616 }
617 let def_id = self
618 .genv
619 .maybe_extern_id(item.owner_id.def_id)
620 .map(|def_id| OwnerId { def_id });
621
622 self.push_rib(TypeNS, RibKind::Normal);
623 self.push_rib(ValueNS, RibKind::Normal);
624
625 match item.kind {
626 ItemKind::Trait(..) => {
627 self.define_generics(def_id);
628 self.define_res_in(
629 kw::SelfUpper,
630 fhir::Res::SelfTyParam { trait_: def_id.resolved_id() },
631 TypeNS,
632 );
633 self.resolve_trait(def_id).collect_err(&mut self.err);
634 }
635 ItemKind::Impl(impl_) => {
636 self.define_generics(def_id);
637 self.define_res_in(
638 kw::SelfUpper,
639 fhir::Res::SelfTyAlias {
640 alias_to: def_id.resolved_id(),
641 is_trait_impl: impl_.of_trait.is_some(),
642 },
643 TypeNS,
644 );
645 self.resolve_impl(def_id).collect_err(&mut self.err);
646 }
647 ItemKind::TyAlias(..) => {
648 self.define_generics(def_id);
649 self.resolve_type_alias(def_id).collect_err(&mut self.err);
650 }
651 ItemKind::Enum(_enum_def, ..) => {
652 self.define_generics(def_id);
653 self.define_res_in(
654 kw::SelfUpper,
655 fhir::Res::SelfTyAlias { alias_to: def_id.resolved_id(), is_trait_impl: false },
656 TypeNS,
657 );
658 self.resolve_enum_def(def_id).collect_err(&mut self.err);
659 }
660 ItemKind::Struct(..) => {
661 self.define_generics(def_id);
662 self.define_res_in(
663 kw::SelfUpper,
664 fhir::Res::SelfTyAlias { alias_to: def_id.resolved_id(), is_trait_impl: false },
665 TypeNS,
666 );
667 self.resolve_struct_def(def_id).collect_err(&mut self.err);
668 }
669 ItemKind::Fn { .. } => {
670 self.define_generics(def_id);
671 self.resolve_fn_sig(def_id).collect_err(&mut self.err);
672 }
673 ItemKind::Const(..) => {
674 self.resolve_constant(def_id).collect_err(&mut self.err);
675 }
676 _ => {}
677 }
678
679 hir::intravisit::walk_item(self, item);
680
681 self.pop_rib(ValueNS);
682 self.pop_rib(TypeNS);
683 }
684
685 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
686 let def_id = self
687 .genv
688 .maybe_extern_id(impl_item.owner_id.def_id)
689 .map(|def_id| OwnerId { def_id });
690
691 self.push_rib(TypeNS, RibKind::Normal);
692 self.define_generics(def_id);
693 if let hir::ImplItemKind::Fn(..) = impl_item.kind {
694 self.resolve_fn_sig(def_id).collect_err(&mut self.err);
695 }
696 hir::intravisit::walk_impl_item(self, impl_item);
697 self.pop_rib(TypeNS);
698 }
699
700 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
701 let def_id = self
702 .genv
703 .maybe_extern_id(trait_item.owner_id.def_id)
704 .map(|def_id| OwnerId { def_id });
705
706 self.push_rib(TypeNS, RibKind::Normal);
707 self.define_generics(def_id);
708 if let hir::TraitItemKind::Fn(..) = trait_item.kind {
709 self.resolve_fn_sig(def_id).collect_err(&mut self.err);
710 }
711 hir::intravisit::walk_trait_item(self, trait_item);
712 self.pop_rib(TypeNS);
713 }
714}
715
716#[derive(Debug)]
718struct Module {
719 kind: ModuleKind,
720 def_id: DefId,
721}
722
723impl Module {
724 fn new(kind: ModuleKind, def_id: DefId) -> Self {
725 Self { kind, def_id }
726 }
727}
728
729#[derive(Debug)]
731enum ModuleKind {
732 Mod,
733 Trait,
734 Enum,
735}
736
737#[derive(Debug)]
738enum RibKind {
739 Normal,
741 Module,
743}
744
745#[derive(Debug)]
746struct Rib {
747 kind: RibKind,
748 bindings: FxHashMap<Symbol, fhir::Res>,
749}
750
751impl Rib {
752 fn new(kind: RibKind) -> Self {
753 Self { kind, bindings: Default::default() }
754 }
755}
756
757fn module_children(tcx: TyCtxt<'_>, def_id: DefId) -> &[ModChild] {
758 #[expect(clippy::disallowed_methods, reason = "modules cannot have extern specs")]
759 if let Some(local_id) = def_id.as_local() {
760 tcx.module_children_local(local_id)
761 } else {
762 tcx.module_children(def_id)
763 }
764}
765
766fn visible_module_children(
768 tcx: TyCtxt<'_>,
769 module_id: DefId,
770 curr_mod: DefId,
771) -> impl Iterator<Item = &ModChild> {
772 module_children(tcx, module_id)
773 .iter()
774 .filter(move |child| child.vis.is_accessible_from(curr_mod, tcx))
775}
776
777fn is_prelude_import(tcx: TyCtxt, item: &hir::Item) -> bool {
779 tcx.hir_attrs(item.hir_id())
780 .iter()
781 .any(|attr| attr.path_matches(&[sym::prelude_import]))
782}
783
784trait Segment: std::fmt::Debug {
787 fn record_segment_res(resolver: &mut CrateResolver, segment: &Self, res: fhir::Res);
788 fn ident(&self) -> Ident;
789}
790
791impl Segment for surface::PathSegment {
792 fn record_segment_res(resolver: &mut CrateResolver, segment: &Self, res: fhir::Res) {
793 resolver
794 .output
795 .path_res_map
796 .insert(segment.node_id, fhir::PartialRes::new(res));
797 }
798
799 fn ident(&self) -> Ident {
800 self.ident
801 }
802}
803
804impl Segment for surface::ExprPathSegment {
805 fn record_segment_res(_resolver: &mut CrateResolver, _segment: &Self, _res: fhir::Res) {}
806
807 fn ident(&self) -> Ident {
808 self.ident
809 }
810}
811
812impl Segment for Ident {
813 fn record_segment_res(_resolver: &mut CrateResolver, _segment: &Self, _res: fhir::Res) {}
814
815 fn ident(&self) -> Ident {
816 *self
817 }
818}
819
820impl Segment for hir::PathSegment<'_> {
821 fn record_segment_res(_resolver: &mut CrateResolver, _segment: &Self, _res: fhir::Res) {}
822
823 fn ident(&self) -> Ident {
824 self.ident
825 }
826}
827
828struct ItemResolver<'a, 'genv, 'tcx> {
829 resolver: &'a mut CrateResolver<'genv, 'tcx>,
830 opaque: Option<LocalDefId>, errors: Errors<'genv>,
832}
833
834impl<'a, 'genv, 'tcx> ItemResolver<'a, 'genv, 'tcx> {
835 fn run(
836 resolver: &'a mut CrateResolver<'genv, 'tcx>,
837 owner_id: MaybeExternId<OwnerId>,
838 f: impl FnOnce(&mut ItemResolver),
839 ) -> Result {
840 let mut item_resolver = ItemResolver::new(resolver, owner_id)?;
841 f(&mut item_resolver);
842 item_resolver.errors.into_result()
843 }
844
845 fn new(
846 resolver: &'a mut CrateResolver<'genv, 'tcx>,
847 owner_id: MaybeExternId<OwnerId>,
848 ) -> Result<Self> {
849 let tcx = resolver.genv.tcx();
850 let sess = resolver.genv.sess();
851 let opaque = match tcx.hir_owner_node(owner_id.local_id()) {
852 hir::OwnerNode::Item(item) => OpaqueTypeCollector::collect_item(sess, item)?,
853 hir::OwnerNode::ImplItem(impl_item) => {
854 OpaqueTypeCollector::collect_impl_item(sess, impl_item)?
855 }
856 hir::OwnerNode::TraitItem(trait_item) => {
857 OpaqueTypeCollector::collect_trait_item(sess, trait_item)?
858 }
859 node @ (hir::OwnerNode::ForeignItem(_)
860 | hir::OwnerNode::Crate(_)
861 | hir::OwnerNode::Synthetic) => {
862 bug!("unsupported node {node:?}")
863 }
864 };
865
866 let errors = Errors::new(resolver.genv.sess());
867 Ok(Self { resolver, opaque, errors })
868 }
869
870 fn resolve_opaque_impl(&mut self, node_id: surface::NodeId, span: Span) {
871 if let Some(def_id) = self.opaque {
872 self.resolver
873 .output
874 .impl_trait_res_map
875 .insert(node_id, def_id);
876 } else {
877 self.errors
878 .emit(errors::UnresolvedPath { span, path: "opaque type".into() });
879 }
880 }
881
882 fn resolve_type_path(&mut self, path: &surface::Path) {
883 self.resolve_path_in(path, TypeNS);
884 }
885
886 fn resolve_path_in(&mut self, path: &surface::Path, ns: Namespace) {
887 if let Some(partial_res) = self.resolver.resolve_path_with_ribs(&path.segments, ns) {
888 self.resolver
889 .output
890 .path_res_map
891 .insert(path.node_id, partial_res);
892 } else {
893 self.errors.emit(errors::UnresolvedPath::new(path));
894 }
895 }
896}
897
898impl surface::visit::Visitor for ItemResolver<'_, '_, '_> {
899 fn visit_async(&mut self, asyncness: &surface::Async) {
900 if let surface::Async::Yes { node_id, span } = asyncness {
901 self.resolve_opaque_impl(*node_id, *span);
902 }
903 }
904
905 fn visit_ty(&mut self, ty: &surface::Ty) {
906 if let surface::TyKind::ImplTrait(node_id, _) = &ty.kind {
907 self.resolve_opaque_impl(*node_id, ty.span);
908 }
909 surface::visit::walk_ty(self, ty);
910 }
911
912 fn visit_generic_arg(&mut self, arg: &surface::GenericArg) {
913 if let surface::GenericArgKind::Type(ty) = &arg.kind
914 && let Some(path) = ty.is_potential_const_arg()
915 {
916 let check_ns = |ns| {
921 self.resolver
922 .resolve_ident_with_ribs(path.last().ident, ns)
923 .is_some()
924 };
925
926 if !check_ns(TypeNS) && check_ns(ValueNS) {
927 self.resolve_path_in(path, ValueNS);
928 return;
929 }
930 }
931 surface::visit::walk_generic_arg(self, arg);
932 }
933
934 fn visit_path(&mut self, path: &surface::Path) {
935 self.resolve_type_path(path);
936 surface::visit::walk_path(self, path);
937 }
938}
939
940struct OpaqueTypeCollector<'sess> {
941 opaque: Option<LocalDefId>, errors: Errors<'sess>,
943}
944
945impl<'sess> OpaqueTypeCollector<'sess> {
946 fn new(sess: &'sess FluxSession) -> Self {
947 Self { opaque: None, errors: Errors::new(sess) }
948 }
949
950 fn collect_item(sess: &'sess FluxSession, item: &hir::Item) -> Result<Option<LocalDefId>> {
951 let mut collector = Self::new(sess);
952 hir::intravisit::walk_item(&mut collector, item);
953 collector.into_result()
954 }
955
956 fn collect_impl_item(
957 sess: &'sess FluxSession,
958 impl_item: &hir::ImplItem,
959 ) -> Result<Option<LocalDefId>> {
960 let mut collector = Self::new(sess);
961 hir::intravisit::walk_impl_item(&mut collector, impl_item);
962 collector.into_result()
963 }
964
965 fn collect_trait_item(
966 sess: &'sess FluxSession,
967 trait_item: &hir::TraitItem,
968 ) -> Result<Option<LocalDefId>> {
969 let mut collector = Self::new(sess);
970 hir::intravisit::walk_trait_item(&mut collector, trait_item);
971 collector.into_result()
972 }
973
974 fn into_result(self) -> Result<Option<LocalDefId>> {
975 self.errors.into_result()?;
976 Ok(self.opaque)
977 }
978}
979
980impl<'tcx> hir::intravisit::Visitor<'tcx> for OpaqueTypeCollector<'_> {
981 fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
982 if let hir::TyKind::OpaqueDef(opaque_ty, ..) = ty.kind {
983 if self.opaque.is_some() {
984 self.errors.emit(errors::UnsupportedSignature::new(
985 ty.span,
986 "duplicate opaque types in signature",
987 ));
988 } else {
989 self.opaque = Some(opaque_ty.def_id);
990 }
991 }
992 hir::intravisit::walk_ty(self, ty);
993 }
994}
995
996fn builtin_types_rib() -> Rib {
997 Rib {
998 kind: RibKind::Normal,
999 bindings: PrimTy::ALL
1000 .into_iter()
1001 .map(|pty| (pty.name(), fhir::Res::PrimTy(pty)))
1002 .collect(),
1003 }
1004}
1005
1006fn mk_crate_mapping(tcx: TyCtxt) -> UnordMap<Symbol, DefId> {
1007 let mut map = UnordMap::default();
1008 map.insert(kw::Crate, CRATE_DEF_ID.to_def_id());
1009 for cnum in tcx.crates(()) {
1010 let name = tcx.crate_name(*cnum);
1011 if let Some(extern_crate) = tcx.extern_crate(*cnum)
1012 && extern_crate.is_direct()
1013 {
1014 map.insert(name, cnum.as_def_id());
1015 }
1016 }
1017 map
1018}
1019
1020mod errors {
1021 use flux_errors::E0999;
1022 use flux_macros::Diagnostic;
1023 use flux_syntax::surface;
1024 use itertools::Itertools;
1025 use rustc_span::{Ident, Span};
1026
1027 #[derive(Diagnostic)]
1028 #[diag(desugar_unsupported_signature, code = E0999)]
1029 #[note]
1030 pub(super) struct UnsupportedSignature<'a> {
1031 #[primary_span]
1032 span: Span,
1033 note: &'a str,
1034 }
1035
1036 impl<'a> UnsupportedSignature<'a> {
1037 pub(super) fn new(span: Span, note: &'a str) -> Self {
1038 Self { span, note }
1039 }
1040 }
1041
1042 #[derive(Diagnostic)]
1043 #[diag(desugar_unresolved_path, code = E0999)]
1044 pub struct UnresolvedPath {
1045 #[primary_span]
1046 pub span: Span,
1047 pub path: String,
1048 }
1049
1050 impl UnresolvedPath {
1051 pub fn new(path: &surface::Path) -> Self {
1052 Self {
1053 span: path.span,
1054 path: path.segments.iter().map(|segment| segment.ident).join("::"),
1055 }
1056 }
1057 }
1058
1059 #[derive(Diagnostic)]
1060 #[diag(desugar_unknown_qualifier, code = E0999)]
1061 pub(super) struct UnknownQualifier {
1062 #[primary_span]
1063 span: Span,
1064 }
1065
1066 impl UnknownQualifier {
1067 pub(super) fn new(span: Span) -> Self {
1068 Self { span }
1069 }
1070 }
1071
1072 #[derive(Diagnostic)]
1073 #[diag(desugar_unknown_reveal_definition, code = E0999)]
1074 pub(super) struct UnknownRevealDefinition {
1075 #[primary_span]
1076 span: Span,
1077 }
1078
1079 impl UnknownRevealDefinition {
1080 pub(super) fn new(span: Span) -> Self {
1081 Self { span }
1082 }
1083 }
1084
1085 #[derive(Diagnostic)]
1086 #[diag(desugar_duplicate_definition, code = E0999)]
1087 pub(super) struct DuplicateDefinition {
1088 #[primary_span]
1089 #[label]
1090 pub span: Span,
1091 #[label(desugar_previous_definition)]
1092 pub previous_definition: Span,
1093 pub name: Ident,
1094 }
1095}