flux_middle/
global_env.rs

1use std::{alloc, 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 rustc_data_structures::unord::UnordSet;
9use rustc_hir::{
10    def::DefKind,
11    def_id::{CrateNum, DefId, LocalDefId},
12};
13use rustc_middle::{
14    query::IntoQueryParam,
15    ty::{TyCtxt, Variance},
16};
17use rustc_span::Span;
18pub use rustc_span::{Symbol, symbol::Ident};
19
20use crate::{
21    cstore::CrateStoreDyn,
22    def_id::{FluxDefId, FluxLocalDefId, MaybeExternId, ResolvedDefId},
23    fhir::{self, VariantIdx},
24    queries::{Providers, Queries, QueryErr, QueryResult},
25    query_bug,
26    rty::{
27        self,
28        refining::{Refine as _, Refiner},
29    },
30};
31
32#[derive(Clone, Copy)]
33pub struct GlobalEnv<'genv, 'tcx> {
34    inner: &'genv GlobalEnvInner<'genv, 'tcx>,
35}
36
37struct GlobalEnvInner<'genv, 'tcx> {
38    tcx: TyCtxt<'tcx>,
39    sess: &'genv FluxSession,
40    arena: &'genv fhir::Arena,
41    cstore: Box<CrateStoreDyn>,
42    queries: Queries<'genv, 'tcx>,
43}
44
45impl<'tcx> GlobalEnv<'_, 'tcx> {
46    pub fn enter<'a, R>(
47        tcx: TyCtxt<'tcx>,
48        sess: &'a FluxSession,
49        cstore: Box<CrateStoreDyn>,
50        arena: &'a fhir::Arena,
51        providers: Providers,
52        f: impl for<'genv> FnOnce(GlobalEnv<'genv, 'tcx>) -> R,
53    ) -> R {
54        let inner = GlobalEnvInner { tcx, sess, cstore, arena, queries: Queries::new(providers) };
55        f(GlobalEnv { inner: &inner })
56    }
57}
58
59impl<'genv, 'tcx> GlobalEnv<'genv, 'tcx> {
60    pub fn tcx(self) -> TyCtxt<'tcx> {
61        self.inner.tcx
62    }
63
64    pub fn sess(self) -> &'genv FluxSession {
65        self.inner.sess
66    }
67
68    pub fn collect_specs(self) -> &'genv crate::Specs {
69        self.inner.queries.collect_specs(self)
70    }
71
72    pub fn resolve_crate(self) -> &'genv crate::ResolverOutput {
73        self.inner.queries.resolve_crate(self)
74    }
75
76    pub fn desugar(self, def_id: LocalDefId) -> QueryResult<fhir::Node<'genv>> {
77        self.inner.queries.desugar(self, def_id)
78    }
79
80    pub fn fhir_crate(self) -> &'genv fhir::FluxItems<'genv> {
81        self.inner.queries.fhir_crate(self)
82    }
83
84    pub fn alloc<T>(&self, val: T) -> &'genv T {
85        self.inner.arena.alloc(val)
86    }
87
88    pub fn alloc_slice<T: Copy>(self, slice: &[T]) -> &'genv [T] {
89        self.inner.arena.alloc_slice_copy(slice)
90    }
91
92    pub fn alloc_slice_fill_iter<T, I>(self, it: I) -> &'genv [T]
93    where
94        I: IntoIterator<Item = T>,
95        I::IntoIter: ExactSizeIterator,
96    {
97        self.inner.arena.alloc_slice_fill_iter(it)
98    }
99
100    pub fn def_kind(&self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
101        self.tcx().def_kind(def_id.into_query_param())
102    }
103
104    /// Allocates space to store `cap` elements of type `T`.
105    ///
106    /// The elements are initialized using the supplied iterator. At most `cap` elements will be
107    /// retrieved from the iterator. If the iterator yields fewer than `cap` elements, the returned
108    /// slice will be of length less than the allocated capacity.
109    ///
110    /// ## Panics
111    ///
112    /// Panics if reserving space for the slice fails.
113    pub fn alloc_slice_with_capacity<T, I>(self, cap: usize, it: I) -> &'genv [T]
114    where
115        I: IntoIterator<Item = T>,
116    {
117        let layout = alloc::Layout::array::<T>(cap).unwrap_or_else(|_| bug!("out of memory"));
118        let dst = self.inner.arena.alloc_layout(layout).cast::<T>();
119        unsafe {
120            let mut len = 0;
121            for (i, v) in it.into_iter().take(cap).enumerate() {
122                len += 1;
123                ptr::write(dst.as_ptr().add(i), v);
124            }
125
126            slice::from_raw_parts(dst.as_ptr(), len)
127        }
128    }
129
130    pub fn normalized_info(self, did: FluxDefId) -> rty::NormalizeInfo {
131        self.normalized_defns(did.krate()).func_info(did).clone()
132    }
133
134    pub fn normalized_defns(self, krate: CrateNum) -> Rc<rty::NormalizedDefns> {
135        self.inner.queries.normalized_defns(self, krate)
136    }
137
138    pub fn prim_rel_for(self, op: &rty::BinOp) -> QueryResult<Option<&'genv rty::PrimRel>> {
139        Ok(self.inner.queries.prim_rel(self)?.get(op))
140    }
141
142    pub fn qualifiers(self) -> QueryResult<&'genv [rty::Qualifier]> {
143        self.inner.queries.qualifiers(self)
144    }
145
146    /// Return all the qualifiers that apply to an item, including both global and local qualifiers.
147    pub fn qualifiers_for(
148        self,
149        did: LocalDefId,
150    ) -> QueryResult<impl Iterator<Item = &'genv rty::Qualifier>> {
151        let quals = if let Some(fn_sig) = self.fhir_expect_owner_node(did)?.fn_sig() {
152            fn_sig.qualifiers
153        } else {
154            &[]
155        };
156        let names: UnordSet<_> = quals.iter().copied().collect();
157        Ok(self
158            .qualifiers()?
159            .iter()
160            .filter(move |qual| qual.global || names.contains(&qual.def_id)))
161    }
162
163    /// Return the list of flux function definitions that should be revelaed for item
164    pub fn reveals_for(self, did: LocalDefId) -> QueryResult<impl Iterator<Item = FluxDefId>> {
165        let reveals = if let Some(fn_sig) = self.fhir_expect_owner_node(did)?.fn_sig() {
166            fn_sig.reveals
167        } else {
168            &[]
169        };
170        Ok(reveals.iter().copied())
171    }
172
173    pub fn func_sort(self, def_id: impl IntoQueryParam<FluxDefId>) -> rty::PolyFuncSort {
174        self.inner
175            .queries
176            .func_sort(self, def_id.into_query_param())
177    }
178
179    pub fn func_span(self, def_id: impl IntoQueryParam<FluxDefId>) -> Span {
180        self.inner
181            .queries
182            .func_span(self, def_id.into_query_param())
183    }
184
185    pub fn should_inline_fun(self, def_id: FluxDefId) -> bool {
186        let is_poly = self.func_sort(def_id).params().len() > 0;
187        is_poly || !flux_config::smt_define_fun()
188    }
189
190    pub fn variances_of(self, did: DefId) -> &'tcx [Variance] {
191        self.tcx().variances_of(did)
192    }
193
194    pub fn mir(self, def_id: LocalDefId) -> QueryResult<Rc<mir::Body<'tcx>>> {
195        self.inner.queries.mir(self, def_id)
196    }
197
198    pub fn lower_generics_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::Generics<'tcx> {
199        self.inner
200            .queries
201            .lower_generics_of(self, def_id.into_query_param())
202    }
203
204    pub fn lower_predicates_of(
205        self,
206        def_id: impl IntoQueryParam<DefId>,
207    ) -> QueryResult<ty::GenericPredicates> {
208        self.inner
209            .queries
210            .lower_predicates_of(self, def_id.into_query_param())
211    }
212
213    pub fn lower_type_of(
214        self,
215        def_id: impl IntoQueryParam<DefId>,
216    ) -> QueryResult<ty::EarlyBinder<ty::Ty>> {
217        self.inner
218            .queries
219            .lower_type_of(self, def_id.into_query_param())
220    }
221
222    pub fn lower_fn_sig(
223        self,
224        def_id: impl Into<DefId>,
225    ) -> QueryResult<ty::EarlyBinder<ty::PolyFnSig>> {
226        self.inner.queries.lower_fn_sig(self, def_id.into())
227    }
228
229    pub fn adt_def(self, def_id: impl IntoQueryParam<DefId>) -> QueryResult<rty::AdtDef> {
230        self.inner.queries.adt_def(self, def_id.into_query_param())
231    }
232
233    pub fn constant_info(
234        self,
235        def_id: impl IntoQueryParam<DefId>,
236    ) -> QueryResult<rty::ConstantInfo> {
237        self.inner
238            .queries
239            .constant_info(self, def_id.into_query_param())
240    }
241
242    pub fn adt_sort_def_of(
243        self,
244        def_id: impl IntoQueryParam<DefId>,
245    ) -> QueryResult<rty::AdtSortDef> {
246        self.inner
247            .queries
248            .adt_sort_def_of(self, def_id.into_query_param())
249    }
250
251    pub fn check_wf(self, def_id: LocalDefId) -> QueryResult<Rc<rty::WfckResults>> {
252        self.inner.queries.check_wf(self, def_id)
253    }
254
255    pub fn impl_trait_ref(
256        self,
257        impl_id: DefId,
258    ) -> QueryResult<Option<rty::EarlyBinder<rty::TraitRef>>> {
259        let Some(trait_ref) = self.tcx().impl_trait_ref(impl_id) else { return Ok(None) };
260        let trait_ref = trait_ref.skip_binder();
261        let trait_ref = trait_ref
262            .lower(self.tcx())
263            .map_err(|err| QueryErr::unsupported(trait_ref.def_id, err.into_err()))?
264            .refine(&Refiner::default_for_item(self, impl_id)?)?;
265        Ok(Some(rty::EarlyBinder(trait_ref)))
266    }
267
268    pub fn generics_of(self, def_id: impl IntoQueryParam<DefId>) -> QueryResult<rty::Generics> {
269        self.inner
270            .queries
271            .generics_of(self, def_id.into_query_param())
272    }
273
274    pub fn refinement_generics_of(
275        self,
276        def_id: impl IntoQueryParam<DefId>,
277    ) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>> {
278        self.inner
279            .queries
280            .refinement_generics_of(self, def_id.into_query_param())
281    }
282
283    pub fn predicates_of(
284        self,
285        def_id: impl IntoQueryParam<DefId>,
286    ) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
287        self.inner
288            .queries
289            .predicates_of(self, def_id.into_query_param())
290    }
291
292    pub fn assoc_refinements_of(
293        self,
294        def_id: impl IntoQueryParam<DefId>,
295    ) -> QueryResult<rty::AssocRefinements> {
296        self.inner
297            .queries
298            .assoc_refinements_of(self, def_id.into_query_param())
299    }
300
301    pub fn assoc_refinement(self, assoc_id: FluxDefId) -> QueryResult<rty::AssocReft> {
302        Ok(self.assoc_refinements_of(assoc_id.parent())?.get(assoc_id))
303    }
304
305    /// Given the id of an associated refinement in a trait definition returns the body for the
306    /// corresponding associated refinement in the implementation with id `impl_id`.
307    ///
308    /// This function returns [`QueryErr::MissingAssocReft`] if the associated refinement is not
309    /// found in the implementation and there's no default body in the trait. This can happen if an
310    /// extern spec adds an associated refinement without a default body because we are currently
311    /// not checking `compare_impl_item` for those definitions.
312    pub fn assoc_refinement_body_for_impl(
313        self,
314        trait_assoc_id: FluxDefId,
315        impl_id: DefId,
316    ) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
317        // Check if the implementation has the associated refinement
318        let impl_assoc_refts = self.assoc_refinements_of(impl_id)?;
319        if let Some(impl_assoc_reft) = impl_assoc_refts.find(trait_assoc_id.name()) {
320            return self.assoc_refinement_body(impl_assoc_reft.def_id());
321        }
322
323        // Otherwise, check if the trait has a default body
324        if let Some(body) = self.default_assoc_refinement_body(trait_assoc_id)? {
325            let impl_trait_ref = self
326                .impl_trait_ref(impl_id)?
327                .unwrap()
328                .instantiate_identity();
329            return Ok(rty::EarlyBinder(body.instantiate(self.tcx(), &impl_trait_ref.args, &[])));
330        }
331
332        Err(QueryErr::MissingAssocReft {
333            impl_id,
334            trait_id: trait_assoc_id.parent(),
335            name: trait_assoc_id.name(),
336        })
337    }
338
339    pub fn default_assoc_refinement_body(
340        self,
341        trait_assoc_id: FluxDefId,
342    ) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>> {
343        self.inner
344            .queries
345            .default_assoc_refinement_body(self, trait_assoc_id)
346    }
347
348    pub fn assoc_refinement_body(
349        self,
350        impl_assoc_id: FluxDefId,
351    ) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
352        self.inner
353            .queries
354            .assoc_refinement_body(self, impl_assoc_id)
355    }
356
357    pub fn sort_of_assoc_reft(
358        self,
359        assoc_id: FluxDefId,
360    ) -> QueryResult<rty::EarlyBinder<rty::FuncSort>> {
361        self.inner.queries.sort_of_assoc_reft(self, assoc_id)
362    }
363
364    pub fn item_bounds(self, def_id: DefId) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>> {
365        self.inner.queries.item_bounds(self, def_id)
366    }
367
368    pub fn type_of(
369        self,
370        def_id: impl IntoQueryParam<DefId>,
371    ) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>> {
372        self.inner.queries.type_of(self, def_id.into_query_param())
373    }
374
375    pub fn fn_sig(
376        self,
377        def_id: impl IntoQueryParam<DefId>,
378    ) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>> {
379        self.inner.queries.fn_sig(self, def_id.into_query_param())
380    }
381
382    pub fn variants_of(
383        self,
384        def_id: impl IntoQueryParam<DefId>,
385    ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>> {
386        self.inner
387            .queries
388            .variants_of(self, def_id.into_query_param())
389    }
390
391    pub fn variant_sig(
392        self,
393        def_id: DefId,
394        variant_idx: VariantIdx,
395    ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariant>>> {
396        Ok(self
397            .variants_of(def_id)?
398            .map(|variants| variants.map(|variants| variants[variant_idx.as_usize()].clone())))
399    }
400
401    pub fn lower_late_bound_vars(
402        self,
403        def_id: LocalDefId,
404    ) -> QueryResult<List<ty::BoundVariableKind>> {
405        self.inner.queries.lower_late_bound_vars(self, def_id)
406    }
407
408    pub fn is_box(&self, res: fhir::Res) -> bool {
409        res.is_box(self.tcx())
410    }
411
412    pub fn def_id_to_param_index(&self, def_id: DefId) -> u32 {
413        let parent = self.tcx().parent(def_id);
414        let generics = self.tcx().generics_of(parent);
415        generics.param_def_id_to_index(self.tcx(), def_id).unwrap()
416    }
417
418    pub(crate) fn cstore(self) -> &'genv CrateStoreDyn {
419        &*self.inner.cstore
420    }
421
422    pub fn has_trusted_impl(&self, def_id: DefId) -> bool {
423        if let Some(did) = self
424            .resolve_id(def_id)
425            .as_maybe_extern()
426            .map(|id| id.local_id())
427        {
428            self.trusted_impl(did)
429        } else {
430            false
431        }
432    }
433
434    /// The `Output` associated type is defined in `FnOnce`, and `Fn`/`FnMut`
435    /// inherit it, so this should suffice to check if the `def_id`
436    /// corresponds to `LangItem::FnOnceOutput`.
437    pub fn is_fn_output(&self, def_id: DefId) -> bool {
438        let def_span = self.tcx().def_span(def_id);
439        self.tcx()
440            .require_lang_item(rustc_hir::LangItem::FnOnceOutput, def_span)
441            == def_id
442    }
443
444    /// Iterator over all local def ids that are not a extern spec
445    pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + use<'tcx, 'genv> {
446        self.tcx().iter_local_def_id().filter(move |&local_def_id| {
447            self.maybe_extern_id(local_def_id).is_local() && !self.is_dummy(local_def_id)
448        })
449    }
450
451    pub fn iter_extern_def_id(self) -> impl Iterator<Item = DefId> + use<'tcx, 'genv> {
452        self.tcx()
453            .iter_local_def_id()
454            .filter_map(move |local_def_id| self.maybe_extern_id(local_def_id).as_extern())
455    }
456
457    pub fn maybe_extern_id(self, local_id: LocalDefId) -> MaybeExternId {
458        self.collect_specs()
459            .local_id_to_extern_id
460            .get(&local_id)
461            .map_or_else(
462                || MaybeExternId::Local(local_id),
463                |def_id| MaybeExternId::Extern(local_id, *def_id),
464            )
465    }
466
467    #[expect(clippy::disallowed_methods)]
468    pub fn resolve_id(self, def_id: DefId) -> ResolvedDefId {
469        let maybe_extern_spec = self
470            .collect_specs()
471            .extern_id_to_local_id
472            .get(&def_id)
473            .copied();
474        if let Some(local_id) = maybe_extern_spec {
475            ResolvedDefId::ExternSpec(local_id, def_id)
476        } else if let Some(local_id) = def_id.as_local() {
477            debug_assert!(
478                self.maybe_extern_id(local_id).is_local(),
479                "def id points to dummy local item `{def_id:?}`"
480            );
481            ResolvedDefId::Local(local_id)
482        } else {
483            ResolvedDefId::Extern(def_id)
484        }
485    }
486
487    pub fn infer_opts(self, def_id: LocalDefId) -> config::InferOpts {
488        let mut opts = config::PartialInferOpts::default();
489        let specs = self.collect_specs();
490        self.traverse_parents(def_id, |did| {
491            if let Some(o) = specs.infer_opts.get(&did) {
492                opts.merge(o);
493            }
494            None::<!>
495        });
496        opts.into()
497    }
498
499    /// Transitively follow the parent-chain of `def_id` to find the first containing item with an
500    /// explicit `#[flux::trusted(..)]` annotation and return whether that item is trusted or not.
501    /// If no explicit annotation is found, return `false`.
502    pub fn trusted(self, def_id: LocalDefId) -> bool {
503        self.traverse_parents(def_id, |did| self.collect_specs().trusted.get(&did))
504            .map(|trusted| trusted.to_bool())
505            .unwrap_or_else(config::trusted_default)
506    }
507
508    pub fn trusted_impl(self, def_id: LocalDefId) -> bool {
509        self.traverse_parents(def_id, |did| self.collect_specs().trusted_impl.get(&did))
510            .map(|trusted| trusted.to_bool())
511            .unwrap_or(false)
512    }
513
514    /// Whether the item is a dummy item created by the extern spec macro.
515    ///
516    /// See [`crate::Specs::dummy_extern`]
517    pub fn is_dummy(self, def_id: LocalDefId) -> bool {
518        self.traverse_parents(def_id, |did| {
519            self.collect_specs()
520                .dummy_extern
521                .contains(&did)
522                .then_some(())
523        })
524        .is_some()
525    }
526
527    /// Transitively follow the parent-chain of `def_id` to find the first containing item with an
528    /// explicit `#[flux::ignore(..)]` annotation and return whether that item is ignored or not.
529    /// If no explicit annotation is found, return `false`.
530    pub fn ignored(self, def_id: LocalDefId) -> bool {
531        self.traverse_parents(def_id, |did| self.collect_specs().ignores.get(&did))
532            .map(|ignored| ignored.to_bool())
533            .unwrap_or_else(config::ignore_default)
534    }
535
536    /// Whether the function is marked with `#[flux::should_fail]`
537    pub fn should_fail(self, def_id: LocalDefId) -> bool {
538        self.collect_specs().should_fail.contains(&def_id)
539    }
540
541    /// Traverse the parent chain of `def_id` until the first node for which `f` returns [`Some`].
542    fn traverse_parents<T>(
543        self,
544        mut def_id: LocalDefId,
545        mut f: impl FnMut(LocalDefId) -> Option<T>,
546    ) -> Option<T> {
547        loop {
548            if let Some(v) = f(def_id) {
549                break Some(v);
550            }
551
552            if let Some(parent) = self.tcx().opt_local_parent(def_id) {
553                def_id = parent;
554            } else {
555                break None;
556            }
557        }
558    }
559}
560
561impl<'genv, 'tcx> GlobalEnv<'genv, 'tcx> {
562    pub fn fhir_iter_flux_items(
563        self,
564    ) -> impl Iterator<Item = (FluxLocalDefId, fhir::FluxItem<'genv>)> {
565        self.fhir_crate()
566            .items
567            .iter()
568            .map(|(id, item)| (*id, *item))
569    }
570
571    pub fn fhir_spec_func_body(
572        &self,
573        def_id: FluxLocalDefId,
574    ) -> Option<&'genv fhir::SpecFunc<'genv>> {
575        self.fhir_crate()
576            .items
577            .get(&def_id)
578            .and_then(|item| if let fhir::FluxItem::Func(defn) = item { Some(*defn) } else { None })
579    }
580
581    pub fn fhir_qualifiers(self) -> impl Iterator<Item = &'genv fhir::Qualifier<'genv>> {
582        self.fhir_crate().items.values().filter_map(|item| {
583            if let fhir::FluxItem::Qualifier(qual) = item { Some(*qual) } else { None }
584        })
585    }
586
587    pub fn fhir_primop_props(self) -> impl Iterator<Item = &'genv fhir::PrimOpProp<'genv>> {
588        self.fhir_crate().items.values().filter_map(|item| {
589            if let fhir::FluxItem::PrimOpProp(prop) = item { Some(*prop) } else { None }
590        })
591    }
592
593    pub fn fhir_get_generics(
594        self,
595        def_id: LocalDefId,
596    ) -> QueryResult<Option<&'genv fhir::Generics<'genv>>> {
597        // We don't have nodes for closures and coroutines
598        if matches!(self.def_kind(def_id), DefKind::Closure) {
599            Ok(None)
600        } else {
601            Ok(Some(self.fhir_expect_owner_node(def_id)?.generics()))
602        }
603    }
604
605    pub fn fhir_expect_refinement_kind(
606        self,
607        def_id: LocalDefId,
608    ) -> QueryResult<&'genv fhir::RefinementKind<'genv>> {
609        let kind = match &self.fhir_expect_item(def_id)?.kind {
610            fhir::ItemKind::Enum(enum_def) => &enum_def.refinement,
611            fhir::ItemKind::Struct(struct_def) => &struct_def.refinement,
612            _ => bug!("expected struct, enum or type alias"),
613        };
614        Ok(kind)
615    }
616
617    pub fn fhir_expect_item(self, def_id: LocalDefId) -> QueryResult<&'genv fhir::Item<'genv>> {
618        if let fhir::Node::Item(item) = self.fhir_node(def_id)? {
619            Ok(item)
620        } else {
621            Err(query_bug!(def_id, "expected item: `{def_id:?}`"))
622        }
623    }
624
625    pub fn fhir_expect_owner_node(self, def_id: LocalDefId) -> QueryResult<fhir::OwnerNode<'genv>> {
626        let Some(owner) = self.fhir_node(def_id)?.as_owner() else {
627            return Err(query_bug!(def_id, "cannot find owner node"));
628        };
629        Ok(owner)
630    }
631
632    pub fn fhir_node(self, def_id: LocalDefId) -> QueryResult<fhir::Node<'genv>> {
633        self.desugar(def_id)
634    }
635}
636
637#[macro_export]
638macro_rules! try_alloc_slice {
639    ($genv:expr, $slice:expr, $map:expr $(,)?) => {{
640        let slice = $slice;
641        $crate::try_alloc_slice!($genv, cap: slice.len(), slice.into_iter().map($map))
642    }};
643    ($genv:expr, cap: $cap:expr, $it:expr $(,)?) => {{
644        let mut err = None;
645        let slice = $genv.alloc_slice_with_capacity($cap, $it.into_iter().collect_errors(&mut err));
646        err.map_or(Ok(slice), Err)
647    }};
648}
649
650impl ErrorEmitter for GlobalEnv<'_, '_> {
651    fn emit<'a>(&'a self, err: impl rustc_errors::Diagnostic<'a>) -> rustc_span::ErrorGuaranteed {
652        self.sess().emit(err)
653    }
654}