1pub(crate) mod refinement_resolver;
2
3use std::collections::hash_map;
4
5use flux_common::{
6 bug,
7 result::{ErrorCollector, ErrorEmitter, ResultExt},
8};
9use flux_errors::Errors;
10use flux_middle::{
11 FluxItemDecl, ResolverOutput, Specs,
12 def_id::{FluxDefId, FluxLocalDefId, MaybeExternId},
13 fhir,
14 fhir::{
15 Namespace::{self, *},
16 PerNS,
17 },
18 global_env::GlobalEnv,
19};
20use flux_syntax::{
21 surface::{self, Ident, visit::Visitor as _},
22 symbols::sym,
23};
24use hir::{ItemId, ItemKind, OwnerId, def::DefKind};
25use itertools::Itertools;
26use rustc_data_structures::unord::{ExtendUnord, UnordMap};
27use rustc_errors::ErrorGuaranteed;
28use rustc_hir::{
29 self as hir, CRATE_OWNER_ID, ParamName, PrimTy, def::CtorOf, def_id::CRATE_DEF_ID,
30};
31use rustc_middle::{middle::resolve::ModChild, ty::TyCtxt};
32use rustc_span::{Span, Symbol, def_id::DefId, symbol::kw};
33
34use self::refinement_resolver::{ImplicitParamCollector, RefinementResolver};
35
36type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
37
38enum ResolveError {
41 NotFound,
42 Ambiguous(Ambiguity),
47 OuterGeneric(Span),
49}
50
51impl ResolveError {
52 #[track_caller]
55 fn emit<'a, D: rustc_errors::Diagnostic<'a>>(
56 self,
57 emitter: &'a impl ErrorEmitter,
58 not_found: impl FnOnce() -> D,
59 ) -> ErrorGuaranteed {
60 match self {
61 Self::NotFound => emitter.emit(not_found()),
62 Self::Ambiguous(ambiguity) => emitter.emit(errors::AmbiguousName::new(ambiguity)),
63 Self::OuterGeneric(span) => emitter.emit(errors::OuterGeneric { span }),
64 }
65 }
66}
67
68#[derive(Clone, Copy, Debug)]
81struct Ambiguity {
82 span: Span,
84 name: Symbol,
86 first: Span,
88 second: Span,
91}
92
93pub(crate) fn resolve_crate(genv: GlobalEnv) -> ResolverOutput {
94 match try_resolve_crate(genv) {
95 Ok(output) => output,
96 Err(err) => genv.sess().abort(err),
97 }
98}
99
100fn try_resolve_crate(genv: GlobalEnv) -> Result<ResolverOutput> {
101 let specs = genv.collect_specs();
102 let mut resolver = CrateResolver::new(genv, specs);
103
104 genv.tcx().hir_walk_toplevel_module(&mut resolver);
105
106 resolver.into_output()
107}
108
109pub(crate) struct CrateResolver<'genv, 'tcx> {
110 genv: GlobalEnv<'genv, 'tcx>,
111 specs: &'genv Specs,
112 output: ResolverOutput,
113 ribs: PerNS<Vec<Rib>>,
114 crates: UnordMap<Symbol, DefId>,
116 prelude: PerNS<Rib>,
119 qualifiers: UnordMap<Symbol, FluxLocalDefId>,
120 primop_props: UnordMap<Symbol, FluxDefId>,
121 err: Option<ErrorGuaranteed>,
122 current_module: OwnerId,
125}
126
127#[derive(Default)]
129struct DefinitionMap {
130 defined: UnordMap<Ident, ()>,
131}
132
133impl DefinitionMap {
134 fn define(&mut self, name: Ident) -> std::result::Result<(), errors::DuplicateDefinition> {
135 match self.defined.entry(name) {
136 hash_map::Entry::Occupied(entry) => {
137 Err(errors::DuplicateDefinition {
138 span: name.span,
139 previous_definition: entry.key().span,
140 name: name.name,
141 })
142 }
143 hash_map::Entry::Vacant(entry) => {
144 entry.insert(());
145 Ok(())
146 }
147 }
148 }
149}
150
151impl<'genv, 'tcx> CrateResolver<'genv, 'tcx> {
152 pub fn new(genv: GlobalEnv<'genv, 'tcx>, specs: &'genv Specs) -> Self {
153 Self {
154 genv,
155 output: ResolverOutput::default(),
156 specs,
157 ribs: PerNS { type_ns: vec![], value_ns: vec![], macro_ns: vec![], flux_fn_ns: vec![] },
158 crates: mk_crate_mapping(genv.tcx()),
159 prelude: PerNS {
160 type_ns: builtin_types_rib(),
161 value_ns: Rib::new(RibKind::Misc),
162 macro_ns: Rib::new(RibKind::Misc),
163 flux_fn_ns: theory_funcs_rib(),
164 },
165 err: None,
166 qualifiers: Default::default(),
167 primop_props: Default::default(),
168 current_module: CRATE_OWNER_ID,
169 }
170 }
171
172 #[allow(
176 clippy::disallowed_methods,
177 reason = "`flux_items_by_scope` is the source of truth for `FluxDefId`"
178 )]
179 fn define_flux_global_items(&mut self) {
180 let mut definitions = DefinitionMap::default();
181 for decls in self.specs.flux_items_by_scope.values() {
182 for FluxItemDecl { declarer, item } in decls {
183 match item {
185 surface::FluxItem::Qualifier(qual) => {
186 let ident = qual.name;
187 if definitions
188 .define(ident)
189 .emit(&self.genv)
190 .collect_err(&mut self.err)
191 .is_some()
192 {
193 let def_id = FluxLocalDefId::new(declarer.def_id, ident.name);
194 self.qualifiers.insert(ident.name, def_id);
195 }
196 }
197 surface::FluxItem::PrimOpProp(primop) => {
198 let ident = primop.name;
199 if definitions
200 .define(ident)
201 .emit(&self.genv)
202 .collect_err(&mut self.err)
203 .is_some()
204 {
205 let def_id = FluxDefId::new(declarer.to_def_id(), ident.name);
206 self.primop_props.insert(ident.name, def_id);
207 }
208 }
209 surface::FluxItem::Axiom(axiom) => {
210 let _ = definitions
211 .define(axiom.name)
212 .emit(&self.genv)
213 .collect_err(&mut self.err);
214 }
215 surface::FluxItem::Use(_)
216 | surface::FluxItem::FuncDef(_)
217 | surface::FluxItem::SortDecl(_) => {}
218 };
219 }
220 }
221 }
222
223 #[allow(
225 clippy::disallowed_methods,
226 reason = "`flux_items_by_scope` is the source of truth for `FluxDefId`"
227 )]
228 fn define_flux_items(&mut self, scope: hir::HirId) {
229 let Some(decls) = self.specs.flux_items_by_scope.get(&scope) else { return };
230 for FluxItemDecl { declarer, item } in decls {
231 match item {
232 surface::FluxItem::Qualifier(_)
233 | surface::FluxItem::PrimOpProp(_)
234 | surface::FluxItem::Axiom(_) => {
235 }
237 surface::FluxItem::FuncDef(defn) => {
238 let def_id = FluxDefId::new(declarer.to_def_id(), defn.name.name);
239 let kind = fhir::SpecFuncKind::Def(def_id);
240 self.define_res_in(
241 fhir::Res::GlobalFunc(kind),
242 ReftNS,
243 BindingSource::Explicit(defn.name),
244 );
245 }
246 surface::FluxItem::SortDecl(sort_decl) => {
247 let def_id = FluxDefId::new(declarer.to_def_id(), sort_decl.name.name);
248 self.define_res_in(
249 fhir::Res::UserSort(def_id),
250 TypeNS,
251 BindingSource::Explicit(sort_decl.name),
252 );
253 }
254 surface::FluxItem::Use(use_tree) => {
255 for (ident, res, ns) in self.resolve_flux_use_tree(use_tree) {
257 self.define_res_in(res, ns, BindingSource::Explicit(ident));
258 }
259 }
260 }
261 }
262 }
263
264 fn define_items(&mut self, item_ids: impl IntoIterator<Item = &'tcx ItemId>) {
265 for item_id in item_ids {
266 let item = self.genv.tcx().hir_item(*item_id);
267 let def_kind = match item.kind {
268 ItemKind::Use(use_tree) => {
269 let is_prelude = is_prelude_import(self.genv.tcx(), item);
270 self.define_use_tree(&use_tree, &mut vec![], is_prelude, item.span);
271 continue;
272 }
273 ItemKind::ForeignMod { items, .. } => {
274 self.define_foreign_items(items);
275 continue;
276 }
277 ItemKind::TyAlias(..)
278 | ItemKind::Enum(..)
279 | ItemKind::Struct(..)
280 | ItemKind::Union(..)
281 | ItemKind::Trait { .. }
282 | ItemKind::Mod(..)
283 | ItemKind::Const(..) => self.genv.def_kind(item.owner_id),
284 _ => continue,
285 };
286 if let Some(ns) = def_kind.ns().map(Namespace::from)
287 && let Some(ident) = item.kind.ident()
288 {
289 self.define_res_in(
290 fhir::Res::Def(def_kind, item.owner_id.to_def_id()),
291 ns,
292 BindingSource::Explicit(ident),
293 );
294 }
295 }
296 }
297
298 fn define_foreign_items(&mut self, items: &[rustc_hir::ForeignItemId]) {
299 for item_id in items {
300 let item = self.genv.tcx().hir_foreign_item(*item_id);
301 match item.kind {
302 rustc_hir::ForeignItemKind::Type => {
303 self.define_res_in(
304 fhir::Res::Def(DefKind::ForeignTy, item.owner_id.to_def_id()),
305 TypeNS,
306 BindingSource::Explicit(item.ident),
307 );
308 }
309 rustc_hir::ForeignItemKind::Fn(..) | rustc_hir::ForeignItemKind::Static(..) => {}
310 }
311 }
312 }
313
314 fn define_res_in(
316 &mut self,
317 res: fhir::Res<surface::NodeId>,
318 ns: Namespace,
319 source: BindingSource,
320 ) {
321 let ident = source.ident();
322 if ident.name == kw::Underscore {
323 return;
324 }
325 let entry = self.ribs[ns]
326 .last_mut()
327 .unwrap()
328 .bindings
329 .entry(ident.name)
330 .or_default();
331
332 if let Some(prev) = entry.define(source, res) {
333 if let fhir::Res::Param(..) = prev.res {
334 self.emit(errors::DuplicateParam {
335 span: ident.span,
336 name: ident.name,
337 first_use: prev.span,
338 });
339 } else {
340 self.emit(errors::DuplicateDefinition {
341 span: ident.span,
342 previous_definition: prev.span,
343 name: ident.name,
344 });
345 }
346 }
347 }
348
349 fn define_in_prelude(&mut self, ident: Ident, res: fhir::Res<surface::NodeId>, ns: Namespace) {
353 self.prelude[ns]
354 .bindings
355 .insert(ident.name, NameResolution::from_explicit(Binding { span: ident.span, res }));
356 }
357
358 fn push_rib(&mut self, ns: Namespace, kind: RibKind) {
359 self.ribs[ns].push(Rib::new(kind));
360 }
361
362 fn pop_rib(&mut self, ns: Namespace) {
363 self.ribs[ns].pop();
364 }
365
366 fn define_generics(&mut self, def_id: MaybeExternId<OwnerId>) {
367 let generics = self
368 .genv
369 .tcx()
370 .hir_get_generics(def_id.local_id().def_id)
371 .unwrap();
372 for param in generics.params {
373 let def_kind = self.genv.tcx().def_kind(param.def_id);
374 if let ParamName::Plain(name) = param.name
375 && let Some(ns) = def_kind.ns().map(Namespace::from)
376 {
377 debug_assert!(matches!(def_kind, DefKind::TyParam | DefKind::ConstParam));
378 let param_id = self.genv.maybe_extern_id(param.def_id).resolved_id();
379 self.define_res_in(
380 fhir::Res::Def(def_kind, param_id),
381 ns,
382 BindingSource::Explicit(name),
383 );
384 }
385 }
386 }
387
388 fn resolve_flux_items(&mut self, scope: hir::HirId) {
389 let Some(decls) = self.specs.flux_items_by_scope.get(&scope) else { return };
390 for ns in [TypeNS, ValueNS, ReftNS] {
391 self.push_rib(ns, RibKind::Item);
392 }
393 for FluxItemDecl { item, .. } in decls {
394 self.resolve_flux_item(item, MaybeExternId::Local(scope.owner))
395 .collect_err(&mut self.err);
396 }
397 for ns in [TypeNS, ValueNS, ReftNS] {
398 self.pop_rib(ns);
399 }
400 }
401
402 fn resolve_flux_item(
403 &mut self,
404 item: &surface::FluxItem,
405 parent: MaybeExternId<OwnerId>,
406 ) -> Result {
407 if let surface::FluxItem::Use(_) = item {
408 return Ok(());
410 }
411 ItemResolver::run(self, parent, |vis| vis.visit_flux_item(item))?;
412 self.push_rib(TypeNS, RibKind::Misc);
414 for (idx, ident) in item.sort_vars().iter().enumerate() {
415 self.define_res_in(fhir::Res::SortParam(idx), TypeNS, BindingSource::Explicit(*ident));
416 }
417 let result =
418 RefinementResolver::run(self, Default::default(), |vis| vis.visit_flux_item(item));
419 self.pop_rib(TypeNS);
420 result
421 }
422
423 fn resolve_item(&mut self, item: &surface::Item, item_id: MaybeExternId<OwnerId>) -> Result {
424 ItemResolver::run(self, item_id, |vis| vis.visit_item(item))?;
425 let params = ImplicitParamCollector::run(self, |vis| vis.visit_item(item))?;
426 RefinementResolver::run(self, params, |vis| vis.visit_item(item))
427 }
428
429 fn resolve_trait_item(
430 &mut self,
431 item: &surface::TraitItemFn,
432 item_id: MaybeExternId<OwnerId>,
433 ) -> Result {
434 ItemResolver::run(self, item_id, |vis| vis.visit_trait_item(item))?;
435 let params = ImplicitParamCollector::run(self, |vis| vis.visit_trait_item(item))?;
436 RefinementResolver::run(self, params, |vis| vis.visit_trait_item(item))
437 }
438
439 fn resolve_impl_item(
440 &mut self,
441 item: &surface::ImplItemFn,
442 item_id: MaybeExternId<OwnerId>,
443 ) -> Result {
444 ItemResolver::run(self, item_id, |vis| vis.visit_impl_item(item))?;
445 let params = ImplicitParamCollector::run(self, |vis| vis.visit_impl_item(item))?;
446 RefinementResolver::run(self, params, |vis| vis.visit_impl_item(item))
447 }
448
449 fn resolve_path_with_ribs<S: Segment>(
450 &mut self,
451 segments: &[S],
452 ns: Namespace,
453 ) -> std::result::Result<fhir::PartialRes<surface::NodeId>, ResolveError> {
454 let result = self.resolve_path_with_ribs_inner(segments, ns);
455 let fallback = match &result {
456 Ok(res) => matches!(res.full_res(), Some(fhir::Res::Def(DefKind::Mod, _))),
457 Err(ResolveError::NotFound) => true,
458 Err(ResolveError::Ambiguous(_) | ResolveError::OuterGeneric(_)) => false,
459 };
460 if fallback
463 && (ns == TypeNS || (ns == ValueNS && segments.len() > 1))
464 && let Some(first) = segments.first()
465 {
466 let name = first.ident().name;
467 let prim = PrimTy::from_name(name).map(fhir::Res::PrimTy).or_else(|| {
468 fhir::PrimSort::ALL
469 .into_iter()
470 .find(|sort| sort.name() == name)
471 .map(fhir::Res::PrimSort)
472 });
473 if let Some(res) = prim {
474 S::record_segment_res(self, first, res);
475 return Ok(fhir::PartialRes::with_unresolved_segments(res, segments.len() - 1));
476 }
477 }
478 result
479 }
480
481 fn resolve_path_with_ribs_inner<S: Segment>(
483 &mut self,
484 segments: &[S],
485 ns: Namespace,
486 ) -> std::result::Result<fhir::PartialRes<surface::NodeId>, ResolveError> {
487 let mut module: Option<Module> = None;
488 for (segment_idx, segment) in segments.iter().enumerate() {
489 let is_last = segment_idx + 1 == segments.len();
490 let ns = if is_last { ns } else { TypeNS };
491
492 let base_res = if let Some(module) = module {
493 self.resolve_ident_in_module(module, segment.ident(), ns)?
494 } else {
495 self.resolve_ident_with_ribs(segment.ident(), ns)?
496 };
497
498 S::record_segment_res(self, segment, base_res);
499
500 if is_last {
501 return Ok(fhir::PartialRes::new(base_res));
502 }
503
504 match base_res {
505 fhir::Res::Def(DefKind::Mod, module_id) => {
506 module = Some(Module::new(ModuleKind::Mod, module_id));
507 }
508 fhir::Res::Def(DefKind::Trait, module_id) => {
509 module = Some(Module::new(ModuleKind::Trait, module_id));
510 }
511 fhir::Res::Def(DefKind::Enum, module_id) => {
512 module = Some(Module::new(ModuleKind::Enum, module_id));
513 }
514 _ => {
515 return Ok(fhir::PartialRes::with_unresolved_segments(
516 base_res,
517 segments.len() - segment_idx - 1,
518 ));
519 }
520 }
521 }
522 Err(ResolveError::NotFound)
523 }
524
525 fn resolve_flux_use_tree(
526 &mut self,
527 use_tree: &surface::UseTree,
528 ) -> Vec<(Ident, fhir::Res<surface::NodeId>, Namespace)> {
529 self.resolve_flux_use_tree_rec(use_tree, None, &mut vec![])
530 }
531
532 fn resolve_flux_use_tree_rec(
533 &mut self,
534 use_tree: &surface::UseTree,
535 mut resolved_module_id: Option<DefId>,
536 resolved_prefix: &mut Vec<Ident>,
537 ) -> Vec<(Ident, fhir::Res<surface::NodeId>, Namespace)> {
538 let Some((last, all_but_last)) = use_tree.prefix.segments.split_last() else {
539 bug!("path must have at least one segment")
540 };
541 let module_segments = match &use_tree.kind {
542 surface::UseTreeKind::Simple => all_but_last,
543 surface::UseTreeKind::Nested(_) => &use_tree.prefix.segments[..],
544 };
545
546 for segment in module_segments {
547 let ident = segment.ident();
548 let res = if let Some(module_id) = resolved_module_id {
549 let module = Module::new(ModuleKind::Mod, module_id);
550 self.resolve_ident_in_module(module, ident, TypeNS)
551 } else {
552 self.resolve_ident_with_ribs(ident, TypeNS)
553 };
554 let res = match res {
555 Ok(res) => res,
556 Err(err) => {
557 self.emit_resolve_err(err, || {
558 errors::UnresolvedImport::new(ident, resolved_module_id, resolved_prefix)
559 });
560 return vec![];
561 }
562 };
563 if let fhir::Res::Def(DefKind::Mod, def_id) = res {
564 resolved_module_id = Some(def_id);
565 } else {
566 self.emit_not_a_module(ident, resolved_prefix);
567 return vec![];
568 }
569 resolved_prefix.push(ident);
570 }
571
572 match &use_tree.kind {
573 surface::UseTreeKind::Simple => {
574 let mut resolutions = vec![];
575 let mut error = None;
579 for ns in [TypeNS, ValueNS, ReftNS] {
580 let res = if let Some(module_id) = resolved_module_id {
581 let module = Module::new(ModuleKind::Mod, module_id);
582 self.resolve_ident_in_module(module, last.ident(), ns)
583 } else {
584 self.resolve_ident_with_ribs(last.ident(), ns)
585 };
586 match res {
587 Ok(res) => resolutions.push((last.ident(), res, ns)),
588 Err(ResolveError::NotFound) => {}
589 Err(err) => error = error.or(Some(err)),
590 }
591 }
592 if resolutions.is_empty() {
593 error = error.or(Some(ResolveError::NotFound));
594 }
595 if let Some(err) = error {
596 self.emit_resolve_err(err, || {
597 errors::UnresolvedImport::new(
598 last.ident,
599 resolved_module_id,
600 resolved_prefix,
601 )
602 });
603 }
604 resolutions
605 }
606 surface::UseTreeKind::Nested(items) => {
607 let mut resolutions = vec![];
608 for item in items {
609 let len = resolved_prefix.len();
610 resolutions.extend(self.resolve_flux_use_tree_rec(
611 item,
612 resolved_module_id,
613 resolved_prefix,
614 ));
615 resolved_prefix.truncate(len);
616 }
617 resolutions
618 }
619 }
620 }
621
622 fn resolve_ident_with_ribs(
623 &self,
624 ident: Ident,
625 ns: Namespace,
626 ) -> std::result::Result<fhir::Res<surface::NodeId>, ResolveError> {
627 let mut ribs = self.ribs[ns].iter().rev();
628 let mut crossed_item = false;
629 while let Some(rib) = ribs.next() {
630 if let Some(name_res) = rib.bindings.get(&ident.name)
633 && let Some(res) = name_res.resolve(ident)
634 {
635 let res = res.map_err(ResolveError::Ambiguous)?;
637 if crossed_item
638 && matches!(
639 res,
640 fhir::Res::Def(DefKind::TyParam | DefKind::ConstParam, _)
641 | fhir::Res::SelfTyParam { .. }
642 | fhir::Res::SelfTyAlias { .. }
643 )
644 {
645 return Err(ResolveError::OuterGeneric(ident.span));
646 }
647 return Ok(res);
648 }
649 match rib.kind {
650 RibKind::Module => break,
652 RibKind::Item => crossed_item = true,
653 RibKind::Variant => {
658 ribs.take_while_ref(|rib| !matches!(rib.kind, RibKind::Module))
659 .for_each(drop);
660 }
661 _ => {}
662 }
663 }
664 if ns == TypeNS {
665 if let Some(crate_id) = self.crates.get(&ident.name) {
666 return Ok(fhir::Res::Def(DefKind::Mod, *crate_id));
667 }
668 if ident.name == kw::Crate {
670 return Ok(fhir::Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()));
671 }
672 if ident.name == kw::SelfLower {
673 return Ok(fhir::Res::Def(DefKind::Mod, self.current_module.to_def_id()));
674 }
675 if ident.name == kw::Super
676 && let Some(parent) = self.genv.tcx().opt_local_parent(self.current_module.def_id)
677 {
678 return Ok(fhir::Res::Def(DefKind::Mod, parent.to_def_id()));
679 }
680 }
681
682 if let Some(name_res) = self.prelude[ns].bindings.get(&ident.name)
683 && let Some(res) = name_res.resolve(ident)
684 {
685 return res.map_err(ResolveError::Ambiguous);
686 }
687 Err(ResolveError::NotFound)
688 }
689
690 fn define_use_tree(
693 &mut self,
694 use_tree: &hir::UseTree<'tcx>,
695 prefix: &mut Vec<hir::PathSegment<'tcx>>,
696 is_prelude: bool,
697 glob_span: Span,
698 ) {
699 let path = use_tree.prefix;
700 match use_tree.kind {
701 hir::UseKind::Single(mut ident) => {
702 if ident.name == kw::SelfLower
706 && let Some(last) = prefix.last()
707 {
708 ident = Ident::new(last.ident.name, ident.span);
709 }
710 if let Some(res) = path.res.value_ns
711 && let Ok(res) = fhir::Res::try_from(res)
712 {
713 self.define_res_in(res, ValueNS, BindingSource::Explicit(ident));
714 }
715 if let Some(res) = path.res.type_ns
716 && let Ok(res) = fhir::Res::try_from(res)
717 {
718 self.define_res_in(res, TypeNS, BindingSource::Explicit(ident));
719 }
720 }
721 hir::UseKind::Glob => {
722 let len = prefix.len();
723 prefix.extend_from_slice(path.segments);
724 for mod_child in self.glob_imports(prefix) {
725 if let Ok(res) = fhir::Res::try_from(mod_child.res)
726 && let Some(ns @ (TypeNS | ValueNS)) = res.ns()
727 {
728 if is_prelude {
729 self.define_in_prelude(mod_child.ident, res, ns);
730 } else {
731 let source = BindingSource::Glob { ident: mod_child.ident, glob_span };
732 self.define_res_in(res, ns, source);
733 }
734 }
735 }
736 prefix.truncate(len);
737 }
738 hir::UseKind::Nested { items } => {
739 let len = prefix.len();
740 prefix.extend_from_slice(path.segments);
741 for (nested, _, _) in items {
742 self.define_use_tree(nested, prefix, is_prelude, glob_span);
743 }
744 prefix.truncate(len);
745 }
746 }
747 }
748
749 fn glob_imports(
750 &mut self,
751 segments: &[hir::PathSegment<'tcx>],
752 ) -> impl Iterator<Item = &'tcx ModChild> + use<'tcx> {
753 let tcx = self.genv.tcx();
757 let curr_mod = self.current_module.to_def_id();
758 self.resolve_path_with_ribs_inner(segments, TypeNS)
759 .ok()
760 .and_then(|partial_res| partial_res.full_res())
761 .and_then(|res| {
762 if let fhir::Res::Def(DefKind::Mod, module_id) = res {
763 Some(module_id)
764 } else {
765 None
766 }
767 })
768 .into_iter()
769 .flat_map(move |module_id| visible_module_children(tcx, module_id, curr_mod))
770 }
771
772 fn resolve_ident_in_module(
773 &self,
774 module: Module,
775 ident: Ident,
776 ns: Namespace,
777 ) -> std::result::Result<fhir::Res<surface::NodeId>, ResolveError> {
778 let tcx = self.genv.tcx();
779 let res = match module.kind {
780 ModuleKind::Mod => {
781 let module_id = module.def_id;
782 let current_mod = self.current_module.to_def_id();
783
784 let mut resolution: NameResolution = ns
793 .to_rustc()
794 .into_iter()
795 .flat_map(|rustc_ns| {
796 visible_module_children(tcx, module_id, current_mod).filter(move |child| {
797 child.res.matches_ns(rustc_ns)
798 && tcx.hygienic_eq(ident, child.ident, current_mod)
799 })
800 })
801 .filter_map(|child| {
802 Some(Binding {
803 span: child.ident.span,
804 res: fhir::Res::try_from(child.res).ok()?,
805 })
806 })
807 .collect();
808 if resolution.is_empty() {
809 if let Some(ambiguity) = self.ambiguous_module_child(module_id, ident, ns) {
811 return Err(ResolveError::Ambiguous(ambiguity));
812 }
813 resolution = self
814 .genv
815 .flux_module_children(module_id)
816 .iter()
817 .filter(|child| {
818 child.res.ns() == Some(ns) && child.ident.name == ident.name
819 })
820 .map(|child| {
821 Binding {
822 span: child.ident.span,
823 res: child.res.map_param_id(|id| match id {}),
824 }
825 })
826 .collect();
827 }
828 resolution.resolve(ident)
829 }
830 ModuleKind::Trait => {
831 ns.to_rustc()
833 .and_then(|rustc_ns| {
834 let trait_id = module.def_id;
835 tcx.associated_items(trait_id)
836 .find_by_ident_and_namespace(tcx, ident, rustc_ns, trait_id)
837 .map(|assoc| fhir::Res::Def(assoc.kind.as_def_kind(), assoc.def_id))
838 })
839 .map(Ok)
840 }
841 ModuleKind::Enum => {
842 tcx.adt_def(module.def_id)
843 .variants()
844 .iter()
845 .find(|data| data.name == ident.name)
846 .and_then(|data| {
847 let (kind, def_id) = match (ns, data.ctor) {
848 (TypeNS, _) => (DefKind::Variant, data.def_id),
849 (ValueNS, Some((ctor_kind, ctor_id))) => {
850 (DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_id)
851 }
852 _ => return None,
853 };
854 Some(fhir::Res::Def(kind, def_id))
855 })
856 .map(Ok)
857 }
858 };
859 match res {
860 Some(res) => res.map_err(ResolveError::Ambiguous),
861 None => Err(ResolveError::NotFound),
862 }
863 }
864
865 #[expect(clippy::disallowed_methods, reason = "modules cannot have extern specs")]
876 fn ambiguous_module_child(
877 &self,
878 module_id: DefId,
879 ident: Ident,
880 ns: Namespace,
881 ) -> Option<Ambiguity> {
882 let tcx = self.genv.tcx();
883 let module_id = module_id.as_local()?;
884 let rustc_ns = ns.to_rustc()?;
885 let current_mod = self.current_module.to_def_id();
886 let child = tcx
887 .resolutions(())
888 .ambig_module_children
889 .get(&module_id)?
890 .iter()
891 .find(|child| {
892 child.main.res.matches_ns(rustc_ns)
893 && tcx.hygienic_eq(ident, child.main.ident, current_mod)
894 && child.main.vis.is_accessible_from(current_mod, tcx)
895 })?;
896 Some(Ambiguity {
897 span: ident.span,
898 name: ident.name,
899 first: self.glob_span(&child.main),
900 second: self.glob_span(&child.second),
901 })
902 }
903
904 fn glob_span(&self, child: &ModChild) -> Span {
907 let def_id = child
908 .reexport_chain
909 .first()
910 .and_then(|reexport| reexport.id())
911 .unwrap_or_else(|| child.res.def_id());
912 self.genv.tcx().def_span(def_id)
913 }
914
915 pub fn into_output(self) -> Result<ResolverOutput> {
916 self.err.into_result()?;
917 Ok(self.output)
918 }
919
920 #[track_caller]
921 fn emit_resolve_err<D: rustc_errors::Diagnostic<'genv>>(
922 &mut self,
923 err: ResolveError,
924 not_found: impl FnOnce() -> D,
925 ) {
926 self.err.collect(err.emit(self.genv.sess(), not_found));
927 }
928
929 fn emit_not_a_module(&mut self, ident: Ident, resolved_prefix: &[Ident]) {
930 let name = Segment::format_iter(resolved_prefix.iter().chain(&[ident]));
931 self.emit(errors::UnresolvedImport {
932 span: ident.span,
933 name,
934 reason: format!("`{ident}` is not a module"),
935 });
936 }
937
938 #[track_caller]
939 fn emit(&mut self, err: impl rustc_errors::Diagnostic<'genv>) {
940 self.err.collect(self.genv.sess().emit_err(err));
941 }
942}
943
944impl<'tcx> hir::intravisit::Visitor<'tcx> for CrateResolver<'_, 'tcx> {
945 type NestedFilter = rustc_middle::hir::nested_filter::All;
946
947 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
948 self.genv.tcx()
949 }
950
951 fn visit_mod(
952 &mut self,
953 module: &'tcx hir::Mod<'tcx>,
954 _s: Span,
955 mod_id: hir::def_id::LocalModId,
956 ) {
957 let owner_id = OwnerId { def_id: mod_id.to_local_def_id() };
958 let old_mod = self.current_module;
959 self.current_module = owner_id;
960 self.push_rib(TypeNS, RibKind::Module);
961 self.push_rib(ValueNS, RibKind::Module);
962 self.push_rib(ReftNS, RibKind::Module);
963
964 self.define_items(module.item_ids);
965
966 if mod_id.is_top_level_module() {
968 self.define_flux_global_items();
969 }
970 let scope = hir::HirId::make_owner(owner_id.def_id);
972 self.define_flux_items(scope);
973
974 self.resolve_flux_items(scope);
975 hir::intravisit::walk_mod(self, module);
976
977 self.pop_rib(ReftNS);
978 self.pop_rib(ValueNS);
979 self.pop_rib(TypeNS);
980 self.current_module = old_mod;
981 }
982
983 fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
984 self.push_rib(TypeNS, RibKind::Misc);
985 self.push_rib(ValueNS, RibKind::Misc);
986 self.push_rib(ReftNS, RibKind::Misc);
987
988 let item_ids = block.stmts.iter().filter_map(|stmt| {
989 if let hir::StmtKind::Item(item_id) = &stmt.kind { Some(item_id) } else { None }
990 });
991 self.define_items(item_ids);
992 self.define_flux_items(block.hir_id);
993
994 self.resolve_flux_items(block.hir_id);
995 hir::intravisit::walk_block(self, block);
996
997 self.pop_rib(ReftNS);
998 self.pop_rib(ValueNS);
999 self.pop_rib(TypeNS);
1000 }
1001
1002 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
1003 if self.genv.is_dummy(item.owner_id.def_id) {
1004 return;
1005 }
1006 let def_id = self
1007 .genv
1008 .maybe_extern_id(item.owner_id.def_id)
1009 .map(|def_id| OwnerId { def_id });
1010
1011 self.push_rib(TypeNS, RibKind::Item);
1012 self.push_rib(ValueNS, RibKind::Item);
1013
1014 match item.kind {
1015 ItemKind::Trait { .. } => {
1016 self.define_generics(def_id);
1017 self.define_res_in(
1018 fhir::Res::SelfTyParam { trait_: def_id.resolved_id() },
1019 TypeNS,
1020 BindingSource::Explicit(Ident::with_dummy_span(kw::SelfUpper)),
1021 );
1022 }
1023 ItemKind::Impl(hir::Impl { of_trait, .. }) => {
1024 self.define_generics(def_id);
1025 self.define_res_in(
1026 fhir::Res::SelfTyAlias {
1027 alias_to: def_id.resolved_id(),
1028 is_trait_impl: of_trait.is_some(),
1029 },
1030 TypeNS,
1031 BindingSource::Explicit(Ident::with_dummy_span(kw::SelfUpper)),
1032 );
1033 }
1034 ItemKind::TyAlias(..) => {
1035 self.define_generics(def_id);
1036 }
1037 ItemKind::Enum(..) => {
1038 self.define_generics(def_id);
1039 self.define_res_in(
1040 fhir::Res::SelfTyAlias { alias_to: def_id.resolved_id(), is_trait_impl: false },
1041 TypeNS,
1042 BindingSource::Explicit(Ident::with_dummy_span(kw::SelfUpper)),
1043 );
1044 }
1045 ItemKind::Struct(..) => {
1046 self.define_generics(def_id);
1047 self.define_res_in(
1048 fhir::Res::SelfTyAlias { alias_to: def_id.resolved_id(), is_trait_impl: false },
1049 TypeNS,
1050 BindingSource::Explicit(Ident::with_dummy_span(kw::SelfUpper)),
1051 );
1052 }
1053 ItemKind::Fn { .. } => {
1054 self.define_generics(def_id);
1055 }
1056 _ => {}
1057 }
1058 if let Some(item) = self.specs.get_item(def_id.local_id()) {
1059 self.resolve_item(item, def_id).collect_err(&mut self.err);
1060 }
1061
1062 hir::intravisit::walk_item(self, item);
1063
1064 self.pop_rib(ValueNS);
1065 self.pop_rib(TypeNS);
1066 }
1067
1068 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
1069 let def_id = self
1070 .genv
1071 .maybe_extern_id(impl_item.owner_id.def_id)
1072 .map(|def_id| OwnerId { def_id });
1073
1074 self.push_rib(TypeNS, RibKind::Misc);
1077 self.push_rib(ValueNS, RibKind::Misc);
1078 if let Some(item) = self.specs.get_impl_item(def_id.local_id()) {
1079 self.define_generics(def_id);
1080 self.resolve_impl_item(item, def_id)
1081 .collect_err(&mut self.err);
1082 }
1083 hir::intravisit::walk_impl_item(self, impl_item);
1084 self.pop_rib(ValueNS);
1085 self.pop_rib(TypeNS);
1086 }
1087
1088 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
1089 let def_id = self
1090 .genv
1091 .maybe_extern_id(trait_item.owner_id.def_id)
1092 .map(|def_id| OwnerId { def_id });
1093
1094 self.push_rib(TypeNS, RibKind::Misc);
1097 self.push_rib(ValueNS, RibKind::Misc);
1098 if let Some(item) = self.specs.get_trait_item(def_id.local_id()) {
1099 self.define_generics(def_id);
1100 self.resolve_trait_item(item, def_id)
1101 .collect_err(&mut self.err);
1102 }
1103 hir::intravisit::walk_trait_item(self, trait_item);
1104 self.pop_rib(ValueNS);
1105 self.pop_rib(TypeNS);
1106 }
1107}
1108
1109#[derive(Clone, Copy, Debug)]
1111struct Module {
1112 kind: ModuleKind,
1113 def_id: DefId,
1114}
1115
1116impl Module {
1117 fn new(kind: ModuleKind, def_id: DefId) -> Self {
1118 Self { kind, def_id }
1119 }
1120}
1121
1122#[derive(Clone, Copy, Debug)]
1124enum ModuleKind {
1125 Mod,
1126 Trait,
1127 Enum,
1128}
1129
1130#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1131pub(crate) enum RibKind {
1132 Misc,
1134 Module,
1136 Item,
1138 Variant,
1141}
1142
1143#[derive(Clone, Copy, Debug)]
1147struct Binding {
1148 span: Span,
1152 res: fhir::Res<surface::NodeId>,
1153}
1154
1155#[derive(Clone, Copy, Debug)]
1159enum BindingSource {
1160 Explicit(Ident),
1162 Glob { ident: Ident, glob_span: Span },
1165}
1166
1167impl BindingSource {
1168 fn ident(self) -> Ident {
1169 match self {
1170 BindingSource::Explicit(ident) | BindingSource::Glob { ident, .. } => ident,
1171 }
1172 }
1173
1174 fn span(self) -> Span {
1176 match self {
1177 BindingSource::Explicit(ident) => ident.span,
1178 BindingSource::Glob { glob_span, .. } => glob_span,
1179 }
1180 }
1181}
1182
1183#[derive(Clone, Copy, Debug)]
1185enum GlobBinding {
1186 Single(Binding),
1187 Ambiguous(Span, Span),
1192}
1193
1194#[derive(Clone, Copy, Debug, Default)]
1197struct NameResolution {
1198 non_glob: Option<Binding>,
1199 glob: Option<GlobBinding>,
1200}
1201
1202impl NameResolution {
1203 fn from_explicit(binding: Binding) -> Self {
1204 Self { non_glob: Some(binding), glob: None }
1205 }
1206
1207 fn is_empty(&self) -> bool {
1208 self.non_glob.is_none() && self.glob.is_none()
1209 }
1210
1211 fn define(
1213 &mut self,
1214 source: BindingSource,
1215 res: fhir::Res<surface::NodeId>,
1216 ) -> Option<Binding> {
1217 let binding = Binding { span: source.span(), res };
1218 match source {
1219 BindingSource::Explicit(_) => {
1220 if let Some(prev) = self.non_glob {
1221 Some(prev)
1222 } else {
1223 self.non_glob = Some(binding);
1224 None
1225 }
1226 }
1227 BindingSource::Glob { .. } => {
1228 self.add_glob(binding);
1229 None
1230 }
1231 }
1232 }
1233
1234 fn add_glob(&mut self, binding: Binding) {
1238 self.glob = Some(match self.glob {
1239 None => GlobBinding::Single(binding),
1240 Some(GlobBinding::Single(prev)) => {
1241 if prev.res == binding.res {
1242 GlobBinding::Single(prev)
1243 } else {
1244 GlobBinding::Ambiguous(prev.span, binding.span)
1245 }
1246 }
1247 Some(ambiguous @ GlobBinding::Ambiguous(..)) => ambiguous,
1248 });
1249 }
1250
1251 fn resolve(
1254 &self,
1255 ident: Ident,
1256 ) -> Option<std::result::Result<fhir::Res<surface::NodeId>, Ambiguity>> {
1257 if let Some(binding) = self.non_glob {
1258 return Some(Ok(binding.res));
1259 }
1260 match self.glob? {
1261 GlobBinding::Single(binding) => Some(Ok(binding.res)),
1262 GlobBinding::Ambiguous(first, second) => {
1263 Some(Err(Ambiguity { span: ident.span, name: ident.name, first, second }))
1264 }
1265 }
1266 }
1267}
1268
1269impl FromIterator<Binding> for NameResolution {
1270 fn from_iter<T: IntoIterator<Item = Binding>>(iter: T) -> Self {
1273 let mut resolution = Self::default();
1274 for binding in iter {
1275 resolution.add_glob(binding);
1276 }
1277 resolution
1278 }
1279}
1280
1281#[derive(Debug)]
1282struct Rib {
1283 kind: RibKind,
1284 bindings: UnordMap<Symbol, NameResolution>,
1285}
1286
1287impl Rib {
1288 fn new(kind: RibKind) -> Self {
1289 Self { kind, bindings: Default::default() }
1290 }
1291}
1292
1293fn module_children(tcx: TyCtxt<'_>, def_id: DefId) -> &[ModChild] {
1294 #[expect(clippy::disallowed_methods, reason = "modules cannot have extern specs")]
1295 if let Some(local_id) = def_id.as_local() {
1296 tcx.module_children_local(local_id)
1297 } else {
1298 tcx.module_children(def_id)
1299 }
1300}
1301
1302fn visible_module_children(
1304 tcx: TyCtxt<'_>,
1305 module_id: DefId,
1306 curr_mod: DefId,
1307) -> impl Iterator<Item = &ModChild> {
1308 module_children(tcx, module_id)
1309 .iter()
1310 .filter(move |child| child.vis.is_accessible_from(curr_mod, tcx))
1311}
1312
1313fn is_prelude_import(tcx: TyCtxt, item: &hir::Item) -> bool {
1315 tcx.hir_attrs(item.hir_id()).iter().any(|attr| {
1316 matches!(
1317 attr,
1318 rustc_attr_ir::Attribute::Parsed(rustc_attr_ir::AttributeKind::PreludeImport)
1319 )
1320 })
1321}
1322
1323pub(crate) trait Segment: std::fmt::Debug {
1326 fn record_segment_res(
1327 resolver: &mut CrateResolver,
1328 segment: &Self,
1329 res: fhir::Res<surface::NodeId>,
1330 );
1331 fn ident(&self) -> Ident;
1332
1333 fn format_iter<'a>(segments: impl IntoIterator<Item = &'a Self>) -> String
1334 where
1335 Self: Sized + 'a,
1336 {
1337 segments.into_iter().map(|s| s.ident()).join("::")
1338 }
1339}
1340
1341impl Segment for surface::PathSegment {
1342 fn record_segment_res(
1343 resolver: &mut CrateResolver,
1344 segment: &Self,
1345 res: fhir::Res<surface::NodeId>,
1346 ) {
1347 resolver
1348 .output
1349 .path_res_map
1350 .insert(segment.node_id, fhir::PartialRes::new(res));
1351 }
1352
1353 fn ident(&self) -> Ident {
1354 self.ident
1355 }
1356}
1357
1358impl Segment for surface::ExprPathSegment {
1359 fn record_segment_res(
1360 resolver: &mut CrateResolver,
1361 segment: &Self,
1362 res: fhir::Res<surface::NodeId>,
1363 ) {
1364 resolver
1365 .output
1366 .path_res_map
1367 .insert(segment.node_id, fhir::PartialRes::new(res));
1368 }
1369
1370 fn ident(&self) -> Ident {
1371 self.ident
1372 }
1373}
1374
1375impl Segment for Ident {
1376 fn record_segment_res(
1377 _resolver: &mut CrateResolver,
1378 _segment: &Self,
1379 _res: fhir::Res<surface::NodeId>,
1380 ) {
1381 }
1382
1383 fn ident(&self) -> Ident {
1384 *self
1385 }
1386}
1387
1388impl Segment for hir::PathSegment<'_> {
1389 fn record_segment_res(
1390 _resolver: &mut CrateResolver,
1391 _segment: &Self,
1392 _res: fhir::Res<surface::NodeId>,
1393 ) {
1394 }
1395
1396 fn ident(&self) -> Ident {
1397 self.ident
1398 }
1399}
1400
1401struct ItemResolver<'a, 'genv, 'tcx> {
1402 resolver: &'a mut CrateResolver<'genv, 'tcx>,
1403 errors: Errors<'genv>,
1404 item_id: MaybeExternId<OwnerId>,
1405}
1406
1407impl<'a, 'genv, 'tcx> ItemResolver<'a, 'genv, 'tcx> {
1408 fn run(
1409 resolver: &'a mut CrateResolver<'genv, 'tcx>,
1410 item_id: MaybeExternId<OwnerId>,
1411 f: impl FnOnce(&mut ItemResolver),
1412 ) -> Result {
1413 let mut item_resolver = ItemResolver::new(resolver, item_id);
1414 f(&mut item_resolver);
1415 item_resolver.errors.into_result()
1416 }
1417
1418 fn new(resolver: &'a mut CrateResolver<'genv, 'tcx>, item_id: MaybeExternId<OwnerId>) -> Self {
1419 let errors = Errors::new(resolver.genv.sess());
1420 Self { resolver, errors, item_id }
1421 }
1422
1423 fn resolve_path_in(&mut self, ns: Namespace, path: &surface::Path) {
1424 match self.resolver.resolve_path_with_ribs(&path.segments, ns) {
1425 Ok(partial_res) => {
1426 self.resolver
1427 .output
1428 .path_res_map
1429 .insert(path.node_id, partial_res);
1430 }
1431 Err(err) => {
1432 err.emit(&self.errors, || {
1433 errors::UnresolvedName::new(path.span, &path.segments, ns.descr())
1434 });
1435 }
1436 }
1437 }
1438
1439 fn resolve_attrs(&mut self, node_id: surface::NodeId, attrs: &[surface::Attr]) {
1440 for attr in attrs {
1441 match attr {
1442 surface::Attr::Qualifiers(names) => self.resolve_qualifiers(node_id, names),
1443 surface::Attr::Reveal(names) => {
1444 let reveals = self.resolve_func_defs(names);
1445 self.resolver.output.reveal_res_map.insert(node_id, reveals);
1446 }
1447 surface::Attr::Hide(names) => {
1448 let hides = self.resolve_func_defs(names);
1449 self.resolver.output.hide_res_map.insert(node_id, hides);
1450 }
1451 surface::Attr::AssumeParametric(names) => {
1452 self.resolve_parametric_params(node_id, names);
1453 }
1454 _ => {}
1455 }
1456 }
1457 }
1458
1459 fn resolve_parametric_params(&mut self, node_id: surface::NodeId, names: &[Ident]) {
1460 let tcx = self.resolver.genv.tcx();
1461 let generics = tcx.generics_of(self.item_id.resolved_id());
1462 let param_map: UnordMap<Symbol, DefId> = (0..generics.count())
1463 .map(|i| generics.param_at(i, tcx))
1464 .map(|p| (p.name, p.def_id))
1465 .collect();
1466 let mut params = Vec::with_capacity(names.len());
1467 for name in names {
1468 if let Some(&def_id) = param_map.get(&name.name) {
1469 params.push(def_id);
1470 } else {
1471 self.errors
1472 .emit(errors::UnknownParametricParam::new(name.span));
1473 }
1474 }
1475 self.resolver
1476 .output
1477 .parametric_param_res_map
1478 .insert(node_id, params);
1479 }
1480
1481 fn resolve_qualifiers(&mut self, node_id: surface::NodeId, qual_names: &[Ident]) {
1482 let mut qualifiers = Vec::with_capacity(qual_names.len());
1483 for qual in qual_names {
1484 if let Some(def_id) = self.resolver.qualifiers.get(&qual.name) {
1485 qualifiers.push(*def_id);
1486 } else {
1487 self.errors.emit(errors::UnknownQualifier::new(qual.span));
1488 }
1489 }
1490 self.resolver
1491 .output
1492 .qualifier_res_map
1493 .insert(node_id, qualifiers);
1494 }
1495
1496 fn resolve_func_defs(&mut self, names: &[Ident]) -> Vec<(FluxDefId, Span)> {
1498 let mut def_ids = Vec::with_capacity(names.len());
1499 for name in names {
1500 match self.resolver.resolve_ident_with_ribs(*name, ReftNS) {
1501 Ok(fhir::Res::GlobalFunc(kind)) => {
1502 if let Some(def_id) = kind.def_id() {
1503 def_ids.push((def_id, name.span));
1504 } else {
1505 self.errors
1506 .emit(errors::UnknownFuncDefinition::new(name.span));
1507 }
1508 }
1509 Ok(_) => {
1510 self.errors
1511 .emit(errors::UnknownFuncDefinition::new(name.span));
1512 }
1513 Err(err) => {
1514 err.emit(&self.errors, || errors::UnknownFuncDefinition::new(name.span));
1515 }
1516 }
1517 }
1518 def_ids
1519 }
1520}
1521
1522impl surface::visit::Visitor<'_> for ItemResolver<'_, '_, '_> {
1523 fn visit_item(&mut self, item: &surface::Item) {
1524 self.resolve_attrs(item.node_id, &item.attrs);
1525 surface::visit::walk_item(self, item);
1526 }
1527
1528 fn visit_trait_item(&mut self, item: &surface::TraitItemFn) {
1529 self.resolve_attrs(item.node_id, &item.attrs);
1530 surface::visit::walk_trait_item(self, item);
1531 }
1532
1533 fn visit_impl_item(&mut self, item: &surface::ImplItemFn) {
1534 self.resolve_attrs(item.node_id, &item.attrs);
1535 surface::visit::walk_impl_item(self, item);
1536 }
1537
1538 fn visit_trait(&mut self, trait_: &surface::Trait) {
1539 let mut definitions = DefinitionMap::default();
1540 for assoc_reft in &trait_.assoc_refinements {
1541 let _ = definitions.define(assoc_reft.name).emit(&self.errors);
1542 }
1543 surface::visit::walk_trait(self, trait_);
1544 }
1545
1546 fn visit_impl(&mut self, impl_: &surface::Impl) {
1547 let mut definitions = DefinitionMap::default();
1548 for assoc_reft in &impl_.assoc_refinements {
1549 let _ = definitions.define(assoc_reft.name).emit(&self.errors);
1550 }
1551 surface::visit::walk_impl(self, impl_);
1552 }
1553
1554 fn visit_generic_arg(&mut self, arg: &surface::GenericArg) {
1555 if let surface::GenericArgKind::Type(ty) = &arg.kind
1556 && let Some(path) = ty.is_potential_const_arg()
1557 {
1558 let check_ns = |ns| {
1566 !matches!(
1567 self.resolver.resolve_ident_with_ribs(path.last().ident, ns),
1568 Err(ResolveError::NotFound)
1569 )
1570 };
1571
1572 if !check_ns(TypeNS) && check_ns(ValueNS) {
1573 self.resolve_path_in(ValueNS, path);
1574 return;
1575 }
1576 }
1577 surface::visit::walk_generic_arg(self, arg);
1578 }
1579
1580 fn visit_const_arg(&mut self, const_arg: &surface::ConstArg) {
1581 if let surface::ConstArgKind::Path(path) = &const_arg.kind {
1582 self.resolve_path_in(ValueNS, path);
1583 surface::visit::walk_path(self, path);
1584 }
1585 }
1586
1587 fn visit_path(&mut self, path: &surface::Path) {
1588 self.resolve_path_in(TypeNS, path);
1589 surface::visit::walk_path(self, path);
1590 }
1591}
1592
1593fn builtin_types_rib() -> Rib {
1598 use flux_middle::fhir::PrimSort;
1599 let sorts = PrimSort::ALL.into_iter().map(|prim| {
1600 let ident = Ident::with_dummy_span(prim.name());
1601 (
1602 ident.name,
1603 NameResolution::from_explicit(Binding {
1604 span: ident.span,
1605 res: fhir::Res::PrimSort(prim),
1606 }),
1607 )
1608 });
1609 let types = PrimTy::ALL.into_iter().map(|pty| {
1610 let ident = Ident::with_dummy_span(pty.name());
1611 (
1612 ident.name,
1613 NameResolution::from_explicit(Binding {
1614 span: ident.span,
1615 res: fhir::Res::PrimTy(pty),
1616 }),
1617 )
1618 });
1619
1620 let bindings = sorts.chain(types).collect();
1624 Rib { kind: RibKind::Misc, bindings }
1625}
1626
1627fn theory_funcs_rib() -> Rib {
1629 let mut rib = Rib::new(RibKind::Misc);
1630 rib.bindings
1631 .extend_unord(flux_middle::THEORY_FUNCS.items().map(|(_, itf)| {
1632 let ident = Ident::with_dummy_span(itf.name);
1633 let res = fhir::Res::GlobalFunc(fhir::SpecFuncKind::Thy(itf.itf));
1634 (ident.name, NameResolution::from_explicit(Binding { span: ident.span, res }))
1635 }));
1636 let cast_ident = Ident::with_dummy_span(sym::cast);
1637 rib.bindings.insert(
1638 cast_ident.name,
1639 NameResolution::from_explicit(Binding {
1640 span: cast_ident.span,
1641 res: fhir::Res::GlobalFunc(fhir::SpecFuncKind::Cast),
1642 }),
1643 );
1644 rib
1645}
1646
1647fn mk_crate_mapping(tcx: TyCtxt) -> UnordMap<Symbol, DefId> {
1648 let mut map = UnordMap::default();
1649 for cnum in tcx.crates(()) {
1650 let name = tcx.crate_name(*cnum);
1651 if let Some(extern_crate) = tcx.extern_crate(*cnum)
1652 && extern_crate.is_direct()
1653 {
1654 map.insert(name, cnum.as_def_id());
1655 }
1656 }
1657 map
1658}
1659
1660mod errors {
1661 use flux_errors::E0999;
1662 use flux_macros::Diagnostic;
1663 use flux_syntax::surface::Ident;
1664 use rustc_span::{Span, Symbol, def_id::DefId};
1665
1666 use super::Segment;
1667
1668 #[derive(Diagnostic)]
1673 #[diag("cannot find {$kind} `{$name}` in this scope", code = E0999)]
1674 pub(crate) struct UnresolvedName {
1675 #[primary_span]
1676 #[label("not found in this scope")]
1677 span: Span,
1678 kind: &'static str,
1679 name: String,
1680 }
1681
1682 impl UnresolvedName {
1683 pub(crate) fn new<S: Segment>(span: Span, segments: &[S], kind: &'static str) -> Self {
1684 Self { span, name: Segment::format_iter(segments), kind }
1685 }
1686 }
1687
1688 #[derive(Diagnostic)]
1693 #[diag("unresolved import `{$name}`", code = E0999)]
1694 pub(crate) struct UnresolvedImport {
1695 #[primary_span]
1696 #[label("{$reason}")]
1697 pub span: Span,
1698 pub name: String,
1699 pub reason: String,
1700 }
1701
1702 impl UnresolvedImport {
1703 pub(super) fn new(
1706 ident: Ident,
1707 module_id: Option<DefId>,
1708 resolved_prefix: &[Ident],
1709 ) -> Self {
1710 let reason = match module_id {
1711 None => "not found in this scope".to_string(),
1712 Some(_) => format!("no `{ident}` in `{}`", Segment::format_iter(resolved_prefix)),
1713 };
1714 let name = Segment::format_iter(resolved_prefix.iter().chain(&[ident]));
1715 Self { span: ident.span, name, reason }
1716 }
1717 }
1718
1719 #[derive(Diagnostic)]
1720 #[diag("can't use generic parameters from outer item", code = E0999)]
1721 #[note("nested items cannot mention the generic parameters or `Self` of outer items")]
1722 pub(super) struct OuterGeneric {
1723 #[primary_span]
1724 #[label("use of generic parameter from outer item")]
1725 pub span: Span,
1726 }
1727
1728 #[derive(Diagnostic)]
1729 #[diag("unknown qualifier", code = E0999)]
1730 pub(super) struct UnknownQualifier {
1731 #[primary_span]
1732 span: Span,
1733 }
1734
1735 impl UnknownQualifier {
1736 pub(super) fn new(span: Span) -> Self {
1737 Self { span }
1738 }
1739 }
1740
1741 #[derive(Diagnostic)]
1742 #[diag("unknown function definition", code = E0999)]
1743 pub(super) struct UnknownFuncDefinition {
1744 #[primary_span]
1745 span: Span,
1746 }
1747
1748 impl UnknownFuncDefinition {
1749 pub(super) fn new(span: Span) -> Self {
1750 Self { span }
1751 }
1752 }
1753
1754 #[derive(Diagnostic)]
1755 #[diag("unknown type parameter", code = E0999)]
1756 pub(super) struct UnknownParametricParam {
1757 #[primary_span]
1758 span: Span,
1759 }
1760
1761 impl UnknownParametricParam {
1762 pub(super) fn new(span: Span) -> Self {
1763 Self { span }
1764 }
1765 }
1766
1767 #[derive(Diagnostic)]
1768 #[diag("the name `{$name}` is defined multiple times", code = E0999)]
1769 pub(super) struct DuplicateDefinition {
1770 #[primary_span]
1771 #[label("`{$name}` redefined here")]
1772 pub span: Span,
1773 #[label("previous definition of `{$name}`")]
1774 pub previous_definition: Span,
1775 pub name: Symbol,
1776 }
1777
1778 #[derive(Diagnostic)]
1781 #[diag("the name `{$name}` is ambiguous", code = E0999)]
1782 #[note("two different items named `{$name}` are in scope through glob imports")]
1783 pub(super) struct AmbiguousName {
1784 #[primary_span]
1785 #[label("ambiguous name")]
1786 span: Span,
1787 name: Symbol,
1788 #[label("`{$name}` could refer to the item imported here")]
1789 first: Span,
1790 #[label("`{$name}` could also refer to the item imported here")]
1791 second: Option<Span>,
1792 }
1793
1794 impl AmbiguousName {
1795 pub(super) fn new(ambiguity: super::Ambiguity) -> Self {
1796 let super::Ambiguity { span, name, first, second } = ambiguity;
1797 Self { span, name, first, second: (first != second).then_some(second) }
1801 }
1802 }
1803
1804 #[derive(Diagnostic)]
1805 #[diag("identifier `{$name}` is bound more than once in this parameter list", code = E0999)]
1806 pub(super) struct DuplicateParam {
1807 #[primary_span]
1808 #[label("used as a parameter more than once")]
1809 pub span: Span,
1810 pub name: Symbol,
1811 #[label("first use of `{$name}`")]
1812 pub first_use: Span,
1813 }
1814}