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_errors::{E0999, ErrorGuaranteed};
9use flux_rustc_bridge::{
10 self, def_id_to_string,
11 lowering::{self, Lower, UnsupportedErr},
12 mir::{self},
13 ty,
14};
15use itertools::Itertools;
16use rustc_data_structures::unord::{ExtendUnord, UnordMap};
17use rustc_errors::Diagnostic;
18use rustc_hir::{
19 def::DefKind,
20 def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId},
21};
22use rustc_index::IndexVec;
23use rustc_macros::{Decodable, Encodable};
24use rustc_span::{Span, Symbol};
25
26use crate::{
27 def_id::{FluxDefId, FluxId, MaybeExternId, ResolvedDefId},
28 fhir,
29 global_env::GlobalEnv,
30 rty::{
31 self,
32 refining::{self, Refine, Refiner},
33 },
34};
35
36type Cache<K, V> = RefCell<UnordMap<K, V>>;
37
38pub type QueryResult<T = ()> = Result<T, QueryErr>;
39
40#[derive(Debug, Clone, Encodable, Decodable)]
65pub enum QueryErr {
66 Unsupported {
67 def_id: DefId,
68 err: UnsupportedErr,
69 },
70 Ignored {
71 def_id: DefId,
72 },
73 InvalidGenericArg {
74 def_id: DefId,
75 },
76 MissingAssocReft {
77 impl_id: DefId,
78 trait_id: DefId,
79 name: Symbol,
80 },
81 OpaqueStruct {
83 struct_id: DefId,
84 },
85 Bug {
89 def_id: Option<DefId>,
90 location: String,
91 msg: String,
92 },
93 Emitted(ErrorGuaranteed),
94}
95
96#[macro_export]
97macro_rules! query_bug {
98 ($fmt:literal $(,$args:expr)* $(,)?) => {
99 $crate::queries::QueryErr::bug(None, format_args!($fmt, $($args),*))
100 };
101 ($def_id:expr, $fmt:literal $(,$args:expr)* $(,)? ) => {{
102 $crate::queries::QueryErr::bug(Some($def_id.into()), format_args!($fmt, $($args),*))
103 }};
104}
105
106impl QueryErr {
107 pub fn unsupported(def_id: DefId, err: UnsupportedErr) -> Self {
108 QueryErr::Unsupported { def_id, err }
109 }
110
111 #[track_caller]
112 pub fn bug(def_id: Option<DefId>, msg: impl ToString) -> Self {
113 QueryErr::Bug {
114 def_id,
115 location: format!("{}", std::panic::Location::caller()),
116 msg: msg.to_string(),
117 }
118 }
119
120 pub fn at(self, cx: impl Into<ErrCtxt>) -> QueryErrAt {
121 QueryErrAt { cx: cx.into(), err: self }
122 }
123}
124
125pub struct QueryErrAt {
127 cx: ErrCtxt,
128 err: QueryErr,
129}
130
131#[derive(Clone, Copy)]
133pub enum ErrCtxt {
134 FnCheck(Span, LocalDefId),
137 Misc(Span),
139}
140
141impl From<Span> for ErrCtxt {
142 fn from(v: Span) -> Self {
143 Self::Misc(v)
144 }
145}
146
147impl ErrCtxt {
148 fn span(self) -> Span {
149 match self {
150 ErrCtxt::Misc(span) => span,
151 ErrCtxt::FnCheck(span, _) => span,
152 }
153 }
154}
155
156pub struct Providers {
157 pub collect_specs: fn(GlobalEnv) -> crate::Specs,
158 pub resolve_crate: fn(GlobalEnv) -> crate::ResolverOutput,
159 pub desugar: for<'genv> fn(
160 GlobalEnv<'genv, '_>,
161 LocalDefId,
162 ) -> QueryResult<UnordMap<LocalDefId, fhir::Node<'genv>>>,
163 pub fhir_attr_map: for<'genv> fn(GlobalEnv<'genv, '_>, LocalDefId) -> fhir::AttrMap<'genv>,
164 pub fhir_crate: for<'genv> fn(GlobalEnv<'genv, '_>) -> fhir::FluxItems<'genv>,
165 pub qualifiers: fn(GlobalEnv) -> QueryResult<Vec<rty::Qualifier>>,
166 pub prim_rel: fn(GlobalEnv) -> QueryResult<UnordMap<rty::BinOp, rty::PrimRel>>,
167 pub normalized_defns: fn(GlobalEnv) -> rty::NormalizedDefns,
168 pub func_sort: fn(GlobalEnv, FluxId<MaybeExternId>) -> rty::PolyFuncSort,
169 pub func_span: fn(GlobalEnv, FluxId<MaybeExternId>) -> Span,
170 pub adt_sort_def_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AdtSortDef>,
171 pub check_wf: fn(GlobalEnv, LocalDefId) -> QueryResult<Rc<rty::WfckResults>>,
172 pub adt_def: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AdtDef>,
173 pub constant_info: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::ConstantInfo>,
174 pub type_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>>,
175 pub variants_of: fn(
176 GlobalEnv,
177 MaybeExternId,
178 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>>,
179 pub fn_sig: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>>,
180 pub generics_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::Generics>,
181 pub refinement_generics_of:
182 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>>,
183 pub predicates_of:
184 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>>,
185 pub assoc_refinements_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AssocRefinements>,
186 pub sort_of_assoc_reft:
187 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<rty::EarlyBinder<rty::FuncSort>>,
188 pub assoc_refinement_body:
189 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<rty::EarlyBinder<rty::Lambda>>,
190 #[allow(clippy::type_complexity)]
191 pub default_assoc_refinement_body:
192 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>>,
193 pub item_bounds:
194 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>>,
195 pub sort_decl_param_count: fn(GlobalEnv, FluxId<MaybeExternId>) -> usize,
196}
197
198macro_rules! empty_query {
199 () => {
200 flux_common::bug!("query not provided")
201 };
202}
203
204impl Default for Providers {
205 fn default() -> Self {
206 Self {
207 collect_specs: |_| empty_query!(),
208 resolve_crate: |_| empty_query!(),
209 desugar: |_, _| empty_query!(),
210 fhir_attr_map: |_, _| empty_query!(),
211 fhir_crate: |_| empty_query!(),
212 normalized_defns: |_| empty_query!(),
213 func_sort: |_, _| empty_query!(),
214 func_span: |_, _| empty_query!(),
215 qualifiers: |_| empty_query!(),
216 prim_rel: |_| empty_query!(),
217 adt_sort_def_of: |_, _| empty_query!(),
218 check_wf: |_, _| empty_query!(),
219 adt_def: |_, _| empty_query!(),
220 type_of: |_, _| empty_query!(),
221 variants_of: |_, _| empty_query!(),
222 fn_sig: |_, _| empty_query!(),
223 generics_of: |_, _| empty_query!(),
224 refinement_generics_of: |_, _| empty_query!(),
225 predicates_of: |_, _| empty_query!(),
226 assoc_refinements_of: |_, _| empty_query!(),
227 assoc_refinement_body: |_, _| empty_query!(),
228 default_assoc_refinement_body: |_, _| empty_query!(),
229 sort_of_assoc_reft: |_, _| empty_query!(),
230 item_bounds: |_, _| empty_query!(),
231 constant_info: |_, _| empty_query!(),
232 sort_decl_param_count: |_, _| empty_query!(),
233 }
234 }
235}
236
237pub struct Queries<'genv, 'tcx> {
238 pub(crate) providers: Providers,
239 mir: Cache<LocalDefId, QueryResult<Rc<mir::BodyRoot<'tcx>>>>,
240 collect_specs: OnceCell<crate::Specs>,
241 resolve_crate: OnceCell<crate::ResolverOutput>,
242 desugar: Cache<LocalDefId, QueryResult<fhir::Node<'genv>>>,
243 fhir_attr_map: Cache<LocalDefId, fhir::AttrMap<'genv>>,
244 fhir_crate: OnceCell<fhir::FluxItems<'genv>>,
245 lower_generics_of: Cache<DefId, ty::Generics<'tcx>>,
246 lower_predicates_of: Cache<DefId, QueryResult<ty::GenericPredicates>>,
247 lower_type_of: Cache<DefId, QueryResult<ty::EarlyBinder<ty::Ty>>>,
248 lower_fn_sig: Cache<DefId, QueryResult<ty::EarlyBinder<ty::PolyFnSig>>>,
249 normalized_defns: Cache<CrateNum, Rc<rty::NormalizedDefns>>,
250 func_sort: Cache<FluxDefId, rty::PolyFuncSort>,
251 func_span: Cache<FluxDefId, Span>,
252 qualifiers: OnceCell<QueryResult<Vec<rty::Qualifier>>>,
253 prim_rel: OnceCell<QueryResult<UnordMap<rty::BinOp, rty::PrimRel>>>,
254 adt_sort_def_of: Cache<DefId, QueryResult<rty::AdtSortDef>>,
255 check_wf: Cache<LocalDefId, QueryResult<Rc<rty::WfckResults>>>,
256 adt_def: Cache<DefId, QueryResult<rty::AdtDef>>,
257 constant_info: Cache<DefId, QueryResult<rty::ConstantInfo>>,
258 generics_of: Cache<DefId, QueryResult<rty::Generics>>,
259 refinement_generics_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::RefinementGenerics>>>,
260 predicates_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::GenericPredicates>>>,
261 assoc_refinements_of: Cache<DefId, QueryResult<rty::AssocRefinements>>,
262 assoc_refinement_body: Cache<FluxDefId, QueryResult<rty::EarlyBinder<rty::Lambda>>>,
263 default_assoc_refinement_body:
264 Cache<FluxDefId, QueryResult<Option<rty::EarlyBinder<rty::Lambda>>>>,
265 sort_of_assoc_reft: Cache<FluxDefId, QueryResult<rty::EarlyBinder<rty::FuncSort>>>,
266 item_bounds: Cache<DefId, QueryResult<rty::EarlyBinder<List<rty::Clause>>>>,
267 type_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::TyOrCtor>>>,
268 variants_of: Cache<DefId, QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>>>,
269 fn_sig: Cache<DefId, QueryResult<rty::EarlyBinder<rty::PolyFnSig>>>,
270 lower_late_bound_vars: Cache<LocalDefId, QueryResult<List<ty::BoundVariableKind>>>,
271 sort_decl_param_count: Cache<FluxDefId, usize>,
272 no_panic: Cache<DefId, bool>,
273}
274
275impl<'genv, 'tcx> Queries<'genv, 'tcx> {
276 pub(crate) fn new(providers: Providers) -> Self {
277 Self {
278 providers,
279 mir: Default::default(),
280 collect_specs: Default::default(),
281 resolve_crate: Default::default(),
282 desugar: Default::default(),
283 fhir_attr_map: Default::default(),
284 fhir_crate: Default::default(),
285 lower_generics_of: Default::default(),
286 lower_predicates_of: Default::default(),
287 lower_type_of: Default::default(),
288 lower_fn_sig: Default::default(),
289 normalized_defns: Default::default(),
290 func_sort: Default::default(),
291 func_span: Default::default(),
292 qualifiers: Default::default(),
293 prim_rel: Default::default(),
294 adt_sort_def_of: Default::default(),
295 check_wf: Default::default(),
296 adt_def: Default::default(),
297 constant_info: Default::default(),
298 generics_of: Default::default(),
299 refinement_generics_of: Default::default(),
300 predicates_of: Default::default(),
301 assoc_refinements_of: Default::default(),
302 assoc_refinement_body: Default::default(),
303 default_assoc_refinement_body: Default::default(),
304 sort_of_assoc_reft: Default::default(),
305 item_bounds: Default::default(),
306 type_of: Default::default(),
307 variants_of: Default::default(),
308 fn_sig: Default::default(),
309 lower_late_bound_vars: Default::default(),
310 sort_decl_param_count: Default::default(),
311 no_panic: Default::default(),
312 }
313 }
314
315 pub(crate) fn mir(
316 &self,
317 genv: GlobalEnv<'genv, 'tcx>,
318 def_id: LocalDefId,
319 ) -> QueryResult<Rc<mir::BodyRoot<'tcx>>> {
320 run_with_cache(&self.mir, def_id, || {
321 let mir = unsafe { flux_common::mir_storage::retrieve_mir_body(genv.tcx(), def_id) };
322 let mir =
323 lowering::MirLoweringCtxt::lower_mir_body(genv.tcx(), genv.sess(), def_id, mir)?;
324 Ok(Rc::new(mir))
325 })
326 }
327
328 pub(crate) fn collect_specs(&'genv self, genv: GlobalEnv<'genv, 'tcx>) -> &'genv crate::Specs {
329 self.collect_specs
330 .get_or_init(|| (self.providers.collect_specs)(genv))
331 }
332
333 pub(crate) fn resolve_crate(
334 &'genv self,
335 genv: GlobalEnv<'genv, 'tcx>,
336 ) -> &'genv crate::ResolverOutput {
337 self.resolve_crate
338 .get_or_init(|| (self.providers.resolve_crate)(genv))
339 }
340
341 pub(crate) fn desugar(
342 &'genv self,
343 genv: GlobalEnv<'genv, 'tcx>,
344 def_id: LocalDefId,
345 ) -> QueryResult<fhir::Node<'genv>> {
346 if let Some(v) = self.desugar.borrow().get(&def_id) {
347 return v.clone();
348 }
349 match (self.providers.desugar)(genv, def_id) {
350 Ok(nodes) => {
351 let mut cache = self.desugar.borrow_mut();
352 cache.extend_unord(nodes.into_items().map(|(def_id, node)| (def_id, Ok(node))));
353 let Some(res) = cache.get(&def_id) else {
354 tracked_span_bug!("cannot desugar {def_id:?}")
355 };
356 res.clone()
357 }
358 Err(err) => {
359 self.desugar.borrow_mut().insert(def_id, Err(err.clone()));
360 Err(err)
361 }
362 }
363 }
364
365 pub(crate) fn fhir_attr_map(
366 &'genv self,
367 genv: GlobalEnv<'genv, 'tcx>,
368 def_id: LocalDefId,
369 ) -> fhir::AttrMap<'genv> {
370 run_with_cache(&self.fhir_attr_map, def_id, || (self.providers.fhir_attr_map)(genv, def_id))
371 }
372
373 pub(crate) fn fhir_crate(
374 &'genv self,
375 genv: GlobalEnv<'genv, 'tcx>,
376 ) -> &'genv fhir::FluxItems<'genv> {
377 self.fhir_crate
378 .get_or_init(|| (self.providers.fhir_crate)(genv))
379 }
380
381 pub(crate) fn lower_generics_of(
382 &self,
383 genv: GlobalEnv<'genv, 'tcx>,
384 def_id: DefId,
385 ) -> ty::Generics<'tcx> {
386 run_with_cache(&self.lower_generics_of, def_id, || {
387 genv.tcx().generics_of(def_id).lower(genv.tcx())
388 })
389 }
390
391 pub(crate) fn lower_predicates_of(
392 &self,
393 genv: GlobalEnv,
394 def_id: DefId,
395 ) -> QueryResult<ty::GenericPredicates> {
396 run_with_cache(&self.lower_predicates_of, def_id, || {
397 genv.tcx()
398 .predicates_of(def_id)
399 .lower(genv.tcx())
400 .map_err(|err| QueryErr::unsupported(def_id, err))
401 })
402 }
403
404 pub(crate) fn lower_type_of(
405 &self,
406 genv: GlobalEnv,
407 def_id: DefId,
408 ) -> QueryResult<ty::EarlyBinder<ty::Ty>> {
409 run_with_cache(&self.lower_type_of, def_id, || {
410 let ty = genv.tcx().type_of(def_id).instantiate_identity();
411 Ok(ty::EarlyBinder(
412 ty.lower(genv.tcx())
413 .map_err(|err| QueryErr::unsupported(def_id, err.into_err()))?,
414 ))
415 })
416 }
417
418 pub(crate) fn lower_fn_sig(
419 &self,
420 genv: GlobalEnv,
421 def_id: DefId,
422 ) -> QueryResult<ty::EarlyBinder<ty::PolyFnSig>> {
423 run_with_cache(&self.lower_fn_sig, def_id, || {
424 let fn_sig = genv.tcx().fn_sig(def_id).instantiate_identity();
425 Ok(ty::EarlyBinder(
426 fn_sig
427 .lower(genv.tcx())
428 .map_err(|err| QueryErr::unsupported(def_id, err.into_err()))?,
429 ))
430 })
431 }
432
433 pub(crate) fn lower_late_bound_vars(
434 &self,
435 genv: GlobalEnv,
436 def_id: LocalDefId,
437 ) -> QueryResult<List<ty::BoundVariableKind>> {
438 run_with_cache(&self.lower_late_bound_vars, def_id, || {
439 let hir_id = genv.tcx().local_def_id_to_hir_id(def_id);
440 genv.tcx()
441 .late_bound_vars(hir_id)
442 .lower(genv.tcx())
443 .map_err(|err| QueryErr::unsupported(def_id.to_def_id(), err.into_err()))
444 })
445 }
446
447 pub(crate) fn normalized_defns(
448 &self,
449 genv: GlobalEnv,
450 krate: CrateNum,
451 ) -> Rc<rty::NormalizedDefns> {
452 run_with_cache(&self.normalized_defns, krate, || {
453 if krate == LOCAL_CRATE {
454 Rc::new((self.providers.normalized_defns)(genv))
455 } else {
456 genv.cstore().normalized_defns(krate)
457 }
458 })
459 }
460
461 pub(crate) fn func_sort(&self, genv: GlobalEnv, def_id: FluxDefId) -> rty::PolyFuncSort {
462 run_with_cache(&self.func_sort, def_id, || {
463 def_id.dispatch_query(
464 genv,
465 |def_id| {
466 (self.providers.func_sort)(genv, def_id)
468 },
469 |def_id| genv.cstore().func_sort(def_id),
470 |_| {
471 bug!(
472 "cannot generate default function sort, the refinement must be defined somewhere"
473 )
474 },
475 )
476 })
477 }
478
479 pub(crate) fn func_span(&self, genv: GlobalEnv, def_id: FluxDefId) -> Span {
480 run_with_cache(&self.func_span, def_id, || {
481 def_id.dispatch_query(
482 genv,
483 |def_id| {
484 (self.providers.func_span)(genv, def_id)
486 },
487 |def_id| genv.cstore().func_span(def_id),
488 |_|
489 bug!(
490 "cannot generate default function sort, the refinement must be defined somewhere"
491 )
492 ,
493 )
494 })
495 }
496
497 pub(crate) fn qualifiers(&self, genv: GlobalEnv) -> QueryResult<&[rty::Qualifier]> {
498 self.qualifiers
499 .get_or_init(|| (self.providers.qualifiers)(genv))
500 .as_deref()
501 .map_err(Clone::clone)
502 }
503
504 pub(crate) fn prim_rel(
505 &self,
506 genv: GlobalEnv,
507 ) -> QueryResult<&UnordMap<rty::BinOp, rty::PrimRel>> {
508 self.prim_rel
509 .get_or_init(|| (self.providers.prim_rel)(genv))
510 .as_ref()
511 .map_err(|err| err.clone())
512 }
513
514 pub(crate) fn adt_sort_def_of(
515 &self,
516 genv: GlobalEnv,
517 def_id: DefId,
518 ) -> QueryResult<rty::AdtSortDef> {
519 run_with_cache(&self.adt_sort_def_of, def_id, || {
520 def_id.dispatch_query(
521 genv,
522 |def_id| (self.providers.adt_sort_def_of)(genv, def_id),
523 |def_id| genv.cstore().adt_sort_def(def_id),
524 |def_id| {
525 let variants = IndexVec::from([rty::AdtSortVariant::new(vec![])]);
526 Ok(rty::AdtSortDef::new(def_id, vec![], variants, false, true))
527 },
528 )
529 })
530 }
531
532 pub(crate) fn sort_decl_param_count(&self, genv: GlobalEnv, def_id: FluxDefId) -> usize {
533 run_with_cache(&self.sort_decl_param_count, def_id, || {
534 def_id.dispatch_query(
535 genv,
536 |def_id| {
537 (self.providers.sort_decl_param_count)(genv, def_id)
538 },
539 |def_id| genv.cstore().sort_decl_param_count(def_id),
540 |_| {
541 bug!(
542 "cannot generate default param count for sort declaration, it must be defined somewhere"
543 )
544 }
545 )
546 })
547 }
548
549 pub(crate) fn check_wf(
550 &self,
551 genv: GlobalEnv<'genv, '_>,
552 def_id: LocalDefId,
553 ) -> QueryResult<Rc<rty::WfckResults>> {
554 run_with_cache(&self.check_wf, def_id, || (self.providers.check_wf)(genv, def_id))
555 }
556
557 pub(crate) fn constant_info(
558 &self,
559 genv: GlobalEnv,
560 def_id: DefId,
561 ) -> QueryResult<rty::ConstantInfo> {
562 run_with_cache(&self.constant_info, def_id, || {
563 def_id.dispatch_query(
564 genv,
565 |def_id| (self.providers.constant_info)(genv, def_id),
566 |def_id| genv.cstore().constant_info(def_id),
567 |def_id| {
568 let ty = genv.tcx().type_of(def_id).no_bound_vars().unwrap();
570 if ty.is_integral() {
571 let val = genv.tcx().const_eval_poly(def_id).ok().and_then(|val| {
572 let val = val.try_to_scalar_int()?;
573 rty::Constant::from_scalar_int(genv.tcx(), val, &ty)
574 });
575 if let Some(constant_) = val {
576 return Ok(rty::ConstantInfo::Interpreted(
577 rty::Expr::constant(constant_),
578 rty::Sort::Int,
579 ));
580 }
581 }
582 Ok(rty::ConstantInfo::Uninterpreted)
583 },
584 )
585 })
586 }
587
588 pub(crate) fn no_panic(&self, genv: GlobalEnv, def_id: DefId) -> bool {
589 run_with_cache(&self.no_panic, def_id, || {
590 def_id.dispatch_query(
591 genv,
592 |def_id| {
593 let local_id = match def_id {
594 MaybeExternId::Local(def_id) => def_id,
595 MaybeExternId::Extern(def_id, _) => def_id,
596 };
597 genv.fhir_attr_map(local_id).no_panic()
598 },
599 |def_id| genv.cstore().no_panic(def_id),
600 |_| false,
601 )
602 })
603 }
604
605 pub(crate) fn adt_def(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::AdtDef> {
606 run_with_cache(&self.adt_def, def_id, || {
607 def_id.dispatch_query(
608 genv,
609 |def_id| (self.providers.adt_def)(genv, def_id),
610 |def_id| genv.cstore().adt_def(def_id),
611 |def_id| {
612 let adt_def = genv.tcx().adt_def(def_id).lower(genv.tcx());
613 Ok(rty::AdtDef::new(adt_def, genv.adt_sort_def_of(def_id)?, vec![], false))
614 },
615 )
616 })
617 }
618
619 pub(crate) fn generics_of(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::Generics> {
620 run_with_cache(&self.generics_of, def_id, || {
621 def_id.dispatch_query(
622 genv,
623 |def_id| (self.providers.generics_of)(genv, def_id),
624 |def_id| genv.cstore().generics_of(def_id),
625 |def_id| {
626 Ok(refining::refine_generics(genv, def_id, &genv.lower_generics_of(def_id)))
627 },
628 )
629 })
630 }
631
632 pub(crate) fn refinement_generics_of(
633 &self,
634 genv: GlobalEnv,
635 def_id: DefId,
636 ) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>> {
637 run_with_cache(&self.refinement_generics_of, def_id, || {
638 def_id.dispatch_query(
639 genv,
640 |def_id| (self.providers.refinement_generics_of)(genv, def_id),
641 |def_id| genv.cstore().refinement_generics_of(def_id),
642 |def_id| {
643 let parent = genv.tcx().generics_of(def_id).parent;
644 Ok(rty::EarlyBinder(rty::RefinementGenerics {
645 parent,
646 parent_count: 0,
647 own_params: List::empty(),
648 }))
649 },
650 )
651 })
652 }
653
654 pub(crate) fn item_bounds(
655 &self,
656 genv: GlobalEnv<'genv, 'tcx>,
657 def_id: DefId,
658 ) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>> {
659 run_with_cache(&self.item_bounds, def_id, || {
660 def_id.dispatch_query(
661 genv,
662 |def_id| (self.providers.item_bounds)(genv, def_id),
663 |def_id| genv.cstore().item_bounds(def_id),
664 |def_id| {
665 let clauses = genv
666 .tcx()
667 .item_bounds(def_id)
668 .skip_binder()
669 .lower(genv.tcx())
670 .map_err(|err| QueryErr::unsupported(def_id, err))?
671 .refine(&Refiner::default_for_item(genv, def_id)?)?;
672
673 Ok(rty::EarlyBinder(clauses))
674 },
675 )
676 })
677 }
678
679 pub(crate) fn predicates_of(
680 &self,
681 genv: GlobalEnv,
682 def_id: DefId,
683 ) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
684 run_with_cache(&self.predicates_of, def_id, || {
685 def_id.dispatch_query(
686 genv,
687 |def_id| (self.providers.predicates_of)(genv, def_id),
688 |def_id| genv.cstore().predicates_of(def_id),
689 |def_id| {
690 let predicates = genv
691 .lower_predicates_of(def_id)?
692 .refine(&Refiner::default_for_item(genv, def_id)?)?;
693 Ok(rty::EarlyBinder(predicates))
694 },
695 )
696 })
697 }
698
699 pub(crate) fn assoc_refinements_of(
700 &self,
701 genv: GlobalEnv,
702 def_id: DefId,
703 ) -> QueryResult<rty::AssocRefinements> {
704 run_with_cache(&self.assoc_refinements_of, def_id, || {
705 def_id.dispatch_query(
706 genv,
707 |def_id| (self.providers.assoc_refinements_of)(genv, def_id),
708 |def_id| genv.cstore().assoc_refinements_of(def_id),
709 |_| Ok(rty::AssocRefinements::default()),
710 )
711 })
712 }
713
714 pub(crate) fn assoc_refinement_body(
715 &self,
716 genv: GlobalEnv,
717 impl_assoc_id: FluxDefId,
718 ) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
719 run_with_cache(&self.assoc_refinement_body, impl_assoc_id, || {
720 impl_assoc_id.dispatch_query(
721 genv,
722 |impl_assoc_id| (self.providers.assoc_refinement_body)(genv, impl_assoc_id),
723 |impl_assoc_id| genv.cstore().assoc_refinements_def(impl_assoc_id),
724 |impl_assoc_id| {
725 Err(query_bug!(
726 impl_assoc_id.parent(),
727 "cannot generate default associate refinement for extern impl"
728 ))
729 },
730 )
731 })
732 }
733
734 pub(crate) fn default_assoc_refinement_body(
735 &self,
736 genv: GlobalEnv,
737 trait_assoc_id: FluxDefId,
738 ) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>> {
739 run_with_cache(&self.default_assoc_refinement_body, trait_assoc_id, || {
740 trait_assoc_id.dispatch_query(
741 genv,
742 |trait_assoc_id| {
743 (self.providers.default_assoc_refinement_body)(genv, trait_assoc_id)
744 },
745 |trait_assoc_id| genv.cstore().default_assoc_refinements_def(trait_assoc_id),
746 |trait_assoc_id| {
747 Err(query_bug!(
748 trait_assoc_id.parent(),
749 "cannot generate default assoc refinement for extern trait"
750 ))
751 },
752 )
753 })
754 }
755
756 pub(crate) fn sort_of_assoc_reft(
757 &self,
758 genv: GlobalEnv,
759 assoc_id: FluxDefId,
760 ) -> QueryResult<rty::EarlyBinder<rty::FuncSort>> {
761 run_with_cache(&self.sort_of_assoc_reft, assoc_id, || {
762 assoc_id.dispatch_query(
763 genv,
764 |assoc_id| (self.providers.sort_of_assoc_reft)(genv, assoc_id),
765 |assoc_id| genv.cstore().sort_of_assoc_reft(assoc_id),
766 |assoc_id| {
767 Err(query_bug!(
768 assoc_id.parent(),
769 "cannot generate default sort for assoc refinement in extern crate"
770 ))
771 },
772 )
773 })
774 }
775
776 pub(crate) fn type_of(
777 &self,
778 genv: GlobalEnv,
779 def_id: DefId,
780 ) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>> {
781 run_with_cache(&self.type_of, def_id, || {
782 def_id.dispatch_query(
783 genv,
784 |def_id| (self.providers.type_of)(genv, def_id),
785 |def_id| genv.cstore().type_of(def_id),
786 |def_id| {
787 let generics_def_id = match genv.def_kind(def_id) {
789 DefKind::TyParam => genv.tcx().parent(def_id),
790 _ => def_id,
791 };
792 let ty = genv.lower_type_of(def_id)?.skip_binder();
793 Ok(rty::EarlyBinder(
794 Refiner::default_for_item(genv, generics_def_id)?
795 .refine_ty_or_base(&ty)?
796 .into(),
797 ))
798 },
799 )
800 })
801 }
802
803 pub(crate) fn variants_of(
804 &self,
805 genv: GlobalEnv,
806 def_id: DefId,
807 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>> {
808 run_with_cache(&self.variants_of, def_id, || {
809 def_id.dispatch_query(
810 genv,
811 |def_id| (self.providers.variants_of)(genv, def_id),
812 |def_id| genv.cstore().variants_of(def_id),
813 |def_id| {
814 let variants = genv
815 .tcx()
816 .adt_def(def_id)
817 .variants()
818 .indices()
819 .map(|variant_idx| {
820 Refiner::default_for_item(genv, def_id)?
821 .refine_variant_def(def_id, variant_idx)
822 })
823 .try_collect()?;
824 Ok(rty::Opaqueness::Transparent(rty::EarlyBinder(variants)))
825 },
826 )
827 })
828 }
829
830 pub(crate) fn fn_sig(
831 &self,
832 genv: GlobalEnv,
833 def_id: DefId,
834 ) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>> {
835 run_with_cache(&self.fn_sig, def_id, || {
836 def_id.dispatch_query(
837 genv,
838 |def_id| (self.providers.fn_sig)(genv, def_id),
839 |def_id| genv.cstore().fn_sig(def_id),
840 |def_id| {
841 let fn_sig = genv
842 .lower_fn_sig(def_id)?
843 .skip_binder()
844 .refine(&Refiner::default_for_item(genv, def_id)?)?
845 .hoist_input_binders();
846 Ok(rty::EarlyBinder(fn_sig))
847 },
848 )
849 })
850 }
851}
852
853trait DispatchKey: Sized {
856 type LocalId;
857
858 fn dispatch_query<R>(
859 self,
860 genv: GlobalEnv,
861 local: impl FnOnce(Self::LocalId) -> R,
862 external: impl FnOnce(Self) -> Option<R>,
863 default: impl FnOnce(Self) -> R,
864 ) -> R;
865}
866
867impl DispatchKey for DefId {
868 type LocalId = MaybeExternId;
869
870 fn dispatch_query<R>(
871 self,
872 genv: GlobalEnv,
873 local: impl FnOnce(MaybeExternId) -> R,
874 external: impl FnOnce(Self) -> Option<R>,
875 default: impl FnOnce(Self) -> R,
876 ) -> R {
877 match genv.resolve_id(self) {
878 ResolvedDefId::Local(local_id) => {
879 local(MaybeExternId::Local(local_id))
881 }
882 ResolvedDefId::ExternSpec(local_id, def_id) => {
883 local(MaybeExternId::Extern(local_id, def_id))
886 }
887 ResolvedDefId::Extern(def_id) if let Some(v) = external(def_id) => {
888 v
891 }
892 ResolvedDefId::Extern(def_id) => {
893 default(def_id)
895 }
896 }
897 }
898}
899
900impl DispatchKey for FluxDefId {
901 type LocalId = FluxId<MaybeExternId>;
902
903 fn dispatch_query<R>(
904 self,
905 genv: GlobalEnv,
906 local: impl FnOnce(FluxId<MaybeExternId>) -> R,
907 external: impl FnOnce(FluxId<DefId>) -> Option<R>,
908 default: impl FnOnce(FluxId<DefId>) -> R,
909 ) -> R {
910 #[allow(
911 clippy::disallowed_methods,
912 reason = "we are mapping the parent id to a different representation which still guarantees the existence of the item"
913 )]
914 self.parent().dispatch_query(
915 genv,
916 |container_id| local(FluxId::new(container_id, self.name())),
917 |container_id| external(FluxId::new(container_id, self.name())),
918 |container_id| default(FluxId::new(container_id, self.name())),
919 )
920 }
921}
922
923fn run_with_cache<K, V>(cache: &Cache<K, V>, key: K, f: impl FnOnce() -> V) -> V
924where
925 K: std::hash::Hash + Eq,
926 V: Clone,
927{
928 if let Some(v) = cache.borrow().get(&key) {
929 return v.clone();
930 }
931 let v = f();
932 cache.borrow_mut().insert(key, v.clone());
933 v
934}
935
936impl<'a> Diagnostic<'a> for QueryErr {
937 #[track_caller]
938 fn into_diag(
939 self,
940 dcx: rustc_errors::DiagCtxtHandle<'a>,
941 _level: rustc_errors::Level,
942 ) -> rustc_errors::Diag<'a, ErrorGuaranteed> {
943 use crate::fluent_generated as fluent;
944
945 rustc_middle::ty::tls::with_opt(
946 #[track_caller]
947 |tcx| {
948 let tcx = tcx.expect("no TyCtxt stored in tls");
949 match self {
950 QueryErr::Unsupported { def_id, err } => {
951 let span = err.span.unwrap_or_else(|| tcx.def_span(def_id));
952 let mut diag = dcx.struct_span_err(span, fluent::middle_query_unsupported);
953 diag.code(E0999);
954 diag.note(err.descr);
955 diag
956 }
957 QueryErr::Ignored { def_id } => {
958 let def_span = tcx.def_span(def_id);
959 let mut diag =
960 dcx.struct_span_err(def_span, fluent::middle_query_ignored_item);
961 diag.code(E0999);
962 diag
963 }
964 QueryErr::InvalidGenericArg { def_id } => {
965 let def_span = tcx.def_span(def_id);
966 let mut diag =
967 dcx.struct_span_err(def_span, fluent::middle_query_invalid_generic_arg);
968 diag.code(E0999);
969 diag
970 }
971 QueryErr::MissingAssocReft { impl_id, name, .. } => {
972 let def_span = tcx.def_span(impl_id);
973 let mut diag =
974 dcx.struct_span_err(def_span, fluent::middle_query_missing_assoc_reft);
975 diag.arg("name", name);
976 diag.code(E0999);
977 diag
978 }
979 QueryErr::Bug { def_id, location, msg } => {
980 let mut diag = dcx.struct_err(fluent::middle_query_bug);
981 if let Some(def_id) = def_id {
982 diag.span(tcx.def_span(def_id));
983 }
984 diag.arg("location", location);
985 diag.note(msg);
986 diag
987 }
988 QueryErr::Emitted(_) => {
989 let mut diag = dcx.struct_err("QueryErr::Emitted should be emitted");
990 diag.downgrade_to_delayed_bug();
991 diag
992 }
993 QueryErr::OpaqueStruct { struct_id } => {
994 let struct_span = tcx.def_span(struct_id);
995 let mut diag =
996 dcx.struct_span_err(struct_span, fluent::middle_query_opaque_struct);
997 diag.arg("struct", tcx.def_path_str(struct_id));
998 diag
999 }
1000 }
1001 },
1002 )
1003 }
1004}
1005
1006impl<'a> Diagnostic<'a> for QueryErrAt {
1007 #[track_caller]
1008 fn into_diag(
1009 self,
1010 dcx: rustc_errors::DiagCtxtHandle<'a>,
1011 level: rustc_errors::Level,
1012 ) -> rustc_errors::Diag<'a, ErrorGuaranteed> {
1013 use crate::fluent_generated as fluent;
1014
1015 rustc_middle::ty::tls::with_opt(
1016 #[track_caller]
1017 |tcx| {
1018 let tcx = tcx.expect("no TyCtxt stored in tls");
1019 let cx_span = self.cx.span();
1020 let mut diag = match self.err {
1021 QueryErr::Unsupported { def_id, err, .. } => {
1022 let mut diag =
1023 dcx.struct_span_err(cx_span, fluent::middle_query_unsupported_at);
1024 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1025 if let Some(def_ident_span) = tcx.def_ident_span(def_id) {
1026 diag.span_note(def_ident_span, fluent::_subdiag::note);
1027 }
1028 diag.note(err.descr);
1029 diag
1030 }
1031 QueryErr::Ignored { def_id } => {
1032 let mut diag =
1033 dcx.struct_span_err(cx_span, fluent::middle_query_ignored_at);
1034 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1035 diag.arg("name", def_id_to_string(def_id));
1036 diag.span_label(cx_span, fluent::_subdiag::label);
1037 diag
1038 }
1039 QueryErr::MissingAssocReft { name, .. } => {
1040 let mut diag = dcx
1041 .struct_span_err(cx_span, fluent::middle_query_missing_assoc_reft_at);
1042 diag.arg("name", name);
1043 diag.code(E0999);
1044 diag
1045 }
1046 QueryErr::OpaqueStruct { struct_id } => {
1047 let mut diag =
1048 dcx.struct_span_err(cx_span, fluent::middle_query_opaque_struct);
1049 diag.arg("struct", tcx.def_path_str(struct_id));
1050 diag.span_label(cx_span, fluent::_subdiag::label);
1051 if let ErrCtxt::FnCheck(_, fn_def_id) = self.cx {
1052 let fn_span = tcx.def_span(fn_def_id);
1053 diag.arg("def_kind", tcx.def_descr(fn_def_id.to_def_id()));
1054 diag.span_label(fn_span, fluent::middle_query_opaque_struct_help);
1055 diag.note(fluent::middle_query_opaque_struct_note);
1056 }
1057 diag
1058 }
1059 QueryErr::InvalidGenericArg { .. }
1060 | QueryErr::Emitted(_)
1061 | QueryErr::Bug { .. } => {
1062 let mut diag = self.err.into_diag(dcx, level);
1063 diag.span(cx_span);
1064 diag
1065 }
1066 };
1067 diag.code(E0999);
1068 diag
1069 },
1070 )
1071 }
1072}
1073
1074impl From<ErrorGuaranteed> for QueryErr {
1075 fn from(err: ErrorGuaranteed) -> Self {
1076 Self::Emitted(err)
1077 }
1078}
1079
1080pub fn try_query<T>(f: impl FnOnce() -> QueryResult<T>) -> QueryResult<T> {
1081 f()
1082}