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