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