1use std::{alloc, path::PathBuf, ptr, rc::Rc, slice};
2
3use flux_arc_interner::List;
4use flux_common::{bug, result::ErrorEmitter};
5use flux_config as config;
6use flux_errors::FluxSession;
7use flux_rustc_bridge::{self, lowering::Lower, mir, ty};
8use flux_syntax::symbols::sym;
9use rustc_data_structures::unord::UnordSet;
10use rustc_hir::{
11 LangItem,
12 def::DefKind,
13 def_id::{CrateNum, DefId, LocalDefId},
14};
15use rustc_middle::{
16 query::IntoQueryParam,
17 ty::{TyCtxt, Variance},
18};
19use rustc_span::Span;
20pub use rustc_span::{Symbol, symbol::Ident};
21use tempfile::TempDir;
22
23use crate::{
24 cstore::CrateStoreDyn,
25 def_id::{FluxDefId, FluxLocalDefId, MaybeExternId, ResolvedDefId},
26 fhir::{self, VariantIdx},
27 queries::{DispatchKey, Providers, Queries, QueryErr, QueryResult},
28 query_bug,
29 rty::{
30 self, QualifierKind,
31 refining::{Refine as _, Refiner},
32 },
33};
34
35#[derive(Clone, Copy)]
36pub struct GlobalEnv<'genv, 'tcx> {
37 inner: &'genv GlobalEnvInner<'genv, 'tcx>,
38}
39
40struct GlobalEnvInner<'genv, 'tcx> {
41 tcx: TyCtxt<'tcx>,
42 sess: &'genv FluxSession,
43 arena: &'genv fhir::Arena,
44 cstore: Box<CrateStoreDyn>,
45 queries: Queries<'genv, 'tcx>,
46 tempdir: TempDir,
47}
48
49impl<'tcx> GlobalEnv<'_, 'tcx> {
50 pub fn enter<'a, R>(
51 tcx: TyCtxt<'tcx>,
52 sess: &'a FluxSession,
53 cstore: Box<CrateStoreDyn>,
54 arena: &'a fhir::Arena,
55 providers: Providers,
56 f: impl for<'genv> FnOnce(GlobalEnv<'genv, 'tcx>) -> R,
57 ) -> R {
58 let tempdir = TempDir::new_in(lean_parent_dir(tcx)).unwrap();
61 let queries = Queries::new(providers);
62 let inner = GlobalEnvInner { tcx, sess, cstore, arena, queries, tempdir };
63 f(GlobalEnv { inner: &inner })
64 }
65}
66
67impl<'genv, 'tcx> GlobalEnv<'genv, 'tcx> {
68 pub fn queried(self, def_id: DefId) -> bool {
69 self.inner.queries.queried(def_id)
70 }
71
72 pub fn run_query_if_reached<K: DispatchKey, R>(
78 self,
79 key: K,
80 query: impl FnOnce(Self, K) -> QueryResult<R>,
81 ) -> QueryResult<R> {
82 if !self.inner.queries.queried(key.def_id()) {
83 return Err(QueryErr::NotIncluded { def_id: key.def_id() });
84 }
85
86 query(self, key)
87 }
88
89 pub fn tcx(self) -> TyCtxt<'tcx> {
90 self.inner.tcx
91 }
92
93 pub fn sess(self) -> &'genv FluxSession {
94 self.inner.sess
95 }
96
97 pub fn collect_specs(self) -> &'genv crate::Specs {
98 self.inner.queries.collect_specs(self)
99 }
100
101 pub fn resolve_crate(self) -> &'genv crate::ResolverOutput {
102 self.inner.queries.resolve_crate(self)
103 }
104
105 pub fn lean_parent_dir(self) -> PathBuf {
107 lean_parent_dir(self.tcx())
108 }
109
110 pub fn temp_dir(self) -> &'genv TempDir {
111 &self.inner.tempdir
112 }
113
114 pub fn desugar(self, def_id: LocalDefId) -> QueryResult<fhir::Node<'genv>> {
115 self.inner.queries.desugar(self, def_id)
116 }
117
118 pub fn fhir_attr_map(self, def_id: LocalDefId) -> fhir::AttrMap<'genv> {
119 self.inner.queries.fhir_attr_map(self, def_id)
120 }
121
122 pub fn fhir_crate(self) -> &'genv fhir::FluxItems<'genv> {
123 self.inner.queries.fhir_crate(self)
124 }
125
126 pub fn alloc<T>(&self, val: T) -> &'genv T {
127 self.inner.arena.alloc(val)
128 }
129
130 pub fn alloc_slice<T: Copy>(self, slice: &[T]) -> &'genv [T] {
131 self.inner.arena.alloc_slice_copy(slice)
132 }
133
134 pub fn alloc_slice_fill_iter<T, I>(self, it: I) -> &'genv [T]
135 where
136 I: IntoIterator<Item = T>,
137 I::IntoIter: ExactSizeIterator,
138 {
139 self.inner.arena.alloc_slice_fill_iter(it)
140 }
141
142 pub fn def_kind(&self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
143 self.tcx().def_kind(def_id.into_query_param())
144 }
145
146 pub fn alloc_slice_with_capacity<T, I>(self, cap: usize, it: I) -> &'genv [T]
156 where
157 I: IntoIterator<Item = T>,
158 {
159 let layout = alloc::Layout::array::<T>(cap).unwrap_or_else(|_| bug!("out of memory"));
160 let dst = self.inner.arena.alloc_layout(layout).cast::<T>();
161 unsafe {
162 let mut len = 0;
163 for (i, v) in it.into_iter().take(cap).enumerate() {
164 len += 1;
165 ptr::write(dst.as_ptr().add(i), v);
166 }
167
168 slice::from_raw_parts(dst.as_ptr(), len)
169 }
170 }
171
172 pub fn inlined_body(self, did: FluxDefId) -> rty::Binder<rty::Expr> {
173 self.normalized_defns(did.krate()).inlined_body(did)
174 }
175
176 pub fn normalized_info(self, did: FluxDefId) -> rty::FuncInfo {
177 self.normalized_defns(did.krate()).func_info(did).clone()
178 }
179
180 pub fn normalized_defns(self, krate: CrateNum) -> Rc<rty::NormalizedDefns> {
181 self.inner.queries.normalized_defns(self, krate)
182 }
183
184 pub fn prim_rel_for(self, op: &rty::BinOp) -> QueryResult<Option<&'genv rty::PrimRel>> {
185 Ok(self.inner.queries.prim_rel(self)?.get(op))
186 }
187
188 pub fn qualifiers(self) -> QueryResult<&'genv [rty::Qualifier]> {
189 self.inner.queries.qualifiers(self)
190 }
191
192 pub fn qualifiers_for(
194 self,
195 did: LocalDefId,
196 ) -> QueryResult<impl Iterator<Item = &'genv rty::Qualifier>> {
197 let quals = self.fhir_attr_map(did).qualifiers;
198 let names: UnordSet<_> = quals.iter().copied().collect();
199 Ok(self.qualifiers()?.iter().filter(move |qual| {
200 match qual.kind {
201 QualifierKind::Global => true,
202 QualifierKind::Hint => qual.def_id.parent() == did,
203 QualifierKind::Local => names.contains(&qual.def_id),
204 }
205 }))
206 }
207
208 pub fn reveals_for(self, did: LocalDefId) -> &'genv [FluxDefId] {
210 self.fhir_attr_map(did).reveals
211 }
212
213 pub fn func_sort(self, def_id: impl IntoQueryParam<FluxDefId>) -> rty::PolyFuncSort {
214 self.inner
215 .queries
216 .func_sort(self, def_id.into_query_param())
217 }
218
219 pub fn func_span(self, def_id: impl IntoQueryParam<FluxDefId>) -> Span {
220 self.inner
221 .queries
222 .func_span(self, def_id.into_query_param())
223 }
224
225 pub fn should_inline_fun(self, def_id: FluxDefId) -> bool {
226 let is_poly = self.func_sort(def_id).params().len() > 0;
227 is_poly || !flux_config::smt_define_fun()
228 }
229
230 pub fn variances_of(self, did: DefId) -> &'tcx [Variance] {
231 self.tcx().variances_of(did)
232 }
233
234 pub fn mir(self, def_id: LocalDefId) -> QueryResult<Rc<mir::BodyRoot<'tcx>>> {
235 self.inner.queries.mir(self, def_id)
236 }
237
238 pub fn lower_generics_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::Generics<'tcx> {
239 self.inner
240 .queries
241 .lower_generics_of(self, def_id.into_query_param())
242 }
243
244 pub fn lower_predicates_of(
245 self,
246 def_id: impl IntoQueryParam<DefId>,
247 ) -> QueryResult<ty::GenericPredicates> {
248 self.inner
249 .queries
250 .lower_predicates_of(self, def_id.into_query_param())
251 }
252
253 pub fn lower_type_of(
254 self,
255 def_id: impl IntoQueryParam<DefId>,
256 ) -> QueryResult<ty::EarlyBinder<ty::Ty>> {
257 self.inner
258 .queries
259 .lower_type_of(self, def_id.into_query_param())
260 }
261
262 pub fn lower_fn_sig(
263 self,
264 def_id: impl Into<DefId>,
265 ) -> QueryResult<ty::EarlyBinder<ty::PolyFnSig>> {
266 self.inner.queries.lower_fn_sig(self, def_id.into())
267 }
268
269 pub fn adt_def(self, def_id: impl IntoQueryParam<DefId>) -> QueryResult<rty::AdtDef> {
270 self.inner.queries.adt_def(self, def_id.into_query_param())
271 }
272
273 pub fn constant_info(
274 self,
275 def_id: impl IntoQueryParam<DefId>,
276 ) -> QueryResult<rty::ConstantInfo> {
277 self.inner
278 .queries
279 .constant_info(self, def_id.into_query_param())
280 }
281
282 pub fn static_info(self, def_id: impl IntoQueryParam<DefId>) -> QueryResult<rty::StaticInfo> {
283 self.inner
284 .queries
285 .static_info(self, def_id.into_query_param())
286 }
287
288 pub fn adt_sort_def_of(
289 self,
290 def_id: impl IntoQueryParam<DefId>,
291 ) -> QueryResult<rty::AdtSortDef> {
292 self.inner
293 .queries
294 .adt_sort_def_of(self, def_id.into_query_param())
295 }
296
297 pub fn sort_decl_param_count(self, def_id: impl IntoQueryParam<FluxDefId>) -> usize {
298 self.inner
299 .queries
300 .sort_decl_param_count(self, def_id.into_query_param())
301 }
302
303 pub fn check_wf(self, def_id: LocalDefId) -> QueryResult<Rc<rty::WfckResults>> {
304 self.inner.queries.check_wf(self, def_id)
305 }
306
307 pub fn impl_trait_ref(self, impl_id: DefId) -> QueryResult<rty::EarlyBinder<rty::TraitRef>> {
308 let trait_ref = self.tcx().impl_trait_ref(impl_id);
309 let trait_ref = trait_ref.skip_binder();
310 let trait_ref = trait_ref
311 .lower(self.tcx())
312 .map_err(|err| QueryErr::unsupported(impl_id, err.into_err()))?
313 .refine(&Refiner::default_for_item(self, impl_id)?)?;
314 Ok(rty::EarlyBinder(trait_ref))
315 }
316
317 pub fn generics_of(self, def_id: impl IntoQueryParam<DefId>) -> QueryResult<rty::Generics> {
318 self.inner
319 .queries
320 .generics_of(self, def_id.into_query_param())
321 }
322
323 pub fn refinement_generics_of(
324 self,
325 def_id: impl IntoQueryParam<DefId>,
326 ) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>> {
327 self.inner
328 .queries
329 .refinement_generics_of(self, def_id.into_query_param())
330 }
331
332 pub fn predicates_of(
333 self,
334 def_id: impl IntoQueryParam<DefId>,
335 ) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
336 self.inner
337 .queries
338 .predicates_of(self, def_id.into_query_param())
339 }
340
341 pub fn assoc_refinements_of(
342 self,
343 def_id: impl IntoQueryParam<DefId>,
344 ) -> QueryResult<rty::AssocRefinements> {
345 self.inner
346 .queries
347 .assoc_refinements_of(self, def_id.into_query_param())
348 }
349
350 pub fn assoc_refinement(self, assoc_id: FluxDefId) -> QueryResult<rty::AssocReft> {
351 Ok(self.assoc_refinements_of(assoc_id.parent())?.get(assoc_id))
352 }
353
354 pub fn assoc_refinement_body_for_impl(
362 self,
363 trait_assoc_id: FluxDefId,
364 impl_id: DefId,
365 ) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
366 let impl_assoc_refts = self.assoc_refinements_of(impl_id)?;
368 if let Some(impl_assoc_reft) = impl_assoc_refts.find(trait_assoc_id.name()) {
369 return self.assoc_refinement_body(impl_assoc_reft.def_id());
370 }
371
372 if let Some(body) = self.default_assoc_refinement_body(trait_assoc_id)? {
374 let impl_trait_ref = self.impl_trait_ref(impl_id)?.instantiate_identity();
375 return Ok(rty::EarlyBinder(body.instantiate(self.tcx(), &impl_trait_ref.args, &[])));
376 }
377
378 Err(QueryErr::MissingAssocReft {
379 impl_id,
380 trait_id: trait_assoc_id.parent(),
381 name: trait_assoc_id.name(),
382 })
383 }
384
385 pub fn default_assoc_refinement_body(
386 self,
387 trait_assoc_id: FluxDefId,
388 ) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>> {
389 self.inner
390 .queries
391 .default_assoc_refinement_body(self, trait_assoc_id)
392 }
393
394 pub fn assoc_refinement_body(
395 self,
396 impl_assoc_id: FluxDefId,
397 ) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
398 self.inner
399 .queries
400 .assoc_refinement_body(self, impl_assoc_id)
401 }
402
403 pub fn sort_of_assoc_reft(
404 self,
405 assoc_id: FluxDefId,
406 ) -> QueryResult<rty::EarlyBinder<rty::FuncSort>> {
407 self.inner.queries.sort_of_assoc_reft(self, assoc_id)
408 }
409
410 pub fn item_bounds(
411 self,
412 def_id: impl IntoQueryParam<DefId>,
413 ) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>> {
414 self.inner
415 .queries
416 .item_bounds(self, def_id.into_query_param())
417 }
418
419 pub fn type_of(
420 self,
421 def_id: impl IntoQueryParam<DefId>,
422 ) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>> {
423 self.inner.queries.type_of(self, def_id.into_query_param())
424 }
425
426 pub fn fn_sig(
427 self,
428 def_id: impl IntoQueryParam<DefId>,
429 ) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>> {
430 self.inner.queries.fn_sig(self, def_id.into_query_param())
431 }
432
433 pub fn variants_of(
434 self,
435 def_id: impl IntoQueryParam<DefId>,
436 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>> {
437 self.inner
438 .queries
439 .variants_of(self, def_id.into_query_param())
440 }
441
442 pub fn variant_sig(
443 self,
444 def_id: DefId,
445 variant_idx: VariantIdx,
446 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariant>>> {
447 Ok(self
448 .variants_of(def_id)?
449 .map(|variants| variants.map(|variants| variants[variant_idx.as_usize()].clone())))
450 }
451
452 pub fn lower_late_bound_vars(
453 self,
454 def_id: LocalDefId,
455 ) -> QueryResult<List<ty::BoundVariableKind>> {
456 self.inner.queries.lower_late_bound_vars(self, def_id)
457 }
458
459 pub fn no_panic(self, def_id: impl IntoQueryParam<DefId>) -> bool {
461 self.inner.queries.no_panic(self, def_id.into_query_param())
462 }
463
464 pub fn is_box(&self, res: fhir::Res) -> bool {
465 res.is_box(self.tcx())
466 }
467
468 pub fn def_id_to_param_index(&self, def_id: DefId) -> u32 {
469 let parent = self.tcx().parent(def_id);
470 let generics = self.tcx().generics_of(parent);
471 generics.param_def_id_to_index(self.tcx(), def_id).unwrap()
472 }
473
474 pub(crate) fn cstore(self) -> &'genv CrateStoreDyn {
475 &*self.inner.cstore
476 }
477
478 pub fn has_trusted_impl(&self, def_id: DefId) -> bool {
479 if let Some(did) = self
480 .resolve_id(def_id)
481 .as_maybe_extern()
482 .map(|id| id.local_id())
483 {
484 self.trusted_impl(did)
485 } else {
486 false
487 }
488 }
489
490 pub fn is_fn_output(&self, def_id: DefId) -> bool {
494 let def_span = self.tcx().def_span(def_id);
495 self.tcx()
496 .require_lang_item(LangItem::FnOnceOutput, def_span)
497 == def_id
498 }
499
500 pub fn is_fn_call(&self, def_id: DefId) -> bool {
504 let methods_and_names = [
505 (LangItem::Fn, sym::call),
506 (LangItem::FnMut, sym::call_mut),
507 (LangItem::FnOnce, sym::call_once),
508 ];
509 let tcx = self.tcx();
510 let Some(assoc_item) = tcx.opt_associated_item(def_id) else { return false };
511 let Some(trait_id) = assoc_item.trait_container(tcx) else { return false };
512
513 methods_and_names.iter().any(|(lang_item, method_name)| {
514 assoc_item.name() == *method_name && tcx.is_lang_item(trait_id, *lang_item)
515 })
516 }
517
518 pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + use<'tcx, 'genv> {
520 self.tcx().iter_local_def_id().filter(move |&local_def_id| {
521 self.maybe_extern_id(local_def_id).is_local() && !self.is_dummy(local_def_id)
522 })
523 }
524
525 pub fn iter_extern_def_id(self) -> impl Iterator<Item = DefId> + use<'tcx, 'genv> {
526 self.tcx()
527 .iter_local_def_id()
528 .filter_map(move |local_def_id| self.maybe_extern_id(local_def_id).as_extern())
529 }
530
531 pub fn maybe_extern_id(self, local_id: LocalDefId) -> MaybeExternId {
532 self.collect_specs()
533 .local_id_to_extern_id
534 .get(&local_id)
535 .map_or_else(
536 || MaybeExternId::Local(local_id),
537 |def_id| MaybeExternId::Extern(local_id, *def_id),
538 )
539 }
540
541 #[expect(clippy::disallowed_methods)]
542 pub fn resolve_id(self, def_id: DefId) -> ResolvedDefId {
543 let maybe_extern_spec = self
544 .collect_specs()
545 .extern_id_to_local_id
546 .get(&def_id)
547 .copied();
548 if let Some(local_id) = maybe_extern_spec {
549 ResolvedDefId::ExternSpec(local_id, def_id)
550 } else if let Some(local_id) = def_id.as_local() {
551 debug_assert!(
552 self.maybe_extern_id(local_id).is_local(),
553 "def id points to dummy local item `{def_id:?}`"
554 );
555 ResolvedDefId::Local(local_id)
556 } else {
557 ResolvedDefId::Extern(def_id)
558 }
559 }
560
561 pub fn infer_opts(self, def_id: LocalDefId) -> config::InferOpts {
562 let mut opts = config::PartialInferOpts::default();
563 self.traverse_parents(def_id, |did| {
564 if let Some(o) = self.fhir_attr_map(did).infer_opts() {
565 opts.merge(&o);
566 }
567 None::<!>
568 });
569 opts.into()
570 }
571
572 pub fn trusted(self, def_id: LocalDefId) -> bool {
576 self.traverse_parents(def_id, |did| self.fhir_attr_map(did).trusted())
577 .map(|trusted| trusted.to_bool())
578 .unwrap_or_else(config::trusted_default)
579 }
580
581 pub fn trusted_impl(self, def_id: LocalDefId) -> bool {
582 self.traverse_parents(def_id, |did| self.fhir_attr_map(did).trusted_impl())
583 .map(|trusted| trusted.to_bool())
584 .unwrap_or(false)
585 }
586
587 pub fn is_dummy(self, def_id: LocalDefId) -> bool {
591 self.traverse_parents(def_id, |did| {
592 self.collect_specs()
593 .dummy_extern
594 .contains(&did)
595 .then_some(())
596 })
597 .is_some()
598 }
599
600 pub fn ignored(self, def_id: LocalDefId) -> bool {
604 self.traverse_parents(def_id, |did| self.fhir_attr_map(did).ignored())
605 .map(|ignored| ignored.to_bool())
606 .unwrap_or_else(config::ignore_default)
607 }
608
609 pub fn should_fail(self, def_id: LocalDefId) -> bool {
611 self.fhir_attr_map(def_id).should_fail()
612 }
613
614 pub fn proven_externally(self, def_id: LocalDefId) -> Option<Span> {
616 self.fhir_attr_map(def_id).proven_externally()
617 }
618
619 fn traverse_parents<T>(
621 self,
622 mut def_id: LocalDefId,
623 mut f: impl FnMut(LocalDefId) -> Option<T>,
624 ) -> Option<T> {
625 loop {
626 if let Some(v) = f(def_id) {
627 break Some(v);
628 }
629
630 if let Some(parent) = self.tcx().opt_local_parent(def_id) {
631 def_id = parent;
632 } else {
633 break None;
634 }
635 }
636 }
637}
638
639impl<'genv, 'tcx> GlobalEnv<'genv, 'tcx> {
640 pub fn fhir_iter_flux_items(
641 self,
642 ) -> impl Iterator<Item = (FluxLocalDefId, fhir::FluxItem<'genv>)> {
643 self.fhir_crate()
644 .items
645 .iter()
646 .map(|(id, item)| (*id, *item))
647 }
648
649 pub fn fhir_sort_decl(&self, def_id: FluxLocalDefId) -> Option<&fhir::SortDecl> {
650 self.fhir_crate().items.get(&def_id).and_then(|item| {
651 if let fhir::FluxItem::SortDecl(sort_decl) = item { Some(*sort_decl) } else { None }
652 })
653 }
654
655 pub fn fhir_spec_func_body(
656 &self,
657 def_id: FluxLocalDefId,
658 ) -> Option<&'genv fhir::SpecFunc<'genv>> {
659 self.fhir_crate()
660 .items
661 .get(&def_id)
662 .and_then(|item| if let fhir::FluxItem::Func(defn) = item { Some(*defn) } else { None })
663 }
664
665 pub fn fhir_qualifiers(self) -> impl Iterator<Item = &'genv fhir::Qualifier<'genv>> {
666 self.fhir_crate().items.values().filter_map(|item| {
667 if let fhir::FluxItem::Qualifier(qual) = item { Some(*qual) } else { None }
668 })
669 }
670
671 pub fn fhir_primop_props(self) -> impl Iterator<Item = &'genv fhir::PrimOpProp<'genv>> {
672 self.fhir_crate().items.values().filter_map(|item| {
673 if let fhir::FluxItem::PrimOpProp(prop) = item { Some(*prop) } else { None }
674 })
675 }
676
677 pub fn fhir_get_generics(
678 self,
679 def_id: LocalDefId,
680 ) -> QueryResult<Option<&'genv fhir::Generics<'genv>>> {
681 if matches!(self.def_kind(def_id), DefKind::Closure) {
683 Ok(None)
684 } else {
685 Ok(Some(self.fhir_expect_owner_node(def_id)?.generics()))
686 }
687 }
688
689 pub fn fhir_expect_refinement_kind(
690 self,
691 def_id: LocalDefId,
692 ) -> QueryResult<&'genv fhir::RefinementKind<'genv>> {
693 let kind = match &self.fhir_expect_item(def_id)?.kind {
694 fhir::ItemKind::Enum(enum_def) => &enum_def.refinement,
695 fhir::ItemKind::Struct(struct_def) => &struct_def.refinement,
696 _ => bug!("expected struct, enum or type alias"),
697 };
698 Ok(kind)
699 }
700
701 pub fn fhir_expect_item(self, def_id: LocalDefId) -> QueryResult<&'genv fhir::Item<'genv>> {
702 if let fhir::Node::Item(item) = self.fhir_node(def_id)? {
703 Ok(item)
704 } else {
705 Err(query_bug!(def_id, "expected item: `{def_id:?}`"))
706 }
707 }
708
709 pub fn fhir_expect_owner_node(self, def_id: LocalDefId) -> QueryResult<fhir::OwnerNode<'genv>> {
710 let Some(owner) = self.fhir_node(def_id)?.as_owner() else {
711 return Err(query_bug!(def_id, "cannot find owner node"));
712 };
713 Ok(owner)
714 }
715
716 pub fn fhir_node(self, def_id: LocalDefId) -> QueryResult<fhir::Node<'genv>> {
717 self.desugar(def_id)
718 }
719}
720
721#[macro_export]
722macro_rules! try_alloc_slice {
723 ($genv:expr, $slice:expr, $map:expr $(,)?) => {{
724 let slice = $slice;
725 $crate::try_alloc_slice!($genv, cap: slice.len(), slice.into_iter().map($map))
726 }};
727 ($genv:expr, cap: $cap:expr, $it:expr $(,)?) => {{
728 let mut err = None;
729 let slice = $genv.alloc_slice_with_capacity($cap, $it.into_iter().collect_errors(&mut err));
730 err.map_or(Ok(slice), Err)
731 }};
732}
733
734impl ErrorEmitter for GlobalEnv<'_, '_> {
735 fn emit<'a>(&'a self, err: impl rustc_errors::Diagnostic<'a>) -> rustc_span::ErrorGuaranteed {
736 self.sess().emit(err)
737 }
738}
739
740fn lean_parent_dir(tcx: TyCtxt) -> PathBuf {
741 tcx.sess
742 .opts
743 .working_dir
744 .local_path_if_available()
745 .to_path_buf()
746 .join(config::lean_dir())
747}