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