1use std::{
2 cell::{OnceCell, RefCell},
3 rc::Rc,
4};
5
6use flux_arc_interner::List;
7use flux_common::{bug, tracked_span_bug};
8use flux_config as config;
9use flux_errors::{E0999, ErrorGuaranteed};
10use flux_rustc_bridge::{
11 self, def_id_to_string,
12 lowering::{self, Lower, UnsupportedErr},
13 mir::{self},
14 ty,
15};
16use flux_syntax::{surface, symbols::sym};
17use itertools::Itertools;
18use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
19use rustc_errors::Diagnostic;
20use rustc_hir::{
21 LangItem,
22 def::DefKind,
23 def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId},
24};
25use rustc_index::IndexVec;
26use rustc_macros::{Decodable, Encodable};
27use rustc_span::{DUMMY_SP, Span, Symbol};
28
29use crate::{
30 PanicSpec,
31 call_graph::{CallGraph, NodeKey},
32 def_id::{FluxDefId, FluxId, MaybeExternId, ResolvedDefId},
33 fhir,
34 global_env::GlobalEnv,
35 rty::{
36 self, AliasReft, Expr, GenericArg,
37 refining::{self, Refine, Refiner, refine_generic_param_def},
38 },
39};
40
41type Cache<K, V> = RefCell<UnordMap<K, V>>;
42
43pub type QueryResult<T = ()> = Result<T, QueryErr>;
44
45#[derive(Debug, Clone, Encodable, Decodable)]
70pub enum QueryErr {
71 Unsupported {
72 def_id: DefId,
73 err: UnsupportedErr,
74 },
75 Ignored {
76 def_id: DefId,
77 },
78 InvalidGenericArg {
79 def_id: DefId,
80 },
81 MissingAssocReft {
82 impl_id: DefId,
83 trait_id: DefId,
84 name: Symbol,
85 },
86 OpaqueStruct {
88 struct_id: DefId,
89 },
90 Bug {
94 def_id: Option<DefId>,
95 location: String,
96 msg: String,
97 },
98 Emitted(ErrorGuaranteed),
99 NotIncluded {
101 def_id: DefId,
102 },
103}
104
105#[macro_export]
106macro_rules! query_bug {
107 ($fmt:literal $(,$args:expr)* $(,)?) => {
108 $crate::queries::QueryErr::bug(None, format_args!($fmt, $($args),*))
109 };
110 ($def_id:expr, $fmt:literal $(,$args:expr)* $(,)? ) => {{
111 $crate::queries::QueryErr::bug(Some($def_id.into()), format_args!($fmt, $($args),*))
112 }};
113}
114
115impl QueryErr {
116 pub fn unsupported(def_id: DefId, err: UnsupportedErr) -> Self {
117 QueryErr::Unsupported { def_id, err }
118 }
119
120 #[track_caller]
121 pub fn bug(def_id: Option<DefId>, msg: impl ToString) -> Self {
122 QueryErr::Bug {
123 def_id,
124 location: format!("{}", std::panic::Location::caller()),
125 msg: msg.to_string(),
126 }
127 }
128
129 pub fn at(self, cx: impl Into<ErrCtxt>) -> QueryErrAt {
130 QueryErrAt { cx: cx.into(), err: self }
131 }
132}
133
134pub struct QueryErrAt {
136 cx: ErrCtxt,
137 err: QueryErr,
138}
139
140#[derive(Clone, Copy)]
142pub enum ErrCtxt {
143 FnCheck(Span, LocalDefId),
146 Misc(Span),
148}
149
150impl From<Span> for ErrCtxt {
151 fn from(v: Span) -> Self {
152 Self::Misc(v)
153 }
154}
155
156impl ErrCtxt {
157 fn span(self) -> Span {
158 match self {
159 ErrCtxt::Misc(span) => span,
160 ErrCtxt::FnCheck(span, _) => span,
161 }
162 }
163}
164
165pub struct Providers {
166 pub collect_specs: fn(GlobalEnv) -> crate::Specs,
167 pub resolve_crate: fn(GlobalEnv) -> crate::ResolverOutput,
168 pub desugar: for<'genv> fn(
169 GlobalEnv<'genv, '_>,
170 LocalDefId,
171 ) -> QueryResult<UnordMap<LocalDefId, fhir::Node<'genv>>>,
172 pub fhir_attr_map: for<'genv> fn(GlobalEnv<'genv, '_>, LocalDefId) -> fhir::AttrMap<'genv>,
173 pub fhir_crate: for<'genv> fn(GlobalEnv<'genv, '_>) -> fhir::FluxItems<'genv>,
174 pub qualifiers: fn(GlobalEnv) -> QueryResult<Vec<rty::Qualifier>>,
175 pub prim_rel: fn(GlobalEnv) -> QueryResult<UnordMap<rty::BinOp, rty::PrimRel>>,
176 pub normalized_defns: fn(GlobalEnv) -> rty::NormalizedDefns,
177 pub func_sort: fn(GlobalEnv, FluxId<MaybeExternId>) -> rty::PolyFuncSort,
178 pub func_span: fn(GlobalEnv, FluxId<MaybeExternId>) -> Span,
179 pub adt_sort_def_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AdtSortDef>,
180 pub check_wf: fn(GlobalEnv, LocalDefId) -> QueryResult<Rc<rty::WfckResults>>,
181 pub adt_def: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AdtDef>,
182 pub constant_info: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::ConstantInfo>,
183 pub static_info: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::StaticInfo>,
184 pub type_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>>,
185 pub variants_of: fn(
186 GlobalEnv,
187 MaybeExternId,
188 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>>,
189 pub fn_sig: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>>,
190 pub generics_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::Generics>,
191 pub refinement_generics_of:
192 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>>,
193 pub predicates_of:
194 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>>,
195 pub assoc_refinements_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AssocRefinements>,
196 pub sort_of_assoc_reft:
197 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<rty::EarlyBinder<rty::FuncSort>>,
198 pub assoc_refinement_body:
199 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<rty::EarlyBinder<rty::Lambda>>,
200 #[allow(clippy::type_complexity)]
201 pub default_assoc_refinement_body:
202 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>>,
203 pub item_bounds:
204 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>>,
205 pub sort_decl_param_count: fn(GlobalEnv, FluxId<MaybeExternId>) -> usize,
206 pub call_graph: for<'genv, 'tcx> fn(GlobalEnv<'genv, 'tcx>) -> CallGraph<'tcx>,
207 pub inferred_no_panic:
208 for<'genv, 'tcx> fn(GlobalEnv<'genv, 'tcx>) -> UnordMap<NodeKey<'tcx>, PanicSpec>,
209}
210
211macro_rules! empty_query {
212 () => {
213 flux_common::bug!("query not provided")
214 };
215}
216
217impl Default for Providers {
218 fn default() -> Self {
219 Self {
220 collect_specs: |_| empty_query!(),
221 resolve_crate: |_| empty_query!(),
222 desugar: |_, _| empty_query!(),
223 fhir_attr_map: |_, _| empty_query!(),
224 fhir_crate: |_| empty_query!(),
225 normalized_defns: |_| empty_query!(),
226 func_sort: |_, _| empty_query!(),
227 func_span: |_, _| empty_query!(),
228 qualifiers: |_| empty_query!(),
229 prim_rel: |_| empty_query!(),
230 adt_sort_def_of: |_, _| empty_query!(),
231 check_wf: |_, _| empty_query!(),
232 adt_def: |_, _| empty_query!(),
233 type_of: |_, _| empty_query!(),
234 variants_of: |_, _| empty_query!(),
235 fn_sig: |_, _| empty_query!(),
236 generics_of: |_, _| empty_query!(),
237 refinement_generics_of: |_, _| empty_query!(),
238 predicates_of: |_, _| empty_query!(),
239 assoc_refinements_of: |_, _| empty_query!(),
240 assoc_refinement_body: |_, _| empty_query!(),
241 default_assoc_refinement_body: |_, _| empty_query!(),
242 sort_of_assoc_reft: |_, _| empty_query!(),
243 item_bounds: |_, _| empty_query!(),
244 constant_info: |_, _| empty_query!(),
245 static_info: |_, _| empty_query!(),
246 sort_decl_param_count: |_, _| empty_query!(),
247 call_graph: |_| empty_query!(),
248 inferred_no_panic: |_| empty_query!(),
249 }
250 }
251}
252
253pub struct Queries<'genv, 'tcx> {
254 pub(crate) providers: Providers,
255 queried_def_ids: RefCell<UnordSet<DefId>>,
261 mir: Cache<LocalDefId, QueryResult<Rc<mir::BodyRoot<'tcx>>>>,
262 collect_specs: OnceCell<crate::Specs>,
263 resolve_crate: OnceCell<crate::ResolverOutput>,
264 flux_module_children: Cache<DefId, &'genv [fhir::FluxModChild]>,
265 desugar: Cache<LocalDefId, QueryResult<fhir::Node<'genv>>>,
266 fhir_attr_map: Cache<LocalDefId, fhir::AttrMap<'genv>>,
267 fhir_crate: OnceCell<fhir::FluxItems<'genv>>,
268 lower_generics_of: Cache<DefId, ty::Generics<'tcx>>,
269 lower_predicates_of: Cache<DefId, QueryResult<ty::GenericPredicates>>,
270 lower_type_of: Cache<DefId, QueryResult<ty::EarlyBinder<ty::Ty>>>,
271 lower_fn_sig: Cache<DefId, QueryResult<ty::EarlyBinder<ty::PolyFnSig>>>,
272 normalized_defns: Cache<CrateNum, Rc<rty::NormalizedDefns>>,
273 func_sort: Cache<FluxDefId, rty::PolyFuncSort>,
274 func_span: Cache<FluxDefId, Span>,
275 qualifiers: OnceCell<QueryResult<Vec<rty::Qualifier>>>,
276 prim_rel: OnceCell<QueryResult<UnordMap<rty::BinOp, rty::PrimRel>>>,
277 adt_sort_def_of: Cache<DefId, QueryResult<rty::AdtSortDef>>,
278 check_wf: Cache<LocalDefId, QueryResult<Rc<rty::WfckResults>>>,
279 adt_def: Cache<DefId, QueryResult<rty::AdtDef>>,
280 constant_info: Cache<DefId, QueryResult<rty::ConstantInfo>>,
281 static_info: Cache<DefId, QueryResult<rty::StaticInfo>>,
282 generics_of: Cache<DefId, QueryResult<rty::Generics>>,
283 refinement_generics_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::RefinementGenerics>>>,
284 predicates_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::GenericPredicates>>>,
285 assoc_refinements_of: Cache<DefId, QueryResult<rty::AssocRefinements>>,
286 assoc_refinement_body: Cache<FluxDefId, QueryResult<rty::EarlyBinder<rty::Lambda>>>,
287 default_assoc_refinement_body:
288 Cache<FluxDefId, QueryResult<Option<rty::EarlyBinder<rty::Lambda>>>>,
289 sort_of_assoc_reft: Cache<FluxDefId, QueryResult<rty::EarlyBinder<rty::FuncSort>>>,
290 item_bounds: Cache<DefId, QueryResult<rty::EarlyBinder<List<rty::Clause>>>>,
291 type_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::TyOrCtor>>>,
292 variants_of: Cache<DefId, QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>>>,
293 fn_sig: Cache<DefId, QueryResult<rty::EarlyBinder<rty::PolyFnSig>>>,
294 sort_decl_param_count: Cache<FluxDefId, usize>,
295 no_panic: Cache<DefId, bool>,
296 assume_parametric_params: Cache<DefId, UnordSet<u32>>,
297 call_graph: OnceCell<CallGraph<'tcx>>,
298 inferred_no_panic: OnceCell<Rc<UnordMap<NodeKey<'tcx>, PanicSpec>>>,
300}
301
302impl<'genv, 'tcx> Queries<'genv, 'tcx> {
303 pub(crate) fn new(providers: Providers) -> Self {
304 Self {
305 providers,
306 queried_def_ids: RefCell::new(UnordSet::new()),
307 mir: Default::default(),
308 collect_specs: Default::default(),
309 resolve_crate: Default::default(),
310 flux_module_children: Default::default(),
311 desugar: Default::default(),
312 fhir_attr_map: Default::default(),
313 fhir_crate: Default::default(),
314 lower_generics_of: Default::default(),
315 lower_predicates_of: Default::default(),
316 lower_type_of: Default::default(),
317 lower_fn_sig: Default::default(),
318 normalized_defns: Default::default(),
319 func_sort: Default::default(),
320 func_span: Default::default(),
321 qualifiers: Default::default(),
322 prim_rel: Default::default(),
323 adt_sort_def_of: Default::default(),
324 check_wf: Default::default(),
325 adt_def: Default::default(),
326 constant_info: Default::default(),
327 static_info: Default::default(),
328 generics_of: Default::default(),
329 refinement_generics_of: Default::default(),
330 predicates_of: Default::default(),
331 assoc_refinements_of: Default::default(),
332 assoc_refinement_body: Default::default(),
333 default_assoc_refinement_body: Default::default(),
334 sort_of_assoc_reft: Default::default(),
335 item_bounds: Default::default(),
336 type_of: Default::default(),
337 variants_of: Default::default(),
338 fn_sig: Default::default(),
339 sort_decl_param_count: Default::default(),
340 no_panic: Default::default(),
341 assume_parametric_params: Default::default(),
342 call_graph: Default::default(),
343 inferred_no_panic: Default::default(),
344 }
345 }
346
347 pub(crate) fn queried(&self, def_id: DefId) -> bool {
348 self.queried_def_ids.borrow().contains(&def_id)
349 }
350
351 pub(crate) fn mir(
352 &self,
353 genv: GlobalEnv<'genv, 'tcx>,
354 def_id: LocalDefId,
355 ) -> QueryResult<Rc<mir::BodyRoot<'tcx>>> {
356 run_with_cache(&self.mir, def_id, || {
357 let mir = unsafe { flux_common::mir_storage::retrieve_mir_body(genv.tcx(), def_id) };
358 let mir =
359 lowering::MirLoweringCtxt::lower_mir_body(genv.tcx(), genv.sess(), def_id, mir)?;
360 Ok(Rc::new(mir))
361 })
362 }
363
364 pub(crate) fn collect_specs(&'genv self, genv: GlobalEnv<'genv, 'tcx>) -> &'genv crate::Specs {
365 self.collect_specs
366 .get_or_init(|| (self.providers.collect_specs)(genv))
367 }
368
369 pub(crate) fn resolve_crate(
370 &'genv self,
371 genv: GlobalEnv<'genv, 'tcx>,
372 ) -> &'genv crate::ResolverOutput {
373 self.resolve_crate
374 .get_or_init(|| (self.providers.resolve_crate)(genv))
375 }
376
377 #[allow(clippy::disallowed_methods, reason = "`flux_items_by_parent` is the source of truth")]
380 pub(crate) fn flux_module_children(
381 &'genv self,
382 genv: GlobalEnv<'genv, 'tcx>,
383 def_id: DefId,
384 ) -> &'genv [fhir::FluxModChild] {
385 run_with_cache(&self.flux_module_children, def_id, || {
386 def_id.dispatch_query(
387 genv,
388 self,
389 |def_id| -> &'genv [fhir::FluxModChild] {
390 let specs = genv.collect_specs();
394 let parent = def_id.local_id();
395 let items = specs
396 .flux_items_by_parent
397 .get(&rustc_hir::OwnerId { def_id: parent })
398 .map_or(&[][..], Vec::as_ref);
399 genv.alloc_slice(
400 &items
401 .iter()
402 .filter_map(|item| {
403 let res;
404 let ident;
405 match item {
406 surface::FluxItem::FuncDef(func) => {
407 ident = func.name;
408 res = fhir::Res::GlobalFunc(fhir::SpecFuncKind::Def(
409 FluxDefId::new(parent.to_def_id(), ident.name),
410 ));
411 }
412 surface::FluxItem::SortDecl(sort) => {
413 ident = sort.name;
414 res = fhir::Res::UserSort(FluxDefId::new(
415 parent.to_def_id(),
416 ident.name,
417 ));
418 }
419 surface::FluxItem::Qualifier(_)
420 | surface::FluxItem::PrimOpProp(_)
421 | surface::FluxItem::Use(_) => return None,
422 };
423 Some(fhir::FluxModChild { ident, res })
424 })
425 .collect::<Vec<_>>(),
426 )
427 },
428 |def_id| genv.cstore().flux_module_children(def_id),
429 |_| &[], )
431 })
432 }
433
434 pub(crate) fn desugar(
435 &'genv self,
436 genv: GlobalEnv<'genv, 'tcx>,
437 def_id: LocalDefId,
438 ) -> QueryResult<fhir::Node<'genv>> {
439 if let Some(v) = self.desugar.borrow().get(&def_id) {
440 return v.clone();
441 }
442 match (self.providers.desugar)(genv, def_id) {
443 Ok(nodes) => {
444 let mut cache = self.desugar.borrow_mut();
445 cache.extend_unord(nodes.into_items().map(|(def_id, node)| (def_id, Ok(node))));
446 let Some(res) = cache.get(&def_id) else {
447 tracked_span_bug!("cannot desugar {def_id:?}")
448 };
449 res.clone()
450 }
451 Err(err) => {
452 self.desugar.borrow_mut().insert(def_id, Err(err.clone()));
453 Err(err)
454 }
455 }
456 }
457
458 pub(crate) fn fhir_attr_map(
459 &'genv self,
460 genv: GlobalEnv<'genv, 'tcx>,
461 def_id: LocalDefId,
462 ) -> fhir::AttrMap<'genv> {
463 run_with_cache(&self.fhir_attr_map, def_id, || (self.providers.fhir_attr_map)(genv, def_id))
464 }
465
466 pub(crate) fn fhir_crate(
467 &'genv self,
468 genv: GlobalEnv<'genv, 'tcx>,
469 ) -> &'genv fhir::FluxItems<'genv> {
470 self.fhir_crate
471 .get_or_init(|| (self.providers.fhir_crate)(genv))
472 }
473
474 pub(crate) fn lower_generics_of(
475 &self,
476 genv: GlobalEnv<'genv, 'tcx>,
477 def_id: DefId,
478 ) -> ty::Generics<'tcx> {
479 run_with_cache(&self.lower_generics_of, def_id, || {
480 genv.tcx().generics_of(def_id).lower(genv.tcx())
481 })
482 }
483
484 pub(crate) fn lower_predicates_of(
485 &self,
486 genv: GlobalEnv,
487 def_id: DefId,
488 ) -> QueryResult<ty::GenericPredicates> {
489 run_with_cache(&self.lower_predicates_of, def_id, || {
490 genv.tcx()
491 .predicates_of(def_id)
492 .lower(genv.tcx())
493 .map_err(|err| QueryErr::unsupported(def_id, err))
494 })
495 }
496
497 pub(crate) fn lower_type_of(
498 &self,
499 genv: GlobalEnv,
500 def_id: DefId,
501 ) -> QueryResult<ty::EarlyBinder<ty::Ty>> {
502 run_with_cache(&self.lower_type_of, def_id, || {
503 let ty = genv.tcx().type_of(def_id).instantiate_identity();
504 Ok(ty::EarlyBinder(
505 ty.lower(genv.tcx())
506 .map_err(|err| QueryErr::unsupported(def_id, err.into_err()))?,
507 ))
508 })
509 }
510
511 pub(crate) fn lower_fn_sig(
512 &self,
513 genv: GlobalEnv,
514 def_id: DefId,
515 ) -> QueryResult<ty::EarlyBinder<ty::PolyFnSig>> {
516 run_with_cache(&self.lower_fn_sig, def_id, || {
517 let fn_sig = genv.tcx().fn_sig(def_id).instantiate_identity();
518 Ok(ty::EarlyBinder(
519 fn_sig
520 .lower(genv.tcx())
521 .map_err(|err| QueryErr::unsupported(def_id, err.into_err()))?,
522 ))
523 })
524 }
525
526 pub(crate) fn normalized_defns(
527 &self,
528 genv: GlobalEnv,
529 krate: CrateNum,
530 ) -> Rc<rty::NormalizedDefns> {
531 run_with_cache(&self.normalized_defns, krate, || {
532 if krate == LOCAL_CRATE {
533 Rc::new((self.providers.normalized_defns)(genv))
534 } else {
535 genv.cstore().normalized_defns(krate)
536 }
537 })
538 }
539
540 pub(crate) fn func_sort(&self, genv: GlobalEnv, def_id: FluxDefId) -> rty::PolyFuncSort {
541 run_with_cache(&self.func_sort, def_id, || {
542 def_id.dispatch_query(
543 genv,
544 self,
545 |def_id| {
546 (self.providers.func_sort)(genv, def_id)
548 },
549 |def_id| genv.cstore().func_sort(def_id),
550 |_| {
551 bug!(
552 "cannot generate default function sort, the refinement must be defined somewhere"
553 )
554 },
555 )
556 })
557 }
558
559 pub(crate) fn func_span(&self, genv: GlobalEnv, def_id: FluxDefId) -> Span {
560 run_with_cache(&self.func_span, def_id, || {
561 def_id.dispatch_query(
562 genv,
563 self,
564 |def_id| {
565 (self.providers.func_span)(genv, def_id)
567 },
568 |def_id| genv.cstore().func_span(def_id),
569 |_|
570 bug!(
571 "cannot generate default function sort, the refinement must be defined somewhere"
572 )
573 ,
574 )
575 })
576 }
577
578 pub(crate) fn qualifiers(&self, genv: GlobalEnv) -> QueryResult<&[rty::Qualifier]> {
579 self.qualifiers
580 .get_or_init(|| (self.providers.qualifiers)(genv))
581 .as_deref()
582 .map_err(Clone::clone)
583 }
584
585 pub(crate) fn prim_rel(
586 &self,
587 genv: GlobalEnv,
588 ) -> QueryResult<&UnordMap<rty::BinOp, rty::PrimRel>> {
589 self.prim_rel
590 .get_or_init(|| (self.providers.prim_rel)(genv))
591 .as_ref()
592 .map_err(|err| err.clone())
593 }
594
595 pub(crate) fn adt_sort_def_of(
596 &self,
597 genv: GlobalEnv,
598 def_id: DefId,
599 ) -> QueryResult<rty::AdtSortDef> {
600 run_with_cache(&self.adt_sort_def_of, def_id, || {
601 def_id.dispatch_query(
602 genv,
603 self,
604 |def_id| (self.providers.adt_sort_def_of)(genv, def_id),
605 |def_id| genv.cstore().adt_sort_def(def_id),
606 |def_id| {
607 let variants = IndexVec::from([rty::AdtSortVariant::new(vec![])]);
608 Ok(rty::AdtSortDef::new(def_id, vec![], variants, false, true))
609 },
610 )
611 })
612 }
613
614 pub(crate) fn sort_decl_param_count(&self, genv: GlobalEnv, def_id: FluxDefId) -> usize {
615 run_with_cache(&self.sort_decl_param_count, def_id, || {
616 def_id.dispatch_query(
617 genv,
618 self,
619 |def_id| {
620 (self.providers.sort_decl_param_count)(genv, def_id)
621 },
622 |def_id| genv.cstore().sort_decl_param_count(def_id),
623 |_| {
624 bug!(
625 "cannot generate default param count for sort declaration, it must be defined somewhere"
626 )
627 }
628 )
629 })
630 }
631
632 pub(crate) fn check_wf(
633 &self,
634 genv: GlobalEnv<'genv, '_>,
635 def_id: LocalDefId,
636 ) -> QueryResult<Rc<rty::WfckResults>> {
637 run_with_cache(&self.check_wf, def_id, || (self.providers.check_wf)(genv, def_id))
638 }
639
640 pub(crate) fn constant_info(
641 &self,
642 genv: GlobalEnv,
643 def_id: DefId,
644 ) -> QueryResult<rty::ConstantInfo> {
645 run_with_cache(&self.constant_info, def_id, || {
646 def_id.dispatch_query(
647 genv,
648 self,
649 |def_id| (self.providers.constant_info)(genv, def_id),
650 |def_id| genv.cstore().constant_info(def_id),
651 |def_id| {
652 let ty = genv.tcx().type_of(def_id).no_bound_vars().unwrap();
654 if ty.is_integral() {
655 let val = genv.tcx().const_eval_poly(def_id).ok().and_then(|val| {
656 let val = val.try_to_scalar_int()?;
657 rty::Constant::from_scalar_int(genv.tcx(), val, &ty)
658 });
659 if let Some(constant_) = val {
660 return Ok(rty::ConstantInfo::Interpreted(
661 rty::Expr::constant(constant_),
662 rty::Sort::Int,
663 ));
664 }
665 }
666 Ok(rty::ConstantInfo::Uninterpreted)
667 },
668 )
669 })
670 }
671
672 pub fn call_graph(&'genv self, genv: GlobalEnv<'genv, 'tcx>) -> &'genv CallGraph<'tcx> {
673 self.call_graph
674 .get_or_init(|| (self.providers.call_graph)(genv))
675 }
676
677 pub fn inferred_no_panic(
679 &'genv self,
680 genv: GlobalEnv<'genv, 'tcx>,
681 ) -> Rc<UnordMap<NodeKey<'tcx>, PanicSpec>> {
682 self.inferred_no_panic
683 .get_or_init(|| Rc::new((self.providers.inferred_no_panic)(genv)))
684 .clone()
685 }
686
687 pub(crate) fn static_info(
688 &self,
689 genv: GlobalEnv,
690 def_id: DefId,
691 ) -> QueryResult<rty::StaticInfo> {
692 run_with_cache(&self.static_info, def_id, || {
693 def_id.dispatch_query(
694 genv,
695 self,
696 |def_id| (self.providers.static_info)(genv, def_id),
697 |def_id| genv.cstore().static_info(def_id),
698 |_def_id| Ok(rty::StaticInfo::Unknown),
699 )
700 })
701 }
702
703 pub(crate) fn no_panic(&self, genv: GlobalEnv, def_id: DefId) -> bool {
704 run_with_cache(&self.no_panic, def_id, || {
705 def_id.dispatch_query(
706 genv,
707 self,
708 |def_id| {
709 let mut current_id = def_id.local_id();
710
711 loop {
713 if genv.is_dummy(current_id) {
715 if let Some(parent) = genv.tcx().opt_local_parent(current_id) {
716 current_id = parent;
717 continue;
718 } else {
719 return false; }
721 }
722
723 if genv.fhir_attr_map(current_id).no_panic() {
725 return true;
726 }
727
728 if let Some(parent) = genv.tcx().opt_local_parent(current_id) {
730 current_id = parent;
731 } else {
732 break; }
734 }
735
736 config::no_panic()
737 },
738 |def_id| genv.cstore().no_panic(def_id),
739 |_| false,
740 )
741 })
742 }
743
744 pub(crate) fn assume_parametric_params(&self, genv: GlobalEnv, def_id: DefId) -> UnordSet<u32> {
745 run_with_cache(&self.assume_parametric_params, def_id, || {
746 def_id.dispatch_query(
747 genv,
748 self,
749 |def_id| {
750 let tcx = genv.tcx();
751 let generics = tcx.generics_of(def_id);
752 genv.fhir_attr_map(def_id.local_id())
753 .parametric_params()
754 .iter()
755 .map(|param_id| generics.param_def_id_to_index(tcx, *param_id).unwrap())
756 .collect()
757 },
758 |def_id| genv.cstore().assume_parametric_params(def_id),
759 |_| UnordSet::default(),
760 )
761 })
762 }
763
764 pub(crate) fn adt_def(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::AdtDef> {
765 run_with_cache(&self.adt_def, def_id, || {
766 def_id.dispatch_query(
767 genv,
768 self,
769 |def_id| (self.providers.adt_def)(genv, def_id),
770 |def_id| genv.cstore().adt_def(def_id),
771 |def_id| {
772 let adt_def = genv.tcx().adt_def(def_id).lower(genv.tcx());
773 Ok(rty::AdtDef::new(adt_def, genv.adt_sort_def_of(def_id)?, vec![], false))
774 },
775 )
776 })
777 }
778
779 pub(crate) fn generics_of(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::Generics> {
780 if genv.tcx().is_lang_item(def_id, LangItem::OwnedBox) {
784 let generics = genv.lower_generics_of(def_id);
785 debug_assert_eq!(generics.params.len(), 2);
786 let deref_ty = &generics.params[0];
787 let alloc = &generics.params[1];
788 return Ok(rty::Generics {
789 own_params: List::from_arr([
790 refine_generic_param_def(true, deref_ty),
791 refine_generic_param_def(false, alloc),
792 ]),
793 parent: generics.parent(),
794 parent_count: generics.parent_count(),
795 has_self: generics.orig.has_self,
796 });
797 }
798 if genv.tcx().is_lang_item(def_id, LangItem::MetaSized) {
805 let generics = genv.lower_generics_of(def_id);
806 debug_assert_eq!(generics.params.len(), 1);
807 let self_ty = &generics.params[0];
808 return Ok(rty::Generics {
809 own_params: List::from_arr([refine_generic_param_def(true, self_ty)]),
810 parent: generics.parent(),
811 parent_count: generics.parent_count(),
812 has_self: generics.orig.has_self,
813 });
814 }
815
816 run_with_cache(&self.generics_of, def_id, || {
817 def_id.dispatch_query(
818 genv,
819 self,
820 |def_id| (self.providers.generics_of)(genv, def_id),
821 |def_id| genv.cstore().generics_of(def_id),
822 |def_id| Ok(refining::refine_generics(&genv.lower_generics_of(def_id))),
823 )
824 })
825 }
826
827 pub(crate) fn refinement_generics_of(
828 &self,
829 genv: GlobalEnv,
830 def_id: DefId,
831 ) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>> {
832 run_with_cache(&self.refinement_generics_of, def_id, || {
833 def_id.dispatch_query(
834 genv,
835 self,
836 |def_id| (self.providers.refinement_generics_of)(genv, def_id),
837 |def_id| genv.cstore().refinement_generics_of(def_id),
838 |def_id| {
839 let parent = genv.tcx().generics_of(def_id).parent;
840 Ok(rty::EarlyBinder(rty::RefinementGenerics {
841 parent,
842 parent_count: 0,
843 own_params: List::empty(),
844 }))
845 },
846 )
847 })
848 }
849
850 pub(crate) fn item_bounds(
851 &self,
852 genv: GlobalEnv<'genv, 'tcx>,
853 def_id: DefId,
854 ) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>> {
855 run_with_cache(&self.item_bounds, def_id, || {
856 def_id.dispatch_query(
857 genv,
858 self,
859 |def_id| (self.providers.item_bounds)(genv, def_id),
860 |def_id| genv.cstore().item_bounds(def_id),
861 |def_id| {
862 let clauses = genv
863 .tcx()
864 .item_bounds(def_id)
865 .skip_binder()
866 .lower(genv.tcx())
867 .map_err(|err| QueryErr::unsupported(def_id, err))?
868 .refine(&Refiner::default_for_item(genv, def_id)?)?;
869
870 Ok(rty::EarlyBinder(clauses))
871 },
872 )
873 })
874 }
875
876 pub(crate) fn predicates_of(
877 &self,
878 genv: GlobalEnv,
879 def_id: DefId,
880 ) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
881 run_with_cache(&self.predicates_of, def_id, || {
882 def_id.dispatch_query(
883 genv,
884 self,
885 |def_id| (self.providers.predicates_of)(genv, def_id),
886 |def_id| genv.cstore().predicates_of(def_id),
887 |def_id| {
888 let predicates = genv
889 .lower_predicates_of(def_id)?
890 .refine(&Refiner::default_for_item(genv, def_id)?)?;
891 Ok(rty::EarlyBinder(predicates))
892 },
893 )
894 })
895 }
896
897 pub(crate) fn assoc_refinements_of(
898 &self,
899 genv: GlobalEnv,
900 def_id: DefId,
901 ) -> QueryResult<rty::AssocRefinements> {
902 run_with_cache(&self.assoc_refinements_of, def_id, || {
903 def_id.dispatch_query(
904 genv,
905 self,
906 |def_id| (self.providers.assoc_refinements_of)(genv, def_id),
907 |def_id| genv.cstore().assoc_refinements_of(def_id),
908 |def_id| Ok(genv.builtin_assoc_refts(def_id).unwrap_or_default()),
909 )
910 })
911 }
912
913 pub(crate) fn assoc_refinement_body(
914 &self,
915 genv: GlobalEnv,
916 impl_assoc_id: FluxDefId,
917 ) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
918 run_with_cache(&self.assoc_refinement_body, impl_assoc_id, || {
919 impl_assoc_id.dispatch_query(
920 genv,
921 self,
922 |impl_assoc_id| (self.providers.assoc_refinement_body)(genv, impl_assoc_id),
923 |impl_assoc_id| genv.cstore().assoc_refinements_def(impl_assoc_id),
924 |impl_assoc_id| {
925 Err(query_bug!(
926 impl_assoc_id.parent(),
927 "cannot generate default associate refinement for extern impl"
928 ))
929 },
930 )
931 })
932 }
933
934 pub(crate) fn default_assoc_refinement_body(
935 &self,
936 genv: GlobalEnv,
937 trait_assoc_id: FluxDefId,
938 ) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>> {
939 run_with_cache(&self.default_assoc_refinement_body, trait_assoc_id, || {
940 trait_assoc_id.dispatch_query(
941 genv,
942 self,
943 |trait_assoc_id| {
944 (self.providers.default_assoc_refinement_body)(genv, trait_assoc_id)
945 },
946 |trait_assoc_id| genv.cstore().default_assoc_refinements_def(trait_assoc_id),
947 |trait_assoc_id| {
948 Err(query_bug!(
949 trait_assoc_id.parent(),
950 "cannot generate default assoc refinement for extern trait"
951 ))
952 },
953 )
954 })
955 }
956
957 pub(crate) fn sort_of_assoc_reft(
958 &self,
959 genv: GlobalEnv,
960 assoc_id: FluxDefId,
961 ) -> QueryResult<rty::EarlyBinder<rty::FuncSort>> {
962 run_with_cache(&self.sort_of_assoc_reft, assoc_id, || {
963 assoc_id.dispatch_query(
964 genv,
965 self,
966 |assoc_id| (self.providers.sort_of_assoc_reft)(genv, assoc_id),
967 |assoc_id| genv.cstore().sort_of_assoc_reft(assoc_id),
968 |assoc_id| {
969 genv.builtin_assoc_reft_sort(assoc_id).ok_or_else(|| {
970 query_bug!(
971 assoc_id.parent(),
972 "assoc refinement on extern crate is not builtin"
973 )
974 })
975 },
976 )
977 })
978 }
979
980 pub(crate) fn type_of(
981 &self,
982 genv: GlobalEnv,
983 def_id: DefId,
984 ) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>> {
985 run_with_cache(&self.type_of, def_id, || {
986 def_id.dispatch_query(
987 genv,
988 self,
989 |def_id| (self.providers.type_of)(genv, def_id),
990 |def_id| genv.cstore().type_of(def_id),
991 |def_id| {
992 let generics_def_id = match genv.def_kind(def_id) {
994 DefKind::TyParam => genv.tcx().parent(def_id),
995 _ => def_id,
996 };
997 let ty = genv.lower_type_of(def_id)?.skip_binder();
998 Ok(rty::EarlyBinder(
999 Refiner::default_for_item(genv, generics_def_id)?
1000 .refine_ty_or_base(&ty)?
1001 .into(),
1002 ))
1003 },
1004 )
1005 })
1006 }
1007
1008 pub(crate) fn variants_of(
1009 &self,
1010 genv: GlobalEnv,
1011 def_id: DefId,
1012 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>> {
1013 run_with_cache(&self.variants_of, def_id, || {
1014 def_id.dispatch_query(
1015 genv,
1016 self,
1017 |def_id| (self.providers.variants_of)(genv, def_id),
1018 |def_id| genv.cstore().variants_of(def_id),
1019 |def_id| {
1020 let variants = genv
1021 .tcx()
1022 .adt_def(def_id)
1023 .variants()
1024 .indices()
1025 .map(|variant_idx| {
1026 Refiner::default_for_item(genv, def_id)?
1027 .refine_variant_def(def_id, variant_idx)
1028 })
1029 .try_collect()?;
1030 Ok(rty::Opaqueness::Transparent(rty::EarlyBinder(variants)))
1031 },
1032 )
1033 })
1034 }
1035
1036 pub(crate) fn fn_sig(
1037 &self,
1038 genv: GlobalEnv,
1039 def_id: DefId,
1040 ) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>> {
1041 run_with_cache(&self.fn_sig, def_id, || {
1042 def_id.dispatch_query(
1043 genv,
1044 self,
1045 |def_id| (self.providers.fn_sig)(genv, def_id),
1046 |def_id| genv.cstore().fn_sig(def_id),
1047 |def_id| {
1048 let tcx = genv.tcx();
1049
1050 let mut poly_sig = genv
1051 .lower_fn_sig(def_id)?
1052 .skip_binder()
1053 .refine(&Refiner::default_for_item(genv, def_id)?)?
1054 .hoist_input_binders();
1055 if genv.is_fn_call(def_id) {
1056 let fn_once_id = tcx.require_lang_item(LangItem::FnOnce, DUMMY_SP);
1057
1058 let fn_once_no_panic = genv
1059 .builtin_assoc_refts(fn_once_id)
1060 .unwrap()
1061 .find(sym::no_panic)
1062 .unwrap();
1063
1064 let args = GenericArg::identity_for_item(genv, fn_once_id)?;
1065
1066 let alias_reft = AliasReft { assoc_id: fn_once_no_panic.def_id, args };
1067
1068 poly_sig = poly_sig.map(|mut fn_sig| {
1069 fn_sig.no_panic = Expr::alias(alias_reft, List::empty());
1070 fn_sig
1071 });
1072 }
1073
1074 #[cfg(feature = "suggestions")]
1080 if genv.weak_kvars_for(def_id).is_none() {
1081 match genv.resolve_id(def_id).as_maybe_extern() {
1085 Some(maybe_extern) if !genv.no_suggestions(maybe_extern.local_id()) => {
1086 poly_sig = poly_sig
1087 .add_weak_kvars(genv, maybe_extern.local_id().into())?;
1088 }
1089 _ => {}
1090 }
1091 }
1092 Ok(rty::EarlyBinder(poly_sig))
1093 },
1094 )
1095 })
1096 }
1097}
1098
1099pub trait DispatchKey: Sized + Copy {
1102 type LocalId;
1103
1104 fn dispatch_query<R>(
1105 self,
1106 genv: GlobalEnv,
1107 queries: &Queries,
1108 local: impl FnOnce(Self::LocalId) -> R,
1109 external: impl FnOnce(Self) -> Option<R>,
1110 default: impl FnOnce(Self) -> R,
1111 ) -> R;
1112
1113 fn def_id(self) -> DefId;
1114}
1115
1116impl DispatchKey for DefId {
1117 type LocalId = MaybeExternId;
1118
1119 fn dispatch_query<R>(
1120 self,
1121 genv: GlobalEnv,
1122 queries: &Queries,
1123 local: impl FnOnce(MaybeExternId) -> R,
1124 external: impl FnOnce(Self) -> Option<R>,
1125 default: impl FnOnce(Self) -> R,
1126 ) -> R {
1127 queries.queried_def_ids.borrow_mut().insert(self);
1128 match genv.resolve_id(self) {
1129 ResolvedDefId::Local(local_id) => {
1130 local(MaybeExternId::Local(local_id))
1132 }
1133 ResolvedDefId::ExternSpec(local_id, def_id) => {
1134 local(MaybeExternId::Extern(local_id, def_id))
1137 }
1138 ResolvedDefId::Extern(def_id) if let Some(v) = external(def_id) => {
1139 v
1142 }
1143 ResolvedDefId::Extern(def_id) => {
1144 default(def_id)
1146 }
1147 }
1148 }
1149
1150 fn def_id(self) -> DefId {
1151 self
1152 }
1153}
1154
1155impl DispatchKey for FluxDefId {
1156 type LocalId = FluxId<MaybeExternId>;
1157
1158 fn dispatch_query<R>(
1159 self,
1160 genv: GlobalEnv,
1161 queries: &Queries,
1162 local: impl FnOnce(FluxId<MaybeExternId>) -> R,
1163 external: impl FnOnce(FluxId<DefId>) -> Option<R>,
1164 default: impl FnOnce(FluxId<DefId>) -> R,
1165 ) -> R {
1166 #[allow(
1167 clippy::disallowed_methods,
1168 reason = "we are mapping the parent id to a different representation which still guarantees the existence of the item"
1169 )]
1170 self.parent().dispatch_query(
1171 genv,
1172 queries,
1173 |container_id| local(FluxId::new(container_id, self.name())),
1174 |container_id| external(FluxId::new(container_id, self.name())),
1175 |container_id| default(FluxId::new(container_id, self.name())),
1176 )
1177 }
1178
1179 fn def_id(self) -> DefId {
1180 self.parent()
1181 }
1182}
1183
1184fn run_with_cache<K, V>(cache: &Cache<K, V>, key: K, f: impl FnOnce() -> V) -> V
1185where
1186 K: std::hash::Hash + Eq,
1187 V: Clone,
1188{
1189 if let Some(v) = cache.borrow().get(&key) {
1190 return v.clone();
1191 }
1192 let v = f();
1193 cache.borrow_mut().insert(key, v.clone());
1194 v
1195}
1196
1197impl<'a> Diagnostic<'a> for QueryErr {
1198 #[track_caller]
1199 fn into_diag(
1200 self,
1201 dcx: rustc_errors::DiagCtxtHandle<'a>,
1202 _level: rustc_errors::Level,
1203 ) -> rustc_errors::Diag<'a, ErrorGuaranteed> {
1204 use crate::fluent_generated as fluent;
1205
1206 rustc_middle::ty::tls::with_opt(
1207 #[track_caller]
1208 |tcx| {
1209 let tcx = tcx.expect("no TyCtxt stored in tls");
1210 match self {
1211 QueryErr::Unsupported { def_id, err } => {
1212 let span = err.span.unwrap_or_else(|| tcx.def_span(def_id));
1213 let mut diag = dcx.struct_span_err(span, fluent::middle_query_unsupported);
1214 diag.code(E0999);
1215 diag.note(err.descr);
1216 diag
1217 }
1218 QueryErr::Ignored { def_id } => {
1219 let def_span = tcx.def_span(def_id);
1220 let mut diag =
1221 dcx.struct_span_err(def_span, fluent::middle_query_ignored_item);
1222 diag.code(E0999);
1223 diag
1224 }
1225 QueryErr::NotIncluded { def_id } => {
1226 let def_span = tcx.def_span(def_id);
1227 let mut diag =
1228 dcx.struct_span_err(def_span, fluent::middle_query_not_included_item);
1229 diag.code(E0999);
1230 diag
1231 }
1232 QueryErr::InvalidGenericArg { def_id } => {
1233 let def_span = tcx.def_span(def_id);
1234 let mut diag =
1235 dcx.struct_span_err(def_span, fluent::middle_query_invalid_generic_arg);
1236 diag.code(E0999);
1237 diag
1238 }
1239 QueryErr::MissingAssocReft { impl_id, name, .. } => {
1240 let def_span = tcx.def_span(impl_id);
1241 let mut diag =
1242 dcx.struct_span_err(def_span, fluent::middle_query_missing_assoc_reft);
1243 diag.arg("name", name);
1244 diag.code(E0999);
1245 diag
1246 }
1247 QueryErr::Bug { def_id, location, msg } => {
1248 let mut diag = dcx.struct_err(fluent::middle_query_bug);
1249 if let Some(def_id) = def_id {
1250 diag.span(tcx.def_span(def_id));
1251 }
1252 diag.arg("location", location);
1253 diag.note(msg);
1254 diag
1255 }
1256 QueryErr::Emitted(_) => {
1257 let mut diag = dcx.struct_err("QueryErr::Emitted should be emitted");
1258 diag.downgrade_to_delayed_bug();
1259 diag
1260 }
1261 QueryErr::OpaqueStruct { struct_id } => {
1262 let struct_span = tcx.def_span(struct_id);
1263 let mut diag =
1264 dcx.struct_span_err(struct_span, fluent::middle_query_opaque_struct);
1265 diag.arg("struct", tcx.def_path_str(struct_id));
1266 diag
1267 }
1268 }
1269 },
1270 )
1271 }
1272}
1273
1274impl<'a> Diagnostic<'a> for QueryErrAt {
1275 #[track_caller]
1276 fn into_diag(
1277 self,
1278 dcx: rustc_errors::DiagCtxtHandle<'a>,
1279 level: rustc_errors::Level,
1280 ) -> rustc_errors::Diag<'a, ErrorGuaranteed> {
1281 use crate::fluent_generated as fluent;
1282
1283 rustc_middle::ty::tls::with_opt(
1284 #[track_caller]
1285 |tcx| {
1286 let tcx = tcx.expect("no TyCtxt stored in tls");
1287 let cx_span = self.cx.span();
1288 let mut diag = match self.err {
1289 QueryErr::Unsupported { def_id, err, .. } => {
1290 let mut diag =
1291 dcx.struct_span_err(cx_span, fluent::middle_query_unsupported_at);
1292 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1293 if let Some(def_ident_span) = tcx.def_ident_span(def_id) {
1294 diag.span_note(def_ident_span, fluent::_subdiag::note);
1295 }
1296 diag.note(err.descr);
1297 diag
1298 }
1299 QueryErr::Ignored { def_id } => {
1300 let mut diag =
1301 dcx.struct_span_err(cx_span, fluent::middle_query_ignored_at);
1302 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1303 diag.arg("name", def_id_to_string(def_id));
1304 diag.span_label(cx_span, fluent::_subdiag::label);
1305 diag
1306 }
1307 QueryErr::NotIncluded { def_id } => {
1308 let mut diag =
1309 dcx.struct_span_err(cx_span, fluent::middle_query_not_included_at);
1310 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1311 diag.arg("name", def_id_to_string(def_id));
1312 let span = tcx
1313 .def_ident_span(def_id)
1314 .unwrap_or_else(|| tcx.def_span(def_id));
1315 diag.span_help(span, fluent::_subdiag::help);
1316 diag
1317 }
1318 QueryErr::MissingAssocReft { name, .. } => {
1319 let mut diag = dcx
1320 .struct_span_err(cx_span, fluent::middle_query_missing_assoc_reft_at);
1321 diag.arg("name", name);
1322 diag.code(E0999);
1323 diag
1324 }
1325 QueryErr::OpaqueStruct { struct_id } => {
1326 let mut diag =
1327 dcx.struct_span_err(cx_span, fluent::middle_query_opaque_struct);
1328 diag.arg("struct", tcx.def_path_str(struct_id));
1329 diag.span_label(cx_span, fluent::_subdiag::label);
1330 if let ErrCtxt::FnCheck(_, fn_def_id) = self.cx {
1331 let fn_span = tcx.def_span(fn_def_id);
1332 diag.arg("def_kind", tcx.def_descr(fn_def_id.to_def_id()));
1333 diag.span_label(fn_span, fluent::middle_query_opaque_struct_help);
1334 diag.note(fluent::middle_query_opaque_struct_note);
1335 }
1336 diag
1337 }
1338 QueryErr::InvalidGenericArg { .. }
1339 | QueryErr::Emitted(_)
1340 | QueryErr::Bug { .. } => {
1341 let mut diag = self.err.into_diag(dcx, level);
1342 diag.span(cx_span);
1343 diag
1344 }
1345 };
1346 diag.code(E0999);
1347 diag
1348 },
1349 )
1350 }
1351}
1352
1353impl From<ErrorGuaranteed> for QueryErr {
1354 fn from(err: ErrorGuaranteed) -> Self {
1355 Self::Emitted(err)
1356 }
1357}
1358
1359pub fn try_query<T>(f: impl FnOnce() -> QueryResult<T>) -> QueryResult<T> {
1360 f()
1361}