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