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 {
502 let tcx = self.tcx();
503 let Some(assoc_item) = tcx.opt_associated_item(def_id) else { return false };
504 let Some(trait_id) = assoc_item.trait_container(tcx) else { return false };
505 assoc_item.name() == sym::call && tcx.is_lang_item(trait_id, LangItem::Fn)
506 }
507
508 pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + use<'tcx, 'genv> {
510 self.tcx().iter_local_def_id().filter(move |&local_def_id| {
511 self.maybe_extern_id(local_def_id).is_local() && !self.is_dummy(local_def_id)
512 })
513 }
514
515 pub fn iter_extern_def_id(self) -> impl Iterator<Item = DefId> + use<'tcx, 'genv> {
516 self.tcx()
517 .iter_local_def_id()
518 .filter_map(move |local_def_id| self.maybe_extern_id(local_def_id).as_extern())
519 }
520
521 pub fn maybe_extern_id(self, local_id: LocalDefId) -> MaybeExternId {
522 self.collect_specs()
523 .local_id_to_extern_id
524 .get(&local_id)
525 .map_or_else(
526 || MaybeExternId::Local(local_id),
527 |def_id| MaybeExternId::Extern(local_id, *def_id),
528 )
529 }
530
531 #[expect(clippy::disallowed_methods)]
532 pub fn resolve_id(self, def_id: DefId) -> ResolvedDefId {
533 let maybe_extern_spec = self
534 .collect_specs()
535 .extern_id_to_local_id
536 .get(&def_id)
537 .copied();
538 if let Some(local_id) = maybe_extern_spec {
539 ResolvedDefId::ExternSpec(local_id, def_id)
540 } else if let Some(local_id) = def_id.as_local() {
541 debug_assert!(
542 self.maybe_extern_id(local_id).is_local(),
543 "def id points to dummy local item `{def_id:?}`"
544 );
545 ResolvedDefId::Local(local_id)
546 } else {
547 ResolvedDefId::Extern(def_id)
548 }
549 }
550
551 pub fn infer_opts(self, def_id: LocalDefId) -> config::InferOpts {
552 let mut opts = config::PartialInferOpts::default();
553 self.traverse_parents(def_id, |did| {
554 if let Some(o) = self.fhir_attr_map(did).infer_opts() {
555 opts.merge(&o);
556 }
557 None::<!>
558 });
559 opts.into()
560 }
561
562 pub fn trusted(self, def_id: LocalDefId) -> bool {
566 self.traverse_parents(def_id, |did| self.fhir_attr_map(did).trusted())
567 .map(|trusted| trusted.to_bool())
568 .unwrap_or_else(config::trusted_default)
569 }
570
571 pub fn trusted_impl(self, def_id: LocalDefId) -> bool {
572 self.traverse_parents(def_id, |did| self.fhir_attr_map(did).trusted_impl())
573 .map(|trusted| trusted.to_bool())
574 .unwrap_or(false)
575 }
576
577 pub fn is_dummy(self, def_id: LocalDefId) -> bool {
581 self.traverse_parents(def_id, |did| {
582 self.collect_specs()
583 .dummy_extern
584 .contains(&did)
585 .then_some(())
586 })
587 .is_some()
588 }
589
590 pub fn ignored(self, def_id: LocalDefId) -> bool {
594 self.traverse_parents(def_id, |did| self.fhir_attr_map(did).ignored())
595 .map(|ignored| ignored.to_bool())
596 .unwrap_or_else(config::ignore_default)
597 }
598
599 pub fn should_fail(self, def_id: LocalDefId) -> bool {
601 self.fhir_attr_map(def_id).should_fail()
602 }
603
604 pub fn proven_externally(self, def_id: LocalDefId) -> Option<Span> {
606 self.fhir_attr_map(def_id).proven_externally()
607 }
608
609 fn traverse_parents<T>(
611 self,
612 mut def_id: LocalDefId,
613 mut f: impl FnMut(LocalDefId) -> Option<T>,
614 ) -> Option<T> {
615 loop {
616 if let Some(v) = f(def_id) {
617 break Some(v);
618 }
619
620 if let Some(parent) = self.tcx().opt_local_parent(def_id) {
621 def_id = parent;
622 } else {
623 break None;
624 }
625 }
626 }
627}
628
629impl<'genv, 'tcx> GlobalEnv<'genv, 'tcx> {
630 pub fn fhir_iter_flux_items(
631 self,
632 ) -> impl Iterator<Item = (FluxLocalDefId, fhir::FluxItem<'genv>)> {
633 self.fhir_crate()
634 .items
635 .iter()
636 .map(|(id, item)| (*id, *item))
637 }
638
639 pub fn fhir_sort_decl(&self, def_id: FluxLocalDefId) -> Option<&fhir::SortDecl> {
640 self.fhir_crate().items.get(&def_id).and_then(|item| {
641 if let fhir::FluxItem::SortDecl(sort_decl) = item { Some(*sort_decl) } else { None }
642 })
643 }
644
645 pub fn fhir_spec_func_body(
646 &self,
647 def_id: FluxLocalDefId,
648 ) -> Option<&'genv fhir::SpecFunc<'genv>> {
649 self.fhir_crate()
650 .items
651 .get(&def_id)
652 .and_then(|item| if let fhir::FluxItem::Func(defn) = item { Some(*defn) } else { None })
653 }
654
655 pub fn fhir_qualifiers(self) -> impl Iterator<Item = &'genv fhir::Qualifier<'genv>> {
656 self.fhir_crate().items.values().filter_map(|item| {
657 if let fhir::FluxItem::Qualifier(qual) = item { Some(*qual) } else { None }
658 })
659 }
660
661 pub fn fhir_primop_props(self) -> impl Iterator<Item = &'genv fhir::PrimOpProp<'genv>> {
662 self.fhir_crate().items.values().filter_map(|item| {
663 if let fhir::FluxItem::PrimOpProp(prop) = item { Some(*prop) } else { None }
664 })
665 }
666
667 pub fn fhir_get_generics(
668 self,
669 def_id: LocalDefId,
670 ) -> QueryResult<Option<&'genv fhir::Generics<'genv>>> {
671 if matches!(self.def_kind(def_id), DefKind::Closure) {
673 Ok(None)
674 } else {
675 Ok(Some(self.fhir_expect_owner_node(def_id)?.generics()))
676 }
677 }
678
679 pub fn fhir_expect_refinement_kind(
680 self,
681 def_id: LocalDefId,
682 ) -> QueryResult<&'genv fhir::RefinementKind<'genv>> {
683 let kind = match &self.fhir_expect_item(def_id)?.kind {
684 fhir::ItemKind::Enum(enum_def) => &enum_def.refinement,
685 fhir::ItemKind::Struct(struct_def) => &struct_def.refinement,
686 _ => bug!("expected struct, enum or type alias"),
687 };
688 Ok(kind)
689 }
690
691 pub fn fhir_expect_item(self, def_id: LocalDefId) -> QueryResult<&'genv fhir::Item<'genv>> {
692 if let fhir::Node::Item(item) = self.fhir_node(def_id)? {
693 Ok(item)
694 } else {
695 Err(query_bug!(def_id, "expected item: `{def_id:?}`"))
696 }
697 }
698
699 pub fn fhir_expect_owner_node(self, def_id: LocalDefId) -> QueryResult<fhir::OwnerNode<'genv>> {
700 let Some(owner) = self.fhir_node(def_id)?.as_owner() else {
701 return Err(query_bug!(def_id, "cannot find owner node"));
702 };
703 Ok(owner)
704 }
705
706 pub fn fhir_node(self, def_id: LocalDefId) -> QueryResult<fhir::Node<'genv>> {
707 self.desugar(def_id)
708 }
709}
710
711#[macro_export]
712macro_rules! try_alloc_slice {
713 ($genv:expr, $slice:expr, $map:expr $(,)?) => {{
714 let slice = $slice;
715 $crate::try_alloc_slice!($genv, cap: slice.len(), slice.into_iter().map($map))
716 }};
717 ($genv:expr, cap: $cap:expr, $it:expr $(,)?) => {{
718 let mut err = None;
719 let slice = $genv.alloc_slice_with_capacity($cap, $it.into_iter().collect_errors(&mut err));
720 err.map_or(Ok(slice), Err)
721 }};
722}
723
724impl ErrorEmitter for GlobalEnv<'_, '_> {
725 fn emit<'a>(&'a self, err: impl rustc_errors::Diagnostic<'a>) -> rustc_span::ErrorGuaranteed {
726 self.sess().emit(err)
727 }
728}
729
730fn lean_parent_dir(tcx: TyCtxt) -> PathBuf {
731 tcx.sess
732 .opts
733 .working_dir
734 .local_path_if_available()
735 .to_path_buf()
736 .join(config::lean_dir())
737}