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