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