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 lower_late_bound_vars: Cache<LocalDefId, QueryResult<List<ty::BoundVariableKind>>>,
288 sort_decl_param_count: Cache<FluxDefId, usize>,
289 no_panic: Cache<DefId, bool>,
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 lower_late_bound_vars: Default::default(),
329 sort_decl_param_count: Default::default(),
330 no_panic: 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 lower_late_bound_vars(
457 &self,
458 genv: GlobalEnv,
459 def_id: LocalDefId,
460 ) -> QueryResult<List<ty::BoundVariableKind>> {
461 run_with_cache(&self.lower_late_bound_vars, def_id, || {
462 let hir_id = genv.tcx().local_def_id_to_hir_id(def_id);
463 genv.tcx()
464 .late_bound_vars(hir_id)
465 .lower(genv.tcx())
466 .map_err(|err| QueryErr::unsupported(def_id.to_def_id(), err.into_err()))
467 })
468 }
469
470 pub(crate) fn normalized_defns(
471 &self,
472 genv: GlobalEnv,
473 krate: CrateNum,
474 ) -> Rc<rty::NormalizedDefns> {
475 run_with_cache(&self.normalized_defns, krate, || {
476 if krate == LOCAL_CRATE {
477 Rc::new((self.providers.normalized_defns)(genv))
478 } else {
479 genv.cstore().normalized_defns(krate)
480 }
481 })
482 }
483
484 pub(crate) fn func_sort(&self, genv: GlobalEnv, def_id: FluxDefId) -> rty::PolyFuncSort {
485 run_with_cache(&self.func_sort, def_id, || {
486 def_id.dispatch_query(
487 genv,
488 self,
489 |def_id| {
490 (self.providers.func_sort)(genv, def_id)
492 },
493 |def_id| genv.cstore().func_sort(def_id),
494 |_| {
495 bug!(
496 "cannot generate default function sort, the refinement must be defined somewhere"
497 )
498 },
499 )
500 })
501 }
502
503 pub(crate) fn func_span(&self, genv: GlobalEnv, def_id: FluxDefId) -> Span {
504 run_with_cache(&self.func_span, def_id, || {
505 def_id.dispatch_query(
506 genv,
507 self,
508 |def_id| {
509 (self.providers.func_span)(genv, def_id)
511 },
512 |def_id| genv.cstore().func_span(def_id),
513 |_|
514 bug!(
515 "cannot generate default function sort, the refinement must be defined somewhere"
516 )
517 ,
518 )
519 })
520 }
521
522 pub(crate) fn qualifiers(&self, genv: GlobalEnv) -> QueryResult<&[rty::Qualifier]> {
523 self.qualifiers
524 .get_or_init(|| (self.providers.qualifiers)(genv))
525 .as_deref()
526 .map_err(Clone::clone)
527 }
528
529 pub(crate) fn prim_rel(
530 &self,
531 genv: GlobalEnv,
532 ) -> QueryResult<&UnordMap<rty::BinOp, rty::PrimRel>> {
533 self.prim_rel
534 .get_or_init(|| (self.providers.prim_rel)(genv))
535 .as_ref()
536 .map_err(|err| err.clone())
537 }
538
539 pub(crate) fn adt_sort_def_of(
540 &self,
541 genv: GlobalEnv,
542 def_id: DefId,
543 ) -> QueryResult<rty::AdtSortDef> {
544 run_with_cache(&self.adt_sort_def_of, def_id, || {
545 def_id.dispatch_query(
546 genv,
547 self,
548 |def_id| (self.providers.adt_sort_def_of)(genv, def_id),
549 |def_id| genv.cstore().adt_sort_def(def_id),
550 |def_id| {
551 let variants = IndexVec::from([rty::AdtSortVariant::new(vec![])]);
552 Ok(rty::AdtSortDef::new(def_id, vec![], variants, false, true))
553 },
554 )
555 })
556 }
557
558 pub(crate) fn sort_decl_param_count(&self, genv: GlobalEnv, def_id: FluxDefId) -> usize {
559 run_with_cache(&self.sort_decl_param_count, def_id, || {
560 def_id.dispatch_query(
561 genv,
562 self,
563 |def_id| {
564 (self.providers.sort_decl_param_count)(genv, def_id)
565 },
566 |def_id| genv.cstore().sort_decl_param_count(def_id),
567 |_| {
568 bug!(
569 "cannot generate default param count for sort declaration, it must be defined somewhere"
570 )
571 }
572 )
573 })
574 }
575
576 pub(crate) fn check_wf(
577 &self,
578 genv: GlobalEnv<'genv, '_>,
579 def_id: LocalDefId,
580 ) -> QueryResult<Rc<rty::WfckResults>> {
581 run_with_cache(&self.check_wf, def_id, || (self.providers.check_wf)(genv, def_id))
582 }
583
584 pub(crate) fn constant_info(
585 &self,
586 genv: GlobalEnv,
587 def_id: DefId,
588 ) -> QueryResult<rty::ConstantInfo> {
589 run_with_cache(&self.constant_info, def_id, || {
590 def_id.dispatch_query(
591 genv,
592 self,
593 |def_id| (self.providers.constant_info)(genv, def_id),
594 |def_id| genv.cstore().constant_info(def_id),
595 |def_id| {
596 let ty = genv.tcx().type_of(def_id).no_bound_vars().unwrap();
598 if ty.is_integral() {
599 let val = genv.tcx().const_eval_poly(def_id).ok().and_then(|val| {
600 let val = val.try_to_scalar_int()?;
601 rty::Constant::from_scalar_int(genv.tcx(), val, &ty)
602 });
603 if let Some(constant_) = val {
604 return Ok(rty::ConstantInfo::Interpreted(
605 rty::Expr::constant(constant_),
606 rty::Sort::Int,
607 ));
608 }
609 }
610 Ok(rty::ConstantInfo::Uninterpreted)
611 },
612 )
613 })
614 }
615
616 pub(crate) fn static_info(
617 &self,
618 genv: GlobalEnv,
619 def_id: DefId,
620 ) -> QueryResult<rty::StaticInfo> {
621 run_with_cache(&self.static_info, def_id, || {
622 def_id.dispatch_query(
623 genv,
624 self,
625 |def_id| (self.providers.static_info)(genv, def_id),
626 |def_id| genv.cstore().static_info(def_id),
627 |_def_id| Ok(rty::StaticInfo::Unknown),
628 )
629 })
630 }
631
632 pub(crate) fn no_panic(&self, genv: GlobalEnv, def_id: DefId) -> bool {
633 run_with_cache(&self.no_panic, def_id, || {
634 def_id.dispatch_query(
635 genv,
636 self,
637 |def_id| {
638 let mut current_id = def_id.local_id();
639
640 loop {
642 if genv.is_dummy(current_id) {
644 if let Some(parent) = genv.tcx().opt_local_parent(current_id) {
645 current_id = parent;
646 continue;
647 } else {
648 return false; }
650 }
651
652 if genv.fhir_attr_map(current_id).no_panic() {
654 return true;
655 }
656
657 if let Some(parent) = genv.tcx().opt_local_parent(current_id) {
659 current_id = parent;
660 } else {
661 break; }
663 }
664
665 config::no_panic()
666 },
667 |def_id| genv.cstore().no_panic(def_id),
668 |_| false,
669 )
670 })
671 }
672
673 pub(crate) fn adt_def(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::AdtDef> {
674 run_with_cache(&self.adt_def, def_id, || {
675 def_id.dispatch_query(
676 genv,
677 self,
678 |def_id| (self.providers.adt_def)(genv, def_id),
679 |def_id| genv.cstore().adt_def(def_id),
680 |def_id| {
681 let adt_def = genv.tcx().adt_def(def_id).lower(genv.tcx());
682 Ok(rty::AdtDef::new(adt_def, genv.adt_sort_def_of(def_id)?, vec![], false))
683 },
684 )
685 })
686 }
687
688 pub(crate) fn generics_of(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::Generics> {
689 if genv.tcx().is_lang_item(def_id, LangItem::OwnedBox) {
693 let generics = genv.lower_generics_of(def_id);
694 debug_assert_eq!(generics.params.len(), 2);
695 let deref_ty = &generics.params[0];
696 let alloc = &generics.params[1];
697 return Ok(rty::Generics {
698 own_params: List::from_arr([
699 refine_generic_param_def(true, deref_ty),
700 refine_generic_param_def(false, alloc),
701 ]),
702 parent: generics.parent(),
703 parent_count: generics.parent_count(),
704 has_self: generics.orig.has_self,
705 });
706 }
707 if genv.tcx().is_lang_item(def_id, LangItem::MetaSized) {
714 let generics = genv.lower_generics_of(def_id);
715 debug_assert_eq!(generics.params.len(), 1);
716 let self_ty = &generics.params[0];
717 return Ok(rty::Generics {
718 own_params: List::from_arr([refine_generic_param_def(true, self_ty)]),
719 parent: generics.parent(),
720 parent_count: generics.parent_count(),
721 has_self: generics.orig.has_self,
722 });
723 }
724
725 run_with_cache(&self.generics_of, def_id, || {
726 def_id.dispatch_query(
727 genv,
728 self,
729 |def_id| (self.providers.generics_of)(genv, def_id),
730 |def_id| genv.cstore().generics_of(def_id),
731 |def_id| Ok(refining::refine_generics(&genv.lower_generics_of(def_id))),
732 )
733 })
734 }
735
736 pub(crate) fn refinement_generics_of(
737 &self,
738 genv: GlobalEnv,
739 def_id: DefId,
740 ) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>> {
741 run_with_cache(&self.refinement_generics_of, def_id, || {
742 def_id.dispatch_query(
743 genv,
744 self,
745 |def_id| (self.providers.refinement_generics_of)(genv, def_id),
746 |def_id| genv.cstore().refinement_generics_of(def_id),
747 |def_id| {
748 let parent = genv.tcx().generics_of(def_id).parent;
749 Ok(rty::EarlyBinder(rty::RefinementGenerics {
750 parent,
751 parent_count: 0,
752 own_params: List::empty(),
753 }))
754 },
755 )
756 })
757 }
758
759 pub(crate) fn item_bounds(
760 &self,
761 genv: GlobalEnv<'genv, 'tcx>,
762 def_id: DefId,
763 ) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>> {
764 run_with_cache(&self.item_bounds, def_id, || {
765 def_id.dispatch_query(
766 genv,
767 self,
768 |def_id| (self.providers.item_bounds)(genv, def_id),
769 |def_id| genv.cstore().item_bounds(def_id),
770 |def_id| {
771 let clauses = genv
772 .tcx()
773 .item_bounds(def_id)
774 .skip_binder()
775 .lower(genv.tcx())
776 .map_err(|err| QueryErr::unsupported(def_id, err))?
777 .refine(&Refiner::default_for_item(genv, def_id)?)?;
778
779 Ok(rty::EarlyBinder(clauses))
780 },
781 )
782 })
783 }
784
785 pub(crate) fn predicates_of(
786 &self,
787 genv: GlobalEnv,
788 def_id: DefId,
789 ) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
790 run_with_cache(&self.predicates_of, def_id, || {
791 def_id.dispatch_query(
792 genv,
793 self,
794 |def_id| (self.providers.predicates_of)(genv, def_id),
795 |def_id| genv.cstore().predicates_of(def_id),
796 |def_id| {
797 let predicates = genv
798 .lower_predicates_of(def_id)?
799 .refine(&Refiner::default_for_item(genv, def_id)?)?;
800 Ok(rty::EarlyBinder(predicates))
801 },
802 )
803 })
804 }
805
806 pub(crate) fn assoc_refinements_of(
807 &self,
808 genv: GlobalEnv,
809 def_id: DefId,
810 ) -> QueryResult<rty::AssocRefinements> {
811 run_with_cache(&self.assoc_refinements_of, def_id, || {
812 def_id.dispatch_query(
813 genv,
814 self,
815 |def_id| (self.providers.assoc_refinements_of)(genv, def_id),
816 |def_id| genv.cstore().assoc_refinements_of(def_id),
817 |def_id| Ok(genv.builtin_assoc_refts(def_id).unwrap_or_default()),
818 )
819 })
820 }
821
822 pub(crate) fn assoc_refinement_body(
823 &self,
824 genv: GlobalEnv,
825 impl_assoc_id: FluxDefId,
826 ) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
827 run_with_cache(&self.assoc_refinement_body, impl_assoc_id, || {
828 impl_assoc_id.dispatch_query(
829 genv,
830 self,
831 |impl_assoc_id| (self.providers.assoc_refinement_body)(genv, impl_assoc_id),
832 |impl_assoc_id| genv.cstore().assoc_refinements_def(impl_assoc_id),
833 |impl_assoc_id| {
834 Err(query_bug!(
835 impl_assoc_id.parent(),
836 "cannot generate default associate refinement for extern impl"
837 ))
838 },
839 )
840 })
841 }
842
843 pub(crate) fn default_assoc_refinement_body(
844 &self,
845 genv: GlobalEnv,
846 trait_assoc_id: FluxDefId,
847 ) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>> {
848 run_with_cache(&self.default_assoc_refinement_body, trait_assoc_id, || {
849 trait_assoc_id.dispatch_query(
850 genv,
851 self,
852 |trait_assoc_id| {
853 (self.providers.default_assoc_refinement_body)(genv, trait_assoc_id)
854 },
855 |trait_assoc_id| genv.cstore().default_assoc_refinements_def(trait_assoc_id),
856 |trait_assoc_id| {
857 Err(query_bug!(
858 trait_assoc_id.parent(),
859 "cannot generate default assoc refinement for extern trait"
860 ))
861 },
862 )
863 })
864 }
865
866 pub(crate) fn sort_of_assoc_reft(
867 &self,
868 genv: GlobalEnv,
869 assoc_id: FluxDefId,
870 ) -> QueryResult<rty::EarlyBinder<rty::FuncSort>> {
871 run_with_cache(&self.sort_of_assoc_reft, assoc_id, || {
872 assoc_id.dispatch_query(
873 genv,
874 self,
875 |assoc_id| (self.providers.sort_of_assoc_reft)(genv, assoc_id),
876 |assoc_id| genv.cstore().sort_of_assoc_reft(assoc_id),
877 |assoc_id| {
878 genv.builtin_assoc_reft_sort(assoc_id).ok_or_else(|| {
879 query_bug!(
880 assoc_id.parent(),
881 "assoc refinement on extern crate is not builtin"
882 )
883 })
884 },
885 )
886 })
887 }
888
889 pub(crate) fn type_of(
890 &self,
891 genv: GlobalEnv,
892 def_id: DefId,
893 ) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>> {
894 run_with_cache(&self.type_of, def_id, || {
895 def_id.dispatch_query(
896 genv,
897 self,
898 |def_id| (self.providers.type_of)(genv, def_id),
899 |def_id| genv.cstore().type_of(def_id),
900 |def_id| {
901 let generics_def_id = match genv.def_kind(def_id) {
903 DefKind::TyParam => genv.tcx().parent(def_id),
904 _ => def_id,
905 };
906 let ty = genv.lower_type_of(def_id)?.skip_binder();
907 Ok(rty::EarlyBinder(
908 Refiner::default_for_item(genv, generics_def_id)?
909 .refine_ty_or_base(&ty)?
910 .into(),
911 ))
912 },
913 )
914 })
915 }
916
917 pub(crate) fn variants_of(
918 &self,
919 genv: GlobalEnv,
920 def_id: DefId,
921 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>> {
922 run_with_cache(&self.variants_of, def_id, || {
923 def_id.dispatch_query(
924 genv,
925 self,
926 |def_id| (self.providers.variants_of)(genv, def_id),
927 |def_id| genv.cstore().variants_of(def_id),
928 |def_id| {
929 let variants = genv
930 .tcx()
931 .adt_def(def_id)
932 .variants()
933 .indices()
934 .map(|variant_idx| {
935 Refiner::default_for_item(genv, def_id)?
936 .refine_variant_def(def_id, variant_idx)
937 })
938 .try_collect()?;
939 Ok(rty::Opaqueness::Transparent(rty::EarlyBinder(variants)))
940 },
941 )
942 })
943 }
944
945 pub(crate) fn fn_sig(
946 &self,
947 genv: GlobalEnv,
948 def_id: DefId,
949 ) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>> {
950 run_with_cache(&self.fn_sig, def_id, || {
951 def_id.dispatch_query(
952 genv,
953 self,
954 |def_id| (self.providers.fn_sig)(genv, def_id),
955 |def_id| genv.cstore().fn_sig(def_id),
956 |def_id| {
957 let tcx = genv.tcx();
958
959 let mut poly_sig = genv
960 .lower_fn_sig(def_id)?
961 .skip_binder()
962 .refine(&Refiner::default_for_item(genv, def_id)?)?
963 .hoist_input_binders();
964
965 if genv.is_fn_call(def_id) {
966 let fn_once_id = tcx.require_lang_item(LangItem::FnOnce, DUMMY_SP);
967
968 let fn_once_no_panic = genv
969 .builtin_assoc_refts(fn_once_id)
970 .unwrap()
971 .find(sym::no_panic)
972 .unwrap();
973
974 let args = GenericArg::identity_for_item(genv, fn_once_id)?;
975
976 let alias_reft = AliasReft { assoc_id: fn_once_no_panic.def_id, args };
977
978 poly_sig = poly_sig.map(|mut fn_sig| {
979 fn_sig.no_panic = Expr::alias(alias_reft, List::empty());
980 fn_sig
981 });
982 }
983
984 Ok(rty::EarlyBinder(poly_sig))
985 },
986 )
987 })
988 }
989}
990
991pub trait DispatchKey: Sized + Copy {
994 type LocalId;
995
996 fn dispatch_query<R>(
997 self,
998 genv: GlobalEnv,
999 queries: &Queries,
1000 local: impl FnOnce(Self::LocalId) -> R,
1001 external: impl FnOnce(Self) -> Option<R>,
1002 default: impl FnOnce(Self) -> R,
1003 ) -> R;
1004
1005 fn def_id(self) -> DefId;
1006}
1007
1008impl DispatchKey for DefId {
1009 type LocalId = MaybeExternId;
1010
1011 fn dispatch_query<R>(
1012 self,
1013 genv: GlobalEnv,
1014 queries: &Queries,
1015 local: impl FnOnce(MaybeExternId) -> R,
1016 external: impl FnOnce(Self) -> Option<R>,
1017 default: impl FnOnce(Self) -> R,
1018 ) -> R {
1019 queries.queried_def_ids.borrow_mut().insert(self);
1020 match genv.resolve_id(self) {
1021 ResolvedDefId::Local(local_id) => {
1022 local(MaybeExternId::Local(local_id))
1024 }
1025 ResolvedDefId::ExternSpec(local_id, def_id) => {
1026 local(MaybeExternId::Extern(local_id, def_id))
1029 }
1030 ResolvedDefId::Extern(def_id) if let Some(v) = external(def_id) => {
1031 v
1034 }
1035 ResolvedDefId::Extern(def_id) => {
1036 default(def_id)
1038 }
1039 }
1040 }
1041
1042 fn def_id(self) -> DefId {
1043 self
1044 }
1045}
1046
1047impl DispatchKey for FluxDefId {
1048 type LocalId = FluxId<MaybeExternId>;
1049
1050 fn dispatch_query<R>(
1051 self,
1052 genv: GlobalEnv,
1053 queries: &Queries,
1054 local: impl FnOnce(FluxId<MaybeExternId>) -> R,
1055 external: impl FnOnce(FluxId<DefId>) -> Option<R>,
1056 default: impl FnOnce(FluxId<DefId>) -> R,
1057 ) -> R {
1058 #[allow(
1059 clippy::disallowed_methods,
1060 reason = "we are mapping the parent id to a different representation which still guarantees the existence of the item"
1061 )]
1062 self.parent().dispatch_query(
1063 genv,
1064 queries,
1065 |container_id| local(FluxId::new(container_id, self.name())),
1066 |container_id| external(FluxId::new(container_id, self.name())),
1067 |container_id| default(FluxId::new(container_id, self.name())),
1068 )
1069 }
1070
1071 fn def_id(self) -> DefId {
1072 self.parent()
1073 }
1074}
1075
1076fn run_with_cache<K, V>(cache: &Cache<K, V>, key: K, f: impl FnOnce() -> V) -> V
1077where
1078 K: std::hash::Hash + Eq,
1079 V: Clone,
1080{
1081 if let Some(v) = cache.borrow().get(&key) {
1082 return v.clone();
1083 }
1084 let v = f();
1085 cache.borrow_mut().insert(key, v.clone());
1086 v
1087}
1088
1089impl<'a> Diagnostic<'a> for QueryErr {
1090 #[track_caller]
1091 fn into_diag(
1092 self,
1093 dcx: rustc_errors::DiagCtxtHandle<'a>,
1094 _level: rustc_errors::Level,
1095 ) -> rustc_errors::Diag<'a, ErrorGuaranteed> {
1096 use crate::fluent_generated as fluent;
1097
1098 rustc_middle::ty::tls::with_opt(
1099 #[track_caller]
1100 |tcx| {
1101 let tcx = tcx.expect("no TyCtxt stored in tls");
1102 match self {
1103 QueryErr::Unsupported { def_id, err } => {
1104 let span = err.span.unwrap_or_else(|| tcx.def_span(def_id));
1105 let mut diag = dcx.struct_span_err(span, fluent::middle_query_unsupported);
1106 diag.code(E0999);
1107 diag.note(err.descr);
1108 diag
1109 }
1110 QueryErr::Ignored { def_id } => {
1111 let def_span = tcx.def_span(def_id);
1112 let mut diag =
1113 dcx.struct_span_err(def_span, fluent::middle_query_ignored_item);
1114 diag.code(E0999);
1115 diag
1116 }
1117 QueryErr::NotIncluded { def_id } => {
1118 let def_span = tcx.def_span(def_id);
1119 let mut diag =
1120 dcx.struct_span_err(def_span, fluent::middle_query_not_included_item);
1121 diag.code(E0999);
1122 diag
1123 }
1124 QueryErr::InvalidGenericArg { def_id } => {
1125 let def_span = tcx.def_span(def_id);
1126 let mut diag =
1127 dcx.struct_span_err(def_span, fluent::middle_query_invalid_generic_arg);
1128 diag.code(E0999);
1129 diag
1130 }
1131 QueryErr::MissingAssocReft { impl_id, name, .. } => {
1132 let def_span = tcx.def_span(impl_id);
1133 let mut diag =
1134 dcx.struct_span_err(def_span, fluent::middle_query_missing_assoc_reft);
1135 diag.arg("name", name);
1136 diag.code(E0999);
1137 diag
1138 }
1139 QueryErr::Bug { def_id, location, msg } => {
1140 let mut diag = dcx.struct_err(fluent::middle_query_bug);
1141 if let Some(def_id) = def_id {
1142 diag.span(tcx.def_span(def_id));
1143 }
1144 diag.arg("location", location);
1145 diag.note(msg);
1146 diag
1147 }
1148 QueryErr::Emitted(_) => {
1149 let mut diag = dcx.struct_err("QueryErr::Emitted should be emitted");
1150 diag.downgrade_to_delayed_bug();
1151 diag
1152 }
1153 QueryErr::OpaqueStruct { struct_id } => {
1154 let struct_span = tcx.def_span(struct_id);
1155 let mut diag =
1156 dcx.struct_span_err(struct_span, fluent::middle_query_opaque_struct);
1157 diag.arg("struct", tcx.def_path_str(struct_id));
1158 diag
1159 }
1160 }
1161 },
1162 )
1163 }
1164}
1165
1166impl<'a> Diagnostic<'a> for QueryErrAt {
1167 #[track_caller]
1168 fn into_diag(
1169 self,
1170 dcx: rustc_errors::DiagCtxtHandle<'a>,
1171 level: rustc_errors::Level,
1172 ) -> rustc_errors::Diag<'a, ErrorGuaranteed> {
1173 use crate::fluent_generated as fluent;
1174
1175 rustc_middle::ty::tls::with_opt(
1176 #[track_caller]
1177 |tcx| {
1178 let tcx = tcx.expect("no TyCtxt stored in tls");
1179 let cx_span = self.cx.span();
1180 let mut diag = match self.err {
1181 QueryErr::Unsupported { def_id, err, .. } => {
1182 let mut diag =
1183 dcx.struct_span_err(cx_span, fluent::middle_query_unsupported_at);
1184 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1185 if let Some(def_ident_span) = tcx.def_ident_span(def_id) {
1186 diag.span_note(def_ident_span, fluent::_subdiag::note);
1187 }
1188 diag.note(err.descr);
1189 diag
1190 }
1191 QueryErr::Ignored { def_id } => {
1192 let mut diag =
1193 dcx.struct_span_err(cx_span, fluent::middle_query_ignored_at);
1194 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1195 diag.arg("name", def_id_to_string(def_id));
1196 diag.span_label(cx_span, fluent::_subdiag::label);
1197 diag
1198 }
1199 QueryErr::NotIncluded { def_id } => {
1200 let mut diag =
1201 dcx.struct_span_err(cx_span, fluent::middle_query_not_included_at);
1202 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1203 diag.arg("name", def_id_to_string(def_id));
1204 if let Some(def_ident_span) = tcx.def_ident_span(def_id) {
1205 diag.span_help(def_ident_span, fluent::_subdiag::help);
1206 }
1207 diag
1208 }
1209 QueryErr::MissingAssocReft { name, .. } => {
1210 let mut diag = dcx
1211 .struct_span_err(cx_span, fluent::middle_query_missing_assoc_reft_at);
1212 diag.arg("name", name);
1213 diag.code(E0999);
1214 diag
1215 }
1216 QueryErr::OpaqueStruct { struct_id } => {
1217 let mut diag =
1218 dcx.struct_span_err(cx_span, fluent::middle_query_opaque_struct);
1219 diag.arg("struct", tcx.def_path_str(struct_id));
1220 diag.span_label(cx_span, fluent::_subdiag::label);
1221 if let ErrCtxt::FnCheck(_, fn_def_id) = self.cx {
1222 let fn_span = tcx.def_span(fn_def_id);
1223 diag.arg("def_kind", tcx.def_descr(fn_def_id.to_def_id()));
1224 diag.span_label(fn_span, fluent::middle_query_opaque_struct_help);
1225 diag.note(fluent::middle_query_opaque_struct_note);
1226 }
1227 diag
1228 }
1229 QueryErr::InvalidGenericArg { .. }
1230 | QueryErr::Emitted(_)
1231 | QueryErr::Bug { .. } => {
1232 let mut diag = self.err.into_diag(dcx, level);
1233 diag.span(cx_span);
1234 diag
1235 }
1236 };
1237 diag.code(E0999);
1238 diag
1239 },
1240 )
1241 }
1242}
1243
1244impl From<ErrorGuaranteed> for QueryErr {
1245 fn from(err: ErrorGuaranteed) -> Self {
1246 Self::Emitted(err)
1247 }
1248}
1249
1250pub fn try_query<T>(f: impl FnOnce() -> QueryResult<T>) -> QueryResult<T> {
1251 f()
1252}