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