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;
10use flux_middle::{
11 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_HIR_ID, CRATE_OWNER_ID, ParamName, PrimTy, def::CtorOf, def_id::CRATE_DEF_ID,
30};
31use rustc_middle::{metadata::ModChild, ty::TyCtxt};
32use rustc_span::{Span, Symbol, def_id::DefId, symbol::kw};
33
34use self::refinement_resolver::RefinementResolver;
35
36type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
37
38enum ResolveError {
41 NotFound,
42 Ambiguous(Ambiguity),
47}
48
49#[derive(Clone, Copy, Debug)]
62struct Ambiguity {
63 span: Span,
65 name: Symbol,
67 first: Span,
69 second: Span,
72}
73
74pub(crate) fn resolve_crate(genv: GlobalEnv) -> ResolverOutput {
75 match try_resolve_crate(genv) {
76 Ok(output) => output,
77 Err(err) => genv.sess().abort(err),
78 }
79}
80
81fn try_resolve_crate(genv: GlobalEnv) -> Result<ResolverOutput> {
82 let specs = genv.collect_specs();
83 let mut resolver = CrateResolver::new(genv, specs);
84
85 genv.tcx().hir_walk_toplevel_module(&mut resolver);
86
87 resolver.into_output()
88}
89
90pub(crate) struct CrateResolver<'genv, 'tcx> {
91 genv: GlobalEnv<'genv, 'tcx>,
92 specs: &'genv Specs,
93 output: ResolverOutput,
94 ribs: PerNS<Vec<Rib>>,
95 crates: UnordMap<Symbol, DefId>,
97 prelude: PerNS<Rib>,
100 qualifiers: UnordMap<Symbol, FluxLocalDefId>,
101 primop_props: UnordMap<Symbol, FluxDefId>,
102 err: Option<ErrorGuaranteed>,
103 current_module: OwnerId,
106}
107
108#[derive(Default)]
110struct DefinitionMap {
111 defined: UnordMap<Ident, ()>,
112}
113
114impl DefinitionMap {
115 fn define(&mut self, name: Ident) -> std::result::Result<(), errors::DuplicateDefinition> {
116 match self.defined.entry(name) {
117 hash_map::Entry::Occupied(entry) => {
118 Err(errors::DuplicateDefinition {
119 span: name.span,
120 previous_definition: entry.key().span,
121 name: name.name,
122 })
123 }
124 hash_map::Entry::Vacant(entry) => {
125 entry.insert(());
126 Ok(())
127 }
128 }
129 }
130}
131
132impl<'genv, 'tcx> CrateResolver<'genv, 'tcx> {
133 pub fn new(genv: GlobalEnv<'genv, 'tcx>, specs: &'genv Specs) -> Self {
134 Self {
135 genv,
136 output: ResolverOutput::default(),
137 specs,
138 ribs: PerNS { type_ns: vec![], value_ns: vec![], macro_ns: vec![], flux_fn_ns: vec![] },
139 crates: mk_crate_mapping(genv.tcx()),
140 prelude: PerNS {
141 type_ns: builtin_types_rib(),
142 value_ns: Rib::new(RibKind::Misc),
143 macro_ns: Rib::new(RibKind::Misc),
144 flux_fn_ns: theory_funcs_rib(),
145 },
146 err: None,
147 qualifiers: Default::default(),
148 primop_props: Default::default(),
149 current_module: CRATE_OWNER_ID,
150 }
151 }
152
153 #[allow(
156 clippy::disallowed_methods,
157 reason = "`flux_items_by_parent` is the source of truth for `FluxDefId`"
158 )]
159 fn define_flux_global_items(&mut self) {
160 let mut definitions = DefinitionMap::default();
161 for (parent, items) in &self.specs.flux_items_by_parent {
162 for item in items {
163 match item {
165 surface::FluxItem::Qualifier(qual) => {
166 let ident = qual.name;
167 if definitions
168 .define(ident)
169 .emit(&self.genv)
170 .collect_err(&mut self.err)
171 .is_some()
172 {
173 let def_id = FluxLocalDefId::new(parent.def_id, ident.name);
174 self.qualifiers.insert(ident.name, def_id);
175 }
176 }
177 surface::FluxItem::PrimOpProp(primop) => {
178 let ident = primop.name;
179 if definitions
180 .define(ident)
181 .emit(&self.genv)
182 .collect_err(&mut self.err)
183 .is_some()
184 {
185 let def_id = FluxDefId::new(parent.def_id.to_def_id(), ident.name);
186 self.primop_props.insert(ident.name, def_id);
187 }
188 }
189 surface::FluxItem::Use(_)
190 | surface::FluxItem::FuncDef(_)
191 | surface::FluxItem::SortDecl(_) => {}
192 };
193 }
194 }
195 }
196
197 #[allow(
198 clippy::disallowed_methods,
199 reason = "`flux_items_by_parent` is the source of truth for `FluxDefId`"
200 )]
201 fn define_module_flux_items(&mut self, parent: OwnerId) {
202 let Some(items) = self.specs.flux_items_by_parent.get(&parent) else { return };
203 for item in items {
204 match item {
205 surface::FluxItem::Qualifier(_) | surface::FluxItem::PrimOpProp(_) => {
206 }
208 surface::FluxItem::FuncDef(defn) => {
209 let def_id = FluxDefId::new(parent.def_id.to_def_id(), defn.name.name);
210 let kind = fhir::SpecFuncKind::Def(def_id);
211 self.define_res_in(
212 fhir::Res::GlobalFunc(kind),
213 ReftNS,
214 BindingSource::Explicit(defn.name),
215 );
216 }
217 surface::FluxItem::SortDecl(sort_decl) => {
218 let def_id = FluxDefId::new(parent.def_id.to_def_id(), sort_decl.name.name);
219 self.define_res_in(
220 fhir::Res::UserSort(def_id),
221 TypeNS,
222 BindingSource::Explicit(sort_decl.name),
223 );
224 }
225 surface::FluxItem::Use(use_tree) => {
226 for (ident, res, ns) in self.resolve_flux_use_tree(use_tree) {
228 self.define_res_in(res, ns, BindingSource::Explicit(ident));
229 }
230 }
231 }
232 }
233 }
234
235 fn define_items(&mut self, item_ids: impl IntoIterator<Item = &'tcx ItemId>) {
236 for item_id in item_ids {
237 let item = self.genv.tcx().hir_item(*item_id);
238 let def_kind = match item.kind {
239 ItemKind::Use(path, kind) => {
240 match kind {
241 hir::UseKind::Single(ident) => {
242 if let Some(res) = path.res.value_ns
243 && let Ok(res) = fhir::Res::try_from(res)
244 {
245 self.define_res_in(res, ValueNS, BindingSource::Explicit(ident));
246 }
247 if let Some(res) = path.res.type_ns
248 && let Ok(res) = fhir::Res::try_from(res)
249 {
250 self.define_res_in(res, TypeNS, BindingSource::Explicit(ident));
251 }
252 }
253 hir::UseKind::Glob => {
254 let is_prelude = is_prelude_import(self.genv.tcx(), item);
255 let glob_span = item.span;
256 for mod_child in self.glob_imports(path) {
257 if let Ok(res) = fhir::Res::try_from(mod_child.res)
258 && let Some(ns @ (TypeNS | ValueNS)) = res.ns()
259 {
260 if is_prelude {
261 self.define_in_prelude(mod_child.ident, res, ns);
262 } else {
263 let source = BindingSource::Glob {
264 ident: mod_child.ident,
265 glob_span,
266 };
267 self.define_res_in(res, ns, source);
268 }
269 }
270 }
271 }
272 hir::UseKind::ListStem => {}
273 }
274 continue;
275 }
276 ItemKind::TyAlias(..) => DefKind::TyAlias,
277 ItemKind::Enum(..) => DefKind::Enum,
278 ItemKind::Struct(..) => DefKind::Struct,
279 ItemKind::Union(..) => DefKind::Union,
280 ItemKind::Trait(..) => DefKind::Trait,
281 ItemKind::Mod(..) => DefKind::Mod,
282 ItemKind::Const(..) => DefKind::Const,
283 ItemKind::ForeignMod { items, .. } => {
284 self.define_foreign_items(items);
285 continue;
286 }
287 _ => continue,
288 };
289 if let Some(ns) = def_kind.ns().map(Namespace::from)
290 && let Some(ident) = item.kind.ident()
291 {
292 self.define_res_in(
293 fhir::Res::Def(def_kind, item.owner_id.to_def_id()),
294 ns,
295 BindingSource::Explicit(ident),
296 );
297 }
298 }
299 }
300
301 fn define_foreign_items(&mut self, items: &[rustc_hir::ForeignItemId]) {
302 for item_id in items {
303 let item = self.genv.tcx().hir_foreign_item(*item_id);
304 match item.kind {
305 rustc_hir::ForeignItemKind::Type => {
306 self.define_res_in(
307 fhir::Res::Def(DefKind::ForeignTy, item.owner_id.to_def_id()),
308 TypeNS,
309 BindingSource::Explicit(item.ident),
310 );
311 }
312 rustc_hir::ForeignItemKind::Fn(..) | rustc_hir::ForeignItemKind::Static(..) => {}
313 }
314 }
315 }
316
317 fn define_res_in(
319 &mut self,
320 res: fhir::Res<surface::NodeId>,
321 ns: Namespace,
322 source: BindingSource,
323 ) {
324 let ident = source.ident();
325 if ident.name == kw::Underscore {
326 return;
327 }
328 let entry = self.ribs[ns]
329 .last_mut()
330 .unwrap()
331 .bindings
332 .entry(ident.name)
333 .or_default();
334
335 if let Some(prev) = entry.define(source, res) {
336 if let fhir::Res::Param(..) = prev.res {
337 self.emit(errors::DuplicateParam {
338 span: ident.span,
339 name: ident.name,
340 first_use: prev.span,
341 });
342 } else {
343 self.emit(errors::DuplicateDefinition {
344 span: ident.span,
345 previous_definition: prev.span,
346 name: ident.name,
347 });
348 }
349 }
350 }
351
352 fn define_in_prelude(&mut self, ident: Ident, res: fhir::Res<surface::NodeId>, ns: Namespace) {
356 self.prelude[ns]
357 .bindings
358 .insert(ident.name, NameResolution::from_explicit(Binding { span: ident.span, res }));
359 }
360
361 fn push_rib(&mut self, ns: Namespace, kind: RibKind) {
362 self.ribs[ns].push(Rib::new(kind));
363 }
364
365 fn pop_rib(&mut self, ns: Namespace) {
366 self.ribs[ns].pop();
367 }
368
369 fn define_generics(&mut self, def_id: MaybeExternId<OwnerId>) {
370 let generics = self
371 .genv
372 .tcx()
373 .hir_get_generics(def_id.local_id().def_id)
374 .unwrap();
375 for param in generics.params {
376 let def_kind = self.genv.tcx().def_kind(param.def_id);
377 if let ParamName::Plain(name) = param.name
378 && let Some(ns) = def_kind.ns().map(Namespace::from)
379 {
380 debug_assert!(matches!(def_kind, DefKind::TyParam | DefKind::ConstParam));
381 let param_id = self.genv.maybe_extern_id(param.def_id).resolved_id();
382 self.define_res_in(
383 fhir::Res::Def(def_kind, param_id),
384 ns,
385 BindingSource::Explicit(name),
386 );
387 }
388 }
389 }
390
391 fn resolve_flux_items(&mut self, parent: OwnerId) {
392 let Some(items) = self.specs.flux_items_by_parent.get(&parent) else { return };
393 for item in items {
394 RefinementResolver::resolve_flux_item(self, item).collect_err(&mut self.err);
395 }
396 }
397
398 fn resolve_item(&mut self, item: &surface::Item, item_id: MaybeExternId<OwnerId>) -> Result {
399 ItemResolver::run(self, item_id, |item_resolver| item_resolver.visit_item(item))?;
400 RefinementResolver::resolve_item(self, item)
401 }
402
403 fn resolve_trait_item(
404 &mut self,
405 item: &surface::TraitItemFn,
406 item_id: MaybeExternId<OwnerId>,
407 ) -> Result {
408 ItemResolver::run(self, item_id, |item_resolver| item_resolver.visit_trait_item(item))?;
409 RefinementResolver::resolve_trait_item(self, item)
410 }
411
412 fn resolve_impl_item(
413 &mut self,
414 item: &surface::ImplItemFn,
415 item_id: MaybeExternId<OwnerId>,
416 ) -> Result {
417 ItemResolver::run(self, item_id, |item_resolver| item_resolver.visit_impl_item(item))?;
418 RefinementResolver::resolve_impl_item(self, item)
419 }
420
421 fn resolve_path_with_ribs<S: Segment>(
422 &mut self,
423 segments: &[S],
424 ns: Namespace,
425 ) -> std::result::Result<fhir::PartialRes<surface::NodeId>, ResolveError> {
426 let mut module: Option<Module> = None;
427 for (segment_idx, segment) in segments.iter().enumerate() {
428 let is_last = segment_idx + 1 == segments.len();
429 let ns = if is_last { ns } else { TypeNS };
430
431 let base_res = if let Some(module) = module {
432 self.resolve_ident_in_module(module, segment.ident(), ns)?
433 } else {
434 self.resolve_ident_with_ribs(segment.ident(), ns)?
435 };
436
437 S::record_segment_res(self, segment, base_res);
438
439 if is_last {
440 return Ok(fhir::PartialRes::new(base_res));
441 }
442
443 match base_res {
444 fhir::Res::Def(DefKind::Mod, module_id) => {
445 module = Some(Module::new(ModuleKind::Mod, module_id));
446 }
447 fhir::Res::Def(DefKind::Trait, module_id) => {
448 module = Some(Module::new(ModuleKind::Trait, module_id));
449 }
450 fhir::Res::Def(DefKind::Enum, module_id) => {
451 module = Some(Module::new(ModuleKind::Enum, module_id));
452 }
453 _ => {
454 return Ok(fhir::PartialRes::with_unresolved_segments(
455 base_res,
456 segments.len() - segment_idx - 1,
457 ));
458 }
459 }
460 }
461 Err(ResolveError::NotFound)
462 }
463
464 fn resolve_flux_use_tree(
465 &mut self,
466 use_tree: &surface::UseTree,
467 ) -> Vec<(Ident, fhir::Res<surface::NodeId>, Namespace)> {
468 self.resolve_flux_use_tree_rec(use_tree, None, &mut vec![])
469 }
470
471 fn resolve_flux_use_tree_rec(
472 &mut self,
473 use_tree: &surface::UseTree,
474 mut resolved_module_id: Option<DefId>,
475 resolved_prefix: &mut Vec<Ident>,
476 ) -> Vec<(Ident, fhir::Res<surface::NodeId>, Namespace)> {
477 let Some((last, all_but_last)) = use_tree.prefix.segments.split_last() else {
478 bug!("path must have at least one segment")
479 };
480 let module_segments = match &use_tree.kind {
481 surface::UseTreeKind::Simple => all_but_last,
482 surface::UseTreeKind::Nested(_) => &use_tree.prefix.segments[..],
483 };
484
485 for segment in module_segments {
486 let ident = segment.ident();
487 let res = if let Some(module_id) = resolved_module_id {
488 let module = Module::new(ModuleKind::Mod, module_id);
489 self.resolve_ident_in_module(module, ident, TypeNS)
490 } else {
491 self.resolve_ident_with_ribs(ident, TypeNS)
492 };
493 let res = match res {
494 Ok(res) => res,
495 Err(ResolveError::NotFound) => {
496 self.emit_unresolved_import(ident, resolved_module_id, resolved_prefix);
497 return vec![];
498 }
499 Err(ResolveError::Ambiguous(ambiguity)) => {
500 self.emit_ambiguity_err(ambiguity);
501 return vec![];
502 }
503 };
504 if let fhir::Res::Def(DefKind::Mod, def_id) = res {
505 resolved_module_id = Some(def_id);
506 } else {
507 self.emit_not_a_module(ident, resolved_prefix);
508 return vec![];
509 }
510 resolved_prefix.push(ident);
511 }
512
513 match &use_tree.kind {
514 surface::UseTreeKind::Simple => {
515 let mut resolutions = vec![];
516 let mut ambiguity = None;
520 for ns in [TypeNS, ValueNS, ReftNS] {
521 let res = if let Some(module_id) = resolved_module_id {
522 let module = Module::new(ModuleKind::Mod, module_id);
523 self.resolve_ident_in_module(module, last.ident(), ns)
524 } else {
525 self.resolve_ident_with_ribs(last.ident(), ns)
526 };
527 match res {
528 Ok(res) => resolutions.push((last.ident(), res, ns)),
529 Err(ResolveError::Ambiguous(amb)) => ambiguity = ambiguity.or(Some(amb)),
530 Err(ResolveError::NotFound) => {}
531 }
532 }
533 if let Some(ambiguity) = ambiguity {
534 self.emit_ambiguity_err(ambiguity);
535 } else if resolutions.is_empty() {
536 self.emit_unresolved_import(last.ident, resolved_module_id, resolved_prefix);
537 }
538 resolutions
539 }
540 surface::UseTreeKind::Nested(items) => {
541 let mut resolutions = vec![];
542 for item in items {
543 let len = resolved_prefix.len();
544 resolutions.extend(self.resolve_flux_use_tree_rec(
545 item,
546 resolved_module_id,
547 resolved_prefix,
548 ));
549 resolved_prefix.truncate(len);
550 }
551 resolutions
552 }
553 }
554 }
555
556 fn resolve_ident_with_ribs(
557 &self,
558 ident: Ident,
559 ns: Namespace,
560 ) -> std::result::Result<fhir::Res<surface::NodeId>, ResolveError> {
561 let mut ribs = self.ribs[ns].iter().rev();
562 while let Some(rib) = ribs.next() {
563 if let Some(name_res) = rib.bindings.get(&ident.name)
566 && let Some(res) = name_res.resolve(ident)
567 {
568 return res.map_err(ResolveError::Ambiguous);
569 }
570 match rib.kind {
571 RibKind::Module => break,
573 RibKind::Variant => {
578 ribs.take_while_ref(|rib| !matches!(rib.kind, RibKind::Module))
579 .for_each(drop);
580 }
581 _ => {}
582 }
583 }
584 if ns == TypeNS {
585 if let Some(crate_id) = self.crates.get(&ident.name) {
586 return Ok(fhir::Res::Def(DefKind::Mod, *crate_id));
587 }
588 if ident.name == kw::Crate {
590 return Ok(fhir::Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()));
591 }
592 if ident.name == kw::Super
593 && let Some(parent) = self.genv.tcx().opt_local_parent(self.current_module.def_id)
594 {
595 return Ok(fhir::Res::Def(DefKind::Mod, parent.to_def_id()));
596 }
597 }
598
599 if let Some(name_res) = self.prelude[ns].bindings.get(&ident.name)
600 && let Some(res) = name_res.resolve(ident)
601 {
602 return res.map_err(ResolveError::Ambiguous);
603 }
604 Err(ResolveError::NotFound)
605 }
606
607 fn glob_imports(
608 &mut self,
609 path: &hir::UsePath,
610 ) -> impl Iterator<Item = &'tcx ModChild> + use<'tcx> {
611 let tcx = self.genv.tcx();
615 let curr_mod = self.current_module.to_def_id();
616 self.resolve_path_with_ribs(path.segments, TypeNS)
617 .ok()
618 .and_then(|partial_res| partial_res.full_res())
619 .and_then(|res| {
620 if let fhir::Res::Def(DefKind::Mod, module_id) = res {
621 Some(module_id)
622 } else {
623 None
624 }
625 })
626 .into_iter()
627 .flat_map(move |module_id| visible_module_children(tcx, module_id, curr_mod))
628 }
629
630 fn resolve_ident_in_module(
631 &self,
632 module: Module,
633 ident: Ident,
634 ns: Namespace,
635 ) -> std::result::Result<fhir::Res<surface::NodeId>, ResolveError> {
636 let tcx = self.genv.tcx();
637 let res = match module.kind {
638 ModuleKind::Mod => {
639 let module_id = module.def_id;
640 let current_mod = self.current_module.to_def_id();
641
642 let mut resolution: NameResolution = ns
651 .to_rustc()
652 .into_iter()
653 .flat_map(|rustc_ns| {
654 visible_module_children(tcx, module_id, current_mod).filter(move |child| {
655 child.res.matches_ns(rustc_ns)
656 && tcx.hygienic_eq(ident, child.ident, current_mod)
657 })
658 })
659 .filter_map(|child| {
660 Some(Binding {
661 span: child.ident.span,
662 res: fhir::Res::try_from(child.res).ok()?,
663 })
664 })
665 .collect();
666 if resolution.is_empty() {
667 if let Some(ambiguity) = self.ambiguous_module_child(module_id, ident, ns) {
669 return Err(ResolveError::Ambiguous(ambiguity));
670 }
671 resolution = self
672 .genv
673 .flux_module_children(module_id)
674 .iter()
675 .filter(|child| {
676 child.res.ns() == Some(ns) && child.ident.name == ident.name
677 })
678 .map(|child| {
679 Binding {
680 span: child.ident.span,
681 res: child.res.map_param_id(|id| match id {}),
682 }
683 })
684 .collect();
685 }
686 resolution.resolve(ident)
687 }
688 ModuleKind::Trait => {
689 ns.to_rustc()
691 .and_then(|rustc_ns| {
692 let trait_id = module.def_id;
693 tcx.associated_items(trait_id)
694 .find_by_ident_and_namespace(tcx, ident, rustc_ns, trait_id)
695 .map(|assoc| fhir::Res::Def(assoc.kind.as_def_kind(), assoc.def_id))
696 })
697 .map(Ok)
698 }
699 ModuleKind::Enum => {
700 tcx.adt_def(module.def_id)
701 .variants()
702 .iter()
703 .find(|data| data.name == ident.name)
704 .and_then(|data| {
705 let (kind, def_id) = match (ns, data.ctor) {
706 (TypeNS, _) => (DefKind::Variant, data.def_id),
707 (ValueNS, Some((ctor_kind, ctor_id))) => {
708 (DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_id)
709 }
710 _ => return None,
711 };
712 Some(fhir::Res::Def(kind, def_id))
713 })
714 .map(Ok)
715 }
716 };
717 match res {
718 Some(res) => res.map_err(ResolveError::Ambiguous),
719 None => Err(ResolveError::NotFound),
720 }
721 }
722
723 #[expect(clippy::disallowed_methods, reason = "modules cannot have extern specs")]
734 fn ambiguous_module_child(
735 &self,
736 module_id: DefId,
737 ident: Ident,
738 ns: Namespace,
739 ) -> Option<Ambiguity> {
740 let tcx = self.genv.tcx();
741 let module_id = module_id.as_local()?;
742 let rustc_ns = ns.to_rustc()?;
743 let current_mod = self.current_module.to_def_id();
744 let child = tcx
745 .resolutions(())
746 .ambig_module_children
747 .get(&module_id)?
748 .iter()
749 .find(|child| {
750 child.main.res.matches_ns(rustc_ns)
751 && tcx.hygienic_eq(ident, child.main.ident, current_mod)
752 && child.main.vis.is_accessible_from(current_mod, tcx)
753 })?;
754 Some(Ambiguity {
755 span: ident.span,
756 name: ident.name,
757 first: self.glob_span(&child.main),
758 second: self.glob_span(&child.second),
759 })
760 }
761
762 fn glob_span(&self, child: &ModChild) -> Span {
765 let def_id = child
766 .reexport_chain
767 .first()
768 .and_then(|reexport| reexport.id())
769 .unwrap_or_else(|| child.res.def_id());
770 self.genv.tcx().def_span(def_id)
771 }
772
773 pub fn into_output(self) -> Result<ResolverOutput> {
774 self.err.into_result()?;
775 Ok(self.output)
776 }
777
778 #[track_caller]
779 fn emit_unresolved_import(
780 &mut self,
781 ident: Ident,
782 module_id: Option<DefId>,
783 resolved_prefix: &[Ident],
784 ) {
785 let reason = match module_id {
786 None => "not found in this scope".to_string(),
787 Some(_) => format!("no `{ident}` in `{}`", Segment::format_iter(resolved_prefix)),
788 };
789 let name = Segment::format_iter(resolved_prefix.iter().chain(&[ident]));
790 self.emit(errors::UnresolvedImport { span: ident.span, name, reason });
791 }
792
793 #[track_caller]
794 fn emit_ambiguity_err(&mut self, ambiguity: Ambiguity) {
795 self.emit(errors::AmbiguousName::new(ambiguity));
796 }
797
798 fn emit_not_a_module(&mut self, ident: Ident, resolved_prefix: &[Ident]) {
799 let name = Segment::format_iter(resolved_prefix.iter().chain(&[ident]));
800 self.emit(errors::UnresolvedImport {
801 span: ident.span,
802 name,
803 reason: format!("`{ident}` is not a module"),
804 });
805 }
806
807 #[track_caller]
808 fn emit(&mut self, err: impl rustc_errors::Diagnostic<'genv>) {
809 self.err.collect(self.genv.sess().emit_err(err));
810 }
811}
812
813impl<'tcx> hir::intravisit::Visitor<'tcx> for CrateResolver<'_, 'tcx> {
814 type NestedFilter = rustc_middle::hir::nested_filter::All;
815
816 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
817 self.genv.tcx()
818 }
819
820 fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _s: Span, hir_id: hir::HirId) {
821 let old_mod = self.current_module;
822 self.current_module = hir_id.expect_owner();
823 self.push_rib(TypeNS, RibKind::Module);
824 self.push_rib(ValueNS, RibKind::Module);
825 self.push_rib(ReftNS, RibKind::Module);
826
827 self.define_items(module.item_ids);
828
829 if hir_id == CRATE_HIR_ID {
831 self.define_flux_global_items();
832 }
833 self.define_module_flux_items(hir_id.expect_owner());
835
836 self.resolve_flux_items(hir_id.expect_owner());
837 hir::intravisit::walk_mod(self, module);
838
839 self.pop_rib(ReftNS);
840 self.pop_rib(ValueNS);
841 self.pop_rib(TypeNS);
842 self.current_module = old_mod;
843 }
844
845 fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
846 let parent = self.genv.tcx().hir_get_parent_item(block.hir_id);
847
848 self.push_rib(TypeNS, RibKind::Misc);
849 self.push_rib(ValueNS, RibKind::Misc);
850 self.push_rib(ReftNS, RibKind::Misc);
851
852 let item_ids = block.stmts.iter().filter_map(|stmt| {
853 if let hir::StmtKind::Item(item_id) = &stmt.kind { Some(item_id) } else { None }
854 });
855 self.define_items(item_ids);
856 self.define_module_flux_items(parent);
857
858 self.resolve_flux_items(parent);
859 hir::intravisit::walk_block(self, block);
860
861 self.pop_rib(ReftNS);
862 self.pop_rib(ValueNS);
863 self.pop_rib(TypeNS);
864 }
865
866 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
867 if self.genv.is_dummy(item.owner_id.def_id) {
868 return;
869 }
870 let def_id = self
871 .genv
872 .maybe_extern_id(item.owner_id.def_id)
873 .map(|def_id| OwnerId { def_id });
874
875 self.push_rib(TypeNS, RibKind::Misc);
876 self.push_rib(ValueNS, RibKind::Misc);
877
878 match item.kind {
879 ItemKind::Trait(..) => {
880 self.define_generics(def_id);
881 self.define_res_in(
882 fhir::Res::SelfTyParam { trait_: def_id.resolved_id() },
883 TypeNS,
884 BindingSource::Explicit(Ident::with_dummy_span(kw::SelfUpper)),
885 );
886 }
887 ItemKind::Impl(hir::Impl { of_trait, .. }) => {
888 self.define_generics(def_id);
889 self.define_res_in(
890 fhir::Res::SelfTyAlias {
891 alias_to: def_id.resolved_id(),
892 is_trait_impl: of_trait.is_some(),
893 },
894 TypeNS,
895 BindingSource::Explicit(Ident::with_dummy_span(kw::SelfUpper)),
896 );
897 }
898 ItemKind::TyAlias(..) => {
899 self.define_generics(def_id);
900 }
901 ItemKind::Enum(..) => {
902 self.define_generics(def_id);
903 self.define_res_in(
904 fhir::Res::SelfTyAlias { alias_to: def_id.resolved_id(), is_trait_impl: false },
905 TypeNS,
906 BindingSource::Explicit(Ident::with_dummy_span(kw::SelfUpper)),
907 );
908 }
909 ItemKind::Struct(..) => {
910 self.define_generics(def_id);
911 self.define_res_in(
912 fhir::Res::SelfTyAlias { alias_to: def_id.resolved_id(), is_trait_impl: false },
913 TypeNS,
914 BindingSource::Explicit(Ident::with_dummy_span(kw::SelfUpper)),
915 );
916 }
917 ItemKind::Fn { .. } => {
918 self.define_generics(def_id);
919 }
920 _ => {}
921 }
922 if let Some(item) = self.specs.get_item(def_id.local_id()) {
923 self.resolve_item(item, def_id).collect_err(&mut self.err);
924 }
925
926 hir::intravisit::walk_item(self, item);
927
928 self.pop_rib(ValueNS);
929 self.pop_rib(TypeNS);
930 }
931
932 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
933 let def_id = self
934 .genv
935 .maybe_extern_id(impl_item.owner_id.def_id)
936 .map(|def_id| OwnerId { def_id });
937
938 self.push_rib(TypeNS, RibKind::Misc);
939 if let Some(item) = self.specs.get_impl_item(def_id.local_id()) {
940 self.define_generics(def_id);
941 self.resolve_impl_item(item, def_id)
942 .collect_err(&mut self.err);
943 }
944 hir::intravisit::walk_impl_item(self, impl_item);
945 self.pop_rib(TypeNS);
946 }
947
948 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
949 let def_id = self
950 .genv
951 .maybe_extern_id(trait_item.owner_id.def_id)
952 .map(|def_id| OwnerId { def_id });
953
954 self.push_rib(TypeNS, RibKind::Misc);
955 if let Some(item) = self.specs.get_trait_item(def_id.local_id()) {
956 self.define_generics(def_id);
957 self.resolve_trait_item(item, def_id)
958 .collect_err(&mut self.err);
959 }
960 hir::intravisit::walk_trait_item(self, trait_item);
961 self.pop_rib(TypeNS);
962 }
963}
964
965#[derive(Clone, Copy, Debug)]
967struct Module {
968 kind: ModuleKind,
969 def_id: DefId,
970}
971
972impl Module {
973 fn new(kind: ModuleKind, def_id: DefId) -> Self {
974 Self { kind, def_id }
975 }
976}
977
978#[derive(Clone, Copy, Debug)]
980enum ModuleKind {
981 Mod,
982 Trait,
983 Enum,
984}
985
986#[derive(Clone, Copy, PartialEq, Eq, Debug)]
987pub(crate) enum RibKind {
988 Misc,
990 Module,
992 FnInput,
994 FnOutput,
996 Variant,
999 FnTraitInput,
1002}
1003
1004#[derive(Clone, Copy, Debug)]
1008struct Binding {
1009 span: Span,
1013 res: fhir::Res<surface::NodeId>,
1014}
1015
1016#[derive(Clone, Copy, Debug)]
1020enum BindingSource {
1021 Explicit(Ident),
1023 Glob { ident: Ident, glob_span: Span },
1026}
1027
1028impl BindingSource {
1029 fn ident(self) -> Ident {
1030 match self {
1031 BindingSource::Explicit(ident) | BindingSource::Glob { ident, .. } => ident,
1032 }
1033 }
1034
1035 fn span(self) -> Span {
1037 match self {
1038 BindingSource::Explicit(ident) => ident.span,
1039 BindingSource::Glob { glob_span, .. } => glob_span,
1040 }
1041 }
1042}
1043
1044#[derive(Clone, Copy, Debug)]
1046enum GlobBinding {
1047 Single(Binding),
1048 Ambiguous(Span, Span),
1053}
1054
1055#[derive(Clone, Copy, Debug, Default)]
1058struct NameResolution {
1059 non_glob: Option<Binding>,
1060 glob: Option<GlobBinding>,
1061}
1062
1063impl NameResolution {
1064 fn from_explicit(binding: Binding) -> Self {
1065 Self { non_glob: Some(binding), glob: None }
1066 }
1067
1068 fn is_empty(&self) -> bool {
1069 self.non_glob.is_none() && self.glob.is_none()
1070 }
1071
1072 fn define(
1074 &mut self,
1075 source: BindingSource,
1076 res: fhir::Res<surface::NodeId>,
1077 ) -> Option<Binding> {
1078 let binding = Binding { span: source.span(), res };
1079 match source {
1080 BindingSource::Explicit(_) => {
1081 if let Some(prev) = self.non_glob {
1082 Some(prev)
1083 } else {
1084 self.non_glob = Some(binding);
1085 None
1086 }
1087 }
1088 BindingSource::Glob { .. } => {
1089 self.add_glob(binding);
1090 None
1091 }
1092 }
1093 }
1094
1095 fn add_glob(&mut self, binding: Binding) {
1099 self.glob = Some(match self.glob {
1100 None => GlobBinding::Single(binding),
1101 Some(GlobBinding::Single(prev)) => {
1102 if prev.res == binding.res {
1103 GlobBinding::Single(prev)
1104 } else {
1105 GlobBinding::Ambiguous(prev.span, binding.span)
1106 }
1107 }
1108 Some(ambiguous @ GlobBinding::Ambiguous(..)) => ambiguous,
1109 });
1110 }
1111
1112 fn resolve(
1115 &self,
1116 ident: Ident,
1117 ) -> Option<std::result::Result<fhir::Res<surface::NodeId>, Ambiguity>> {
1118 if let Some(binding) = self.non_glob {
1119 return Some(Ok(binding.res));
1120 }
1121 match self.glob? {
1122 GlobBinding::Single(binding) => Some(Ok(binding.res)),
1123 GlobBinding::Ambiguous(first, second) => {
1124 Some(Err(Ambiguity { span: ident.span, name: ident.name, first, second }))
1125 }
1126 }
1127 }
1128}
1129
1130impl FromIterator<Binding> for NameResolution {
1131 fn from_iter<T: IntoIterator<Item = Binding>>(iter: T) -> Self {
1134 let mut resolution = Self::default();
1135 for binding in iter {
1136 resolution.add_glob(binding);
1137 }
1138 resolution
1139 }
1140}
1141
1142#[derive(Debug)]
1143struct Rib {
1144 kind: RibKind,
1145 bindings: UnordMap<Symbol, NameResolution>,
1146}
1147
1148impl Rib {
1149 fn new(kind: RibKind) -> Self {
1150 Self { kind, bindings: Default::default() }
1151 }
1152}
1153
1154fn module_children(tcx: TyCtxt<'_>, def_id: DefId) -> &[ModChild] {
1155 #[expect(clippy::disallowed_methods, reason = "modules cannot have extern specs")]
1156 if let Some(local_id) = def_id.as_local() {
1157 tcx.module_children_local(local_id)
1158 } else {
1159 tcx.module_children(def_id)
1160 }
1161}
1162
1163fn visible_module_children(
1165 tcx: TyCtxt<'_>,
1166 module_id: DefId,
1167 curr_mod: DefId,
1168) -> impl Iterator<Item = &ModChild> {
1169 module_children(tcx, module_id)
1170 .iter()
1171 .filter(move |child| child.vis.is_accessible_from(curr_mod, tcx))
1172}
1173
1174fn is_prelude_import(tcx: TyCtxt, item: &hir::Item) -> bool {
1176 tcx.hir_attrs(item.hir_id())
1177 .iter()
1178 .any(|attr| attr.path_matches(&[sym::prelude_import]))
1179}
1180
1181trait Segment: std::fmt::Debug {
1184 fn record_segment_res(
1185 resolver: &mut CrateResolver,
1186 segment: &Self,
1187 res: fhir::Res<surface::NodeId>,
1188 );
1189 fn ident(&self) -> Ident;
1190
1191 fn format_iter<'a>(segments: impl IntoIterator<Item = &'a Self>) -> String
1192 where
1193 Self: Sized + 'a,
1194 {
1195 segments.into_iter().map(|s| s.ident()).join("::")
1196 }
1197}
1198
1199impl Segment for surface::PathSegment {
1200 fn record_segment_res(
1201 resolver: &mut CrateResolver,
1202 segment: &Self,
1203 res: fhir::Res<surface::NodeId>,
1204 ) {
1205 resolver
1206 .output
1207 .path_res_map
1208 .insert(segment.node_id, fhir::PartialRes::new(res));
1209 }
1210
1211 fn ident(&self) -> Ident {
1212 self.ident
1213 }
1214}
1215
1216impl Segment for surface::ExprPathSegment {
1217 fn record_segment_res(
1218 resolver: &mut CrateResolver,
1219 segment: &Self,
1220 res: fhir::Res<surface::NodeId>,
1221 ) {
1222 resolver
1223 .output
1224 .path_res_map
1225 .insert(segment.node_id, fhir::PartialRes::new(res));
1226 }
1227
1228 fn ident(&self) -> Ident {
1229 self.ident
1230 }
1231}
1232
1233impl Segment for Ident {
1234 fn record_segment_res(
1235 _resolver: &mut CrateResolver,
1236 _segment: &Self,
1237 _res: fhir::Res<surface::NodeId>,
1238 ) {
1239 }
1240
1241 fn ident(&self) -> Ident {
1242 *self
1243 }
1244}
1245
1246impl Segment for hir::PathSegment<'_> {
1247 fn record_segment_res(
1248 _resolver: &mut CrateResolver,
1249 _segment: &Self,
1250 _res: fhir::Res<surface::NodeId>,
1251 ) {
1252 }
1253
1254 fn ident(&self) -> Ident {
1255 self.ident
1256 }
1257}
1258
1259struct ItemResolver<'a, 'genv, 'tcx> {
1260 resolver: &'a mut CrateResolver<'genv, 'tcx>,
1261 errors: Errors<'genv>,
1262 item_id: MaybeExternId<OwnerId>,
1263}
1264
1265impl<'a, 'genv, 'tcx> ItemResolver<'a, 'genv, 'tcx> {
1266 fn run(
1267 resolver: &'a mut CrateResolver<'genv, 'tcx>,
1268 item_id: MaybeExternId<OwnerId>,
1269 f: impl FnOnce(&mut ItemResolver),
1270 ) -> Result {
1271 let mut item_resolver = ItemResolver::new(resolver, item_id);
1272 f(&mut item_resolver);
1273 item_resolver.errors.into_result()
1274 }
1275
1276 fn new(resolver: &'a mut CrateResolver<'genv, 'tcx>, item_id: MaybeExternId<OwnerId>) -> Self {
1277 let errors = Errors::new(resolver.genv.sess());
1278 Self { resolver, errors, item_id }
1279 }
1280
1281 fn resolve_path_in(&mut self, ns: Namespace, path: &surface::Path) {
1282 match self.resolver.resolve_path_with_ribs(&path.segments, ns) {
1283 Ok(partial_res) => {
1284 self.resolver
1285 .output
1286 .path_res_map
1287 .insert(path.node_id, partial_res);
1288 }
1289 Err(ResolveError::NotFound) => self.emit_unresolved_path(path, ns),
1290 Err(ResolveError::Ambiguous(ambiguity)) => self.emit_ambiguity_err(ambiguity),
1291 }
1292 }
1293
1294 fn resolve_attrs(&mut self, node_id: surface::NodeId, attrs: &[surface::Attr]) {
1295 for attr in attrs {
1296 match attr {
1297 surface::Attr::Qualifiers(names) => self.resolve_qualifiers(node_id, names),
1298 surface::Attr::Reveal(names) => self.resolve_reveals(node_id, names),
1299 surface::Attr::AssumeParametric(names) => {
1300 self.resolve_parametric_params(node_id, names);
1301 }
1302 _ => {}
1303 }
1304 }
1305 }
1306
1307 fn resolve_parametric_params(&mut self, node_id: surface::NodeId, names: &[Ident]) {
1308 let tcx = self.resolver.genv.tcx();
1309 let generics = tcx.generics_of(self.item_id.resolved_id());
1310 let param_map: UnordMap<Symbol, DefId> = (0..generics.count())
1311 .map(|i| generics.param_at(i, tcx))
1312 .map(|p| (p.name, p.def_id))
1313 .collect();
1314 let mut params = Vec::with_capacity(names.len());
1315 for name in names {
1316 if let Some(&def_id) = param_map.get(&name.name) {
1317 params.push(def_id);
1318 } else {
1319 self.errors
1320 .emit(errors::UnknownParametricParam::new(name.span));
1321 }
1322 }
1323 self.resolver
1324 .output
1325 .parametric_param_res_map
1326 .insert(node_id, params);
1327 }
1328
1329 fn resolve_qualifiers(&mut self, node_id: surface::NodeId, qual_names: &[Ident]) {
1330 let mut qualifiers = Vec::with_capacity(qual_names.len());
1331 for qual in qual_names {
1332 if let Some(def_id) = self.resolver.qualifiers.get(&qual.name) {
1333 qualifiers.push(*def_id);
1334 } else {
1335 self.errors.emit(errors::UnknownQualifier::new(qual.span));
1336 }
1337 }
1338 self.resolver
1339 .output
1340 .qualifier_res_map
1341 .insert(node_id, qualifiers);
1342 }
1343
1344 fn resolve_reveals(&mut self, item_id: surface::NodeId, reveal_names: &[Ident]) {
1345 let mut reveals = Vec::with_capacity(reveal_names.len());
1346 for reveal in reveal_names {
1347 match self.resolver.resolve_ident_with_ribs(*reveal, ReftNS) {
1348 Ok(fhir::Res::GlobalFunc(kind)) => {
1349 if let Some(def_id) = kind.def_id() {
1350 reveals.push(def_id);
1351 } else {
1352 self.errors
1353 .emit(errors::UnknownRevealDefinition::new(reveal.span));
1354 }
1355 }
1356 Ok(_) | Err(ResolveError::NotFound) => {
1357 self.errors
1358 .emit(errors::UnknownRevealDefinition::new(reveal.span));
1359 }
1360 Err(ResolveError::Ambiguous(ambiguity)) => self.emit_ambiguity_err(ambiguity),
1361 }
1362 }
1363 self.resolver.output.reveal_res_map.insert(item_id, reveals);
1364 }
1365
1366 fn emit_ambiguity_err(&mut self, ambiguity: Ambiguity) {
1367 self.errors.emit(errors::AmbiguousName::new(ambiguity));
1368 }
1369
1370 fn emit_unresolved_path(&mut self, path: &surface::Path, ns: Namespace) {
1371 self.errors.emit(errors::UnresolvedName {
1372 span: path.span,
1373 name: Segment::format_iter(&path.segments),
1374 kind: ns.descr(),
1375 });
1376 }
1377}
1378
1379impl surface::visit::Visitor for ItemResolver<'_, '_, '_> {
1380 fn visit_item(&mut self, item: &surface::Item) {
1381 self.resolve_attrs(item.node_id, &item.attrs);
1382 surface::visit::walk_item(self, item);
1383 }
1384
1385 fn visit_trait_item(&mut self, item: &surface::TraitItemFn) {
1386 self.resolve_attrs(item.node_id, &item.attrs);
1387 surface::visit::walk_trait_item(self, item);
1388 }
1389
1390 fn visit_impl_item(&mut self, item: &surface::ImplItemFn) {
1391 self.resolve_attrs(item.node_id, &item.attrs);
1392 surface::visit::walk_impl_item(self, item);
1393 }
1394
1395 fn visit_trait(&mut self, trait_: &surface::Trait) {
1396 let mut definitions = DefinitionMap::default();
1397 for assoc_reft in &trait_.assoc_refinements {
1398 let _ = definitions.define(assoc_reft.name).emit(&self.errors);
1399 }
1400 surface::visit::walk_trait(self, trait_);
1401 }
1402
1403 fn visit_impl(&mut self, impl_: &surface::Impl) {
1404 let mut definitions = DefinitionMap::default();
1405 for assoc_reft in &impl_.assoc_refinements {
1406 let _ = definitions.define(assoc_reft.name).emit(&self.errors);
1407 }
1408 surface::visit::walk_impl(self, impl_);
1409 }
1410
1411 fn visit_generic_arg(&mut self, arg: &surface::GenericArg) {
1412 if let surface::GenericArgKind::Type(ty) = &arg.kind
1413 && let Some(path) = ty.is_potential_const_arg()
1414 {
1415 let check_ns = |ns| {
1423 !matches!(
1424 self.resolver.resolve_ident_with_ribs(path.last().ident, ns),
1425 Err(ResolveError::NotFound)
1426 )
1427 };
1428
1429 if !check_ns(TypeNS) && check_ns(ValueNS) {
1430 self.resolve_path_in(ValueNS, path);
1431 return;
1432 }
1433 }
1434 surface::visit::walk_generic_arg(self, arg);
1435 }
1436
1437 fn visit_const_arg(&mut self, const_arg: &surface::ConstArg) {
1438 if let surface::ConstArgKind::Path(path) = &const_arg.kind {
1439 self.resolve_path_in(ValueNS, path);
1440 surface::visit::walk_path(self, path);
1441 }
1442 }
1443
1444 fn visit_path(&mut self, path: &surface::Path) {
1445 self.resolve_path_in(TypeNS, path);
1446 surface::visit::walk_path(self, path);
1447 }
1448}
1449
1450fn builtin_types_rib() -> Rib {
1455 use flux_middle::fhir::PrimSort;
1456 let sorts = PrimSort::ALL.into_iter().map(|prim| {
1457 let ident = Ident::with_dummy_span(prim.name());
1458 (
1459 ident.name,
1460 NameResolution::from_explicit(Binding {
1461 span: ident.span,
1462 res: fhir::Res::PrimSort(prim),
1463 }),
1464 )
1465 });
1466 let types = PrimTy::ALL.into_iter().map(|pty| {
1467 let ident = Ident::with_dummy_span(pty.name());
1468 (
1469 ident.name,
1470 NameResolution::from_explicit(Binding {
1471 span: ident.span,
1472 res: fhir::Res::PrimTy(pty),
1473 }),
1474 )
1475 });
1476
1477 let bindings = sorts.chain(types).collect();
1481 Rib { kind: RibKind::Misc, bindings }
1482}
1483
1484fn theory_funcs_rib() -> Rib {
1486 let mut rib = Rib::new(RibKind::Misc);
1487 rib.bindings
1488 .extend_unord(flux_middle::THEORY_FUNCS.items().map(|(_, itf)| {
1489 let ident = Ident::with_dummy_span(itf.name);
1490 let res = fhir::Res::GlobalFunc(fhir::SpecFuncKind::Thy(itf.itf));
1491 (ident.name, NameResolution::from_explicit(Binding { span: ident.span, res }))
1492 }));
1493 let cast_ident = Ident::with_dummy_span(sym::cast);
1494 rib.bindings.insert(
1495 cast_ident.name,
1496 NameResolution::from_explicit(Binding {
1497 span: cast_ident.span,
1498 res: fhir::Res::GlobalFunc(fhir::SpecFuncKind::Cast),
1499 }),
1500 );
1501 rib
1502}
1503
1504fn mk_crate_mapping(tcx: TyCtxt) -> UnordMap<Symbol, DefId> {
1505 let mut map = UnordMap::default();
1506 for cnum in tcx.crates(()) {
1507 let name = tcx.crate_name(*cnum);
1508 if let Some(extern_crate) = tcx.extern_crate(*cnum)
1509 && extern_crate.is_direct()
1510 {
1511 map.insert(name, cnum.as_def_id());
1512 }
1513 }
1514 map
1515}
1516
1517mod errors {
1518 use flux_errors::E0999;
1519 use flux_macros::Diagnostic;
1520 use rustc_span::{Span, Symbol};
1521
1522 #[derive(Diagnostic)]
1527 #[diag(desugar_unresolved_name, code = E0999)]
1528 pub(crate) struct UnresolvedName {
1529 #[primary_span]
1530 #[label]
1531 pub span: Span,
1532 pub kind: &'static str,
1533 pub name: String,
1534 }
1535
1536 #[derive(Diagnostic)]
1541 #[diag(desugar_unresolved_import, code = E0999)]
1542 pub(crate) struct UnresolvedImport {
1543 #[primary_span]
1544 #[label]
1545 pub span: Span,
1546 pub name: String,
1547 pub reason: String,
1548 }
1549
1550 #[derive(Diagnostic)]
1551 #[diag(desugar_unknown_qualifier, code = E0999)]
1552 pub(super) struct UnknownQualifier {
1553 #[primary_span]
1554 span: Span,
1555 }
1556
1557 impl UnknownQualifier {
1558 pub(super) fn new(span: Span) -> Self {
1559 Self { span }
1560 }
1561 }
1562
1563 #[derive(Diagnostic)]
1564 #[diag(desugar_unknown_reveal_definition, code = E0999)]
1565 pub(super) struct UnknownRevealDefinition {
1566 #[primary_span]
1567 span: Span,
1568 }
1569
1570 impl UnknownRevealDefinition {
1571 pub(super) fn new(span: Span) -> Self {
1572 Self { span }
1573 }
1574 }
1575
1576 #[derive(Diagnostic)]
1577 #[diag(desugar_unknown_parametric_param, code = E0999)]
1578 pub(super) struct UnknownParametricParam {
1579 #[primary_span]
1580 span: Span,
1581 }
1582
1583 impl UnknownParametricParam {
1584 pub(super) fn new(span: Span) -> Self {
1585 Self { span }
1586 }
1587 }
1588
1589 #[derive(Diagnostic)]
1590 #[diag(desugar_duplicate_definition, code = E0999)]
1591 pub(super) struct DuplicateDefinition {
1592 #[primary_span]
1593 #[label]
1594 pub span: Span,
1595 #[label(desugar_previous_definition)]
1596 pub previous_definition: Span,
1597 pub name: Symbol,
1598 }
1599
1600 #[derive(Diagnostic)]
1603 #[diag(desugar_ambiguous_name, code = E0999)]
1604 #[note]
1605 pub(super) struct AmbiguousName {
1606 #[primary_span]
1607 #[label]
1608 span: Span,
1609 name: Symbol,
1610 #[label(desugar_first_candidate)]
1611 first: Span,
1612 #[label(desugar_second_candidate)]
1613 second: Option<Span>,
1614 }
1615
1616 impl AmbiguousName {
1617 pub(super) fn new(ambiguity: super::Ambiguity) -> Self {
1618 let super::Ambiguity { span, name, first, second } = ambiguity;
1619 Self { span, name, first, second: (first != second).then_some(second) }
1623 }
1624 }
1625
1626 #[derive(Diagnostic)]
1627 #[diag(desugar_duplicate_param, code = E0999)]
1628 pub(super) struct DuplicateParam {
1629 #[primary_span]
1630 #[label]
1631 pub span: Span,
1632 pub name: Symbol,
1633 #[label(desugar_first_use)]
1634 pub first_use: Span,
1635 }
1636}