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