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_macros::msg;
11use flux_rustc_bridge::{
12 self, def_id_to_string,
13 lowering::{self, Lower, UnsupportedErr},
14 mir::{self},
15 ty,
16};
17use flux_syntax::{surface, symbols::sym};
18use itertools::Itertools;
19use rustc_attr_ir::LangItem;
20use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
21use rustc_errors::{DiagMessage, Diagnostic};
22use rustc_hir::{
23 def::DefKind,
24 def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId},
25};
26use rustc_index::IndexVec;
27use rustc_macros::{Decodable, Encodable};
28use rustc_span::{DUMMY_SP, Span, Symbol};
29
30use crate::{
31 PanicSpec,
32 call_graph::{CallGraph, NodeKey},
33 def_id::{FluxDefId, FluxId, MaybeExternId, ResolvedDefId},
34 fhir,
35 global_env::GlobalEnv,
36 rty::{
37 self, AliasReft, Expr, GenericArg,
38 fold::TypeFoldable,
39 refining::{self, Refine, Refiner, refine_generic_param_def},
40 },
41};
42
43type Cache<K, V> = RefCell<UnordMap<K, V>>;
44
45pub type QueryResult<T = ()> = Result<T, QueryErr>;
46
47#[derive(Debug, Clone, Encodable, Decodable)]
72pub enum QueryErr {
73 Unsupported {
74 def_id: DefId,
75 err: UnsupportedErr,
76 },
77 Ignored {
78 def_id: DefId,
79 },
80 InvalidGenericArg {
81 def_id: DefId,
82 },
83 MissingAssocReft {
84 impl_id: DefId,
85 trait_id: DefId,
86 name: Symbol,
87 },
88 OpaqueStruct {
90 struct_id: DefId,
91 },
92 Bug {
96 def_id: Option<DefId>,
97 location: String,
98 msg: String,
99 },
100 Emitted(ErrorGuaranteed),
101 NotIncluded {
103 def_id: DefId,
104 },
105}
106
107#[macro_export]
108macro_rules! query_bug {
109 ($fmt:literal $(,$args:expr)* $(,)?) => {
110 $crate::queries::QueryErr::bug(None, format_args!($fmt, $($args),*))
111 };
112 ($def_id:expr, $fmt:literal $(,$args:expr)* $(,)? ) => {{
113 $crate::queries::QueryErr::bug(Some($def_id.into()), format_args!($fmt, $($args),*))
114 }};
115}
116
117impl QueryErr {
118 pub fn unsupported(def_id: DefId, err: UnsupportedErr) -> Self {
119 QueryErr::Unsupported { def_id, err }
120 }
121
122 #[track_caller]
123 pub fn bug(def_id: Option<DefId>, msg: impl ToString) -> Self {
124 QueryErr::Bug {
125 def_id,
126 location: format!("{}", std::panic::Location::caller()),
127 msg: msg.to_string(),
128 }
129 }
130
131 pub fn at(self, cx: impl Into<ErrCtxt>) -> QueryErrAt {
132 QueryErrAt { cx: cx.into(), err: self }
133 }
134}
135
136pub struct QueryErrAt {
138 cx: ErrCtxt,
139 err: QueryErr,
140}
141
142#[derive(Clone, Copy)]
144pub enum ErrCtxt {
145 FnCheck(Span, LocalDefId),
148 Misc(Span),
150}
151
152impl From<Span> for ErrCtxt {
153 fn from(v: Span) -> Self {
154 Self::Misc(v)
155 }
156}
157
158impl ErrCtxt {
159 fn span(self) -> Span {
160 match self {
161 ErrCtxt::Misc(span) => span,
162 ErrCtxt::FnCheck(span, _) => span,
163 }
164 }
165}
166
167pub struct Providers {
168 pub collect_specs: fn(GlobalEnv) -> crate::Specs,
169 pub resolve_crate: fn(GlobalEnv) -> crate::ResolverOutput,
170 pub desugar: for<'genv> fn(
171 GlobalEnv<'genv, '_>,
172 LocalDefId,
173 ) -> QueryResult<UnordMap<LocalDefId, fhir::Node<'genv>>>,
174 pub fhir_attr_map: for<'genv> fn(GlobalEnv<'genv, '_>, LocalDefId) -> fhir::AttrMap<'genv>,
175 pub fhir_crate: for<'genv> fn(GlobalEnv<'genv, '_>) -> fhir::FluxItems<'genv>,
176 pub qualifiers: fn(GlobalEnv) -> QueryResult<Vec<rty::Qualifier>>,
177 pub axioms: fn(GlobalEnv) -> QueryResult<Vec<rty::Axiom>>,
178 pub prim_rel: fn(GlobalEnv) -> QueryResult<UnordMap<rty::BinOp, rty::PrimRel>>,
179 pub spec_funcs: fn(GlobalEnv) -> rty::SpecFuncs,
180 pub func_sort: fn(GlobalEnv, FluxId<MaybeExternId>) -> rty::PolyFuncSort,
181 pub func_span: fn(GlobalEnv, FluxId<MaybeExternId>) -> Span,
182 pub adt_sort_def_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AdtSortDef>,
183 pub check_wf: fn(GlobalEnv, LocalDefId) -> QueryResult<Rc<rty::WfckResults>>,
184 pub late_bound_refinement_params:
185 for<'genv> fn(GlobalEnv<'genv, '_>, LocalDefId) -> QueryResult<&'genv [fhir::ParamId]>,
186 pub adt_def: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AdtDef>,
187 pub invariants_of: fn(GlobalEnv, MaybeExternId) -> rty::EarlyBinder<List<rty::Invariant>>,
188 pub constant_info: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::ConstantInfo>,
189 pub static_info: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::Ty>,
190 pub type_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>>,
191 pub variants_of: fn(
192 GlobalEnv,
193 MaybeExternId,
194 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>>,
195 pub fn_sig: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>>,
196 pub generics_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::Generics>,
197 pub refinement_generics_of:
198 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>>,
199 pub predicates_of:
200 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>>,
201 pub assoc_refinements_of: fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::AssocRefinements>,
202 pub sort_of_assoc_reft:
203 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<rty::EarlyBinder<rty::FuncSort>>,
204 pub assoc_refinement_body:
205 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<rty::EarlyBinder<rty::Lambda>>,
206 #[allow(clippy::type_complexity)]
207 pub default_assoc_refinement_body:
208 fn(GlobalEnv, FluxId<MaybeExternId>) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>>,
209 pub item_bounds:
210 fn(GlobalEnv, MaybeExternId) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>>,
211 pub sort_decl_param_count: fn(GlobalEnv, FluxId<MaybeExternId>) -> usize,
212 pub call_graph: for<'genv, 'tcx> fn(GlobalEnv<'genv, 'tcx>) -> CallGraph<'tcx>,
213 pub inferred_no_panic:
214 for<'genv, 'tcx> fn(GlobalEnv<'genv, 'tcx>) -> UnordMap<NodeKey<'tcx>, PanicSpec>,
215}
216
217macro_rules! empty_query {
218 () => {
219 flux_common::bug!("query not provided")
220 };
221}
222
223impl Default for Providers {
224 fn default() -> Self {
225 Self {
226 collect_specs: |_| empty_query!(),
227 resolve_crate: |_| empty_query!(),
228 desugar: |_, _| empty_query!(),
229 fhir_attr_map: |_, _| empty_query!(),
230 fhir_crate: |_| empty_query!(),
231 spec_funcs: |_| empty_query!(),
232 func_sort: |_, _| empty_query!(),
233 func_span: |_, _| empty_query!(),
234 qualifiers: |_| empty_query!(),
235 axioms: |_| empty_query!(),
236 prim_rel: |_| empty_query!(),
237 adt_sort_def_of: |_, _| empty_query!(),
238 check_wf: |_, _| empty_query!(),
239 late_bound_refinement_params: |_, _| empty_query!(),
240 adt_def: |_, _| empty_query!(),
241 invariants_of: |_, _| empty_query!(),
242 type_of: |_, _| empty_query!(),
243 variants_of: |_, _| empty_query!(),
244 fn_sig: |_, _| empty_query!(),
245 generics_of: |_, _| empty_query!(),
246 refinement_generics_of: |_, _| empty_query!(),
247 predicates_of: |_, _| empty_query!(),
248 assoc_refinements_of: |_, _| empty_query!(),
249 assoc_refinement_body: |_, _| empty_query!(),
250 default_assoc_refinement_body: |_, _| empty_query!(),
251 sort_of_assoc_reft: |_, _| empty_query!(),
252 item_bounds: |_, _| empty_query!(),
253 constant_info: |_, _| empty_query!(),
254 static_info: |_, _| empty_query!(),
255 sort_decl_param_count: |_, _| empty_query!(),
256 call_graph: |_| empty_query!(),
257 inferred_no_panic: |_| empty_query!(),
258 }
259 }
260}
261
262pub struct Queries<'genv, 'tcx> {
263 pub(crate) providers: Providers,
264 queried_def_ids: RefCell<UnordSet<DefId>>,
270 mir: Cache<LocalDefId, QueryResult<Rc<mir::BodyRoot<'tcx>>>>,
271 collect_specs: OnceCell<crate::Specs>,
272 resolve_crate: OnceCell<crate::ResolverOutput>,
273 flux_module_children: Cache<DefId, &'genv [fhir::FluxModChild]>,
274 desugar: Cache<LocalDefId, QueryResult<fhir::Node<'genv>>>,
275 fhir_attr_map: Cache<LocalDefId, fhir::AttrMap<'genv>>,
276 fhir_crate: OnceCell<fhir::FluxItems<'genv>>,
277 lower_generics_of: Cache<DefId, ty::Generics<'tcx>>,
278 lower_predicates_of: Cache<DefId, QueryResult<ty::GenericPredicates>>,
279 lower_type_of: Cache<DefId, QueryResult<ty::EarlyBinder<ty::Ty>>>,
280 lower_fn_sig: Cache<DefId, QueryResult<ty::EarlyBinder<ty::PolyFnSig>>>,
281 spec_funcs: Cache<CrateNum, Rc<rty::SpecFuncs>>,
282 inlined_body: Cache<FluxDefId, rty::Binder<rty::Expr>>,
283 func_sort: Cache<FluxDefId, rty::PolyFuncSort>,
284 func_span: Cache<FluxDefId, Span>,
285 qualifiers: OnceCell<QueryResult<Vec<rty::Qualifier>>>,
286 axioms: OnceCell<QueryResult<Vec<rty::Axiom>>>,
287 prim_rel: OnceCell<QueryResult<UnordMap<rty::BinOp, rty::PrimRel>>>,
288 adt_sort_def_of: Cache<DefId, QueryResult<rty::AdtSortDef>>,
289 check_wf: Cache<LocalDefId, QueryResult<Rc<rty::WfckResults>>>,
290 late_bound_refinement_params: Cache<LocalDefId, QueryResult<&'genv [fhir::ParamId]>>,
291 adt_def: Cache<DefId, QueryResult<rty::AdtDef>>,
292 invariants_of: Cache<DefId, rty::EarlyBinder<List<rty::Invariant>>>,
293 constant_info: Cache<DefId, QueryResult<rty::ConstantInfo>>,
294 static_info: Cache<DefId, QueryResult<rty::Ty>>,
295 generics_of: Cache<DefId, QueryResult<rty::Generics>>,
296 refinement_generics_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::RefinementGenerics>>>,
297 predicates_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::GenericPredicates>>>,
298 assoc_refinements_of: Cache<DefId, QueryResult<rty::AssocRefinements>>,
299 assoc_refinement_body: Cache<FluxDefId, QueryResult<rty::EarlyBinder<rty::Lambda>>>,
300 default_assoc_refinement_body:
301 Cache<FluxDefId, QueryResult<Option<rty::EarlyBinder<rty::Lambda>>>>,
302 sort_of_assoc_reft: Cache<FluxDefId, QueryResult<rty::EarlyBinder<rty::FuncSort>>>,
303 item_bounds: Cache<DefId, QueryResult<rty::EarlyBinder<List<rty::Clause>>>>,
304 type_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::TyOrCtor>>>,
305 variants_of: Cache<DefId, QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>>>,
306 fn_sig: Cache<DefId, QueryResult<rty::EarlyBinder<rty::PolyFnSig>>>,
307 sort_decl_param_count: Cache<FluxDefId, usize>,
308 no_panic: Cache<DefId, bool>,
309 assume_parametric_params: Cache<DefId, UnordSet<u32>>,
310 call_graph: OnceCell<CallGraph<'tcx>>,
311 inferred_no_panic: OnceCell<Rc<UnordMap<NodeKey<'tcx>, PanicSpec>>>,
313}
314
315impl<'genv, 'tcx> Queries<'genv, 'tcx> {
316 pub(crate) fn new(providers: Providers) -> Self {
317 Self {
318 providers,
319 queried_def_ids: RefCell::new(UnordSet::new()),
320 mir: Default::default(),
321 collect_specs: Default::default(),
322 resolve_crate: Default::default(),
323 flux_module_children: Default::default(),
324 desugar: Default::default(),
325 fhir_attr_map: Default::default(),
326 fhir_crate: Default::default(),
327 lower_generics_of: Default::default(),
328 lower_predicates_of: Default::default(),
329 lower_type_of: Default::default(),
330 lower_fn_sig: Default::default(),
331 spec_funcs: Default::default(),
332 inlined_body: Default::default(),
333 func_sort: Default::default(),
334 func_span: Default::default(),
335 qualifiers: Default::default(),
336 axioms: Default::default(),
337 prim_rel: Default::default(),
338 adt_sort_def_of: Default::default(),
339 check_wf: Default::default(),
340 late_bound_refinement_params: Default::default(),
341 adt_def: Default::default(),
342 invariants_of: Default::default(),
343 constant_info: Default::default(),
344 static_info: Default::default(),
345 generics_of: Default::default(),
346 refinement_generics_of: Default::default(),
347 predicates_of: Default::default(),
348 assoc_refinements_of: Default::default(),
349 assoc_refinement_body: Default::default(),
350 default_assoc_refinement_body: Default::default(),
351 sort_of_assoc_reft: Default::default(),
352 item_bounds: Default::default(),
353 type_of: Default::default(),
354 variants_of: Default::default(),
355 fn_sig: Default::default(),
356 sort_decl_param_count: Default::default(),
357 no_panic: Default::default(),
358 assume_parametric_params: Default::default(),
359 call_graph: Default::default(),
360 inferred_no_panic: Default::default(),
361 }
362 }
363
364 pub(crate) fn queried(&self, def_id: DefId) -> bool {
365 self.queried_def_ids.borrow().contains(&def_id)
366 }
367
368 pub(crate) fn mir(
369 &self,
370 genv: GlobalEnv<'genv, 'tcx>,
371 def_id: LocalDefId,
372 ) -> QueryResult<Rc<mir::BodyRoot<'tcx>>> {
373 run_with_cache(&self.mir, def_id, || {
374 let mir = unsafe { flux_common::mir_storage::retrieve_mir_body(genv.tcx(), def_id) };
375 let mir =
376 lowering::MirLoweringCtxt::lower_mir_body(genv.tcx(), genv.sess(), def_id, mir)?;
377 Ok(Rc::new(mir))
378 })
379 }
380
381 pub(crate) fn collect_specs(&'genv self, genv: GlobalEnv<'genv, 'tcx>) -> &'genv crate::Specs {
382 self.collect_specs
383 .get_or_init(|| (self.providers.collect_specs)(genv))
384 }
385
386 pub(crate) fn resolve_crate(
387 &'genv self,
388 genv: GlobalEnv<'genv, 'tcx>,
389 ) -> &'genv crate::ResolverOutput {
390 self.resolve_crate
391 .get_or_init(|| (self.providers.resolve_crate)(genv))
392 }
393
394 #[allow(clippy::disallowed_methods, reason = "`flux_items_by_scope` is the source of truth")]
397 pub(crate) fn flux_module_children(
398 &'genv self,
399 genv: GlobalEnv<'genv, 'tcx>,
400 def_id: DefId,
401 ) -> &'genv [fhir::FluxModChild] {
402 run_with_cache(&self.flux_module_children, def_id, || {
403 def_id.dispatch_query(
404 genv,
405 self,
406 |def_id| -> &'genv [fhir::FluxModChild] {
407 let specs = genv.collect_specs();
411 let module = rustc_hir::HirId::make_owner(def_id.local_id());
412 let items = specs
413 .flux_items_by_scope
414 .get(&module)
415 .map_or(&[][..], Vec::as_ref);
416 genv.alloc_slice(
417 &items
418 .iter()
419 .filter_map(|crate::FluxItemDecl { declarer, item }| {
420 let declarer = declarer.to_def_id();
421 let ident;
422 let res = match item {
423 surface::FluxItem::FuncDef(func) => {
424 ident = func.name;
425 fhir::Res::GlobalFunc(fhir::SpecFuncKind::Def(
426 FluxDefId::new(declarer, ident.name),
427 ))
428 }
429 surface::FluxItem::SortDecl(sort) => {
430 ident = sort.name;
431 fhir::Res::UserSort(FluxDefId::new(declarer, ident.name))
432 }
433 surface::FluxItem::Qualifier(_)
434 | surface::FluxItem::PrimOpProp(_)
435 | surface::FluxItem::Axiom(_)
436 | surface::FluxItem::Use(_) => return None,
437 };
438 Some(fhir::FluxModChild { ident, res })
439 })
440 .collect::<Vec<_>>(),
441 )
442 },
443 |def_id| genv.cstore().flux_module_children(def_id),
444 |_| &[], )
446 })
447 }
448
449 pub(crate) fn desugar(
450 &'genv self,
451 genv: GlobalEnv<'genv, 'tcx>,
452 def_id: LocalDefId,
453 ) -> QueryResult<fhir::Node<'genv>> {
454 if let Some(v) = self.desugar.borrow().get(&def_id) {
455 return v.clone();
456 }
457 match (self.providers.desugar)(genv, def_id) {
458 Ok(nodes) => {
459 let mut cache = self.desugar.borrow_mut();
460 cache.extend_unord(nodes.into_items().map(|(def_id, node)| (def_id, Ok(node))));
461 let Some(res) = cache.get(&def_id) else {
462 tracked_span_bug!("cannot desugar {def_id:?}")
463 };
464 res.clone()
465 }
466 Err(err) => {
467 self.desugar.borrow_mut().insert(def_id, Err(err.clone()));
468 Err(err)
469 }
470 }
471 }
472
473 pub(crate) fn fhir_attr_map(
474 &'genv self,
475 genv: GlobalEnv<'genv, 'tcx>,
476 def_id: LocalDefId,
477 ) -> fhir::AttrMap<'genv> {
478 run_with_cache(&self.fhir_attr_map, def_id, || (self.providers.fhir_attr_map)(genv, def_id))
479 }
480
481 pub(crate) fn fhir_crate(
482 &'genv self,
483 genv: GlobalEnv<'genv, 'tcx>,
484 ) -> &'genv fhir::FluxItems<'genv> {
485 self.fhir_crate
486 .get_or_init(|| (self.providers.fhir_crate)(genv))
487 }
488
489 pub(crate) fn lower_generics_of(
490 &self,
491 genv: GlobalEnv<'genv, 'tcx>,
492 def_id: DefId,
493 ) -> ty::Generics<'tcx> {
494 run_with_cache(&self.lower_generics_of, def_id, || {
495 genv.tcx().generics_of(def_id).lower(genv.tcx())
496 })
497 }
498
499 pub(crate) fn lower_predicates_of(
500 &self,
501 genv: GlobalEnv,
502 def_id: DefId,
503 ) -> QueryResult<ty::GenericPredicates> {
504 run_with_cache(&self.lower_predicates_of, def_id, || {
505 genv.tcx()
506 .clauses_of(def_id)
507 .lower(genv.tcx())
508 .map_err(|err| QueryErr::unsupported(def_id, err))
509 })
510 }
511
512 pub(crate) fn lower_type_of(
513 &self,
514 genv: GlobalEnv,
515 def_id: DefId,
516 ) -> QueryResult<ty::EarlyBinder<ty::Ty>> {
517 run_with_cache(&self.lower_type_of, def_id, || {
518 let ty = genv
519 .tcx()
520 .type_of(def_id)
521 .instantiate_identity()
522 .skip_norm_wip();
523 Ok(ty::EarlyBinder(
524 ty.lower(genv.tcx())
525 .map_err(|err| QueryErr::unsupported(def_id, err.into_err()))?,
526 ))
527 })
528 }
529
530 pub(crate) fn lower_fn_sig(
531 &self,
532 genv: GlobalEnv,
533 def_id: DefId,
534 ) -> QueryResult<ty::EarlyBinder<ty::PolyFnSig>> {
535 run_with_cache(&self.lower_fn_sig, def_id, || {
536 let fn_sig = genv
537 .tcx()
538 .fn_sig(def_id)
539 .instantiate_identity()
540 .skip_norm_wip();
541 Ok(ty::EarlyBinder(
542 fn_sig
543 .lower(genv.tcx())
544 .map_err(|err| QueryErr::unsupported(def_id, err.into_err()))?,
545 ))
546 })
547 }
548
549 pub(crate) fn spec_funcs(&self, genv: GlobalEnv, krate: CrateNum) -> Rc<rty::SpecFuncs> {
550 run_with_cache(&self.spec_funcs, krate, || {
551 if krate == LOCAL_CRATE {
552 Rc::new((self.providers.spec_funcs)(genv))
553 } else {
554 genv.cstore().spec_funcs(krate)
555 }
556 })
557 }
558
559 pub(crate) fn inlined_body(&self, genv: GlobalEnv, did: FluxDefId) -> rty::Binder<rty::Expr> {
560 run_with_cache(&self.inlined_body, did, || {
565 let rty::SpecFunc::Defined { body, .. } = genv.spec_func(did) else {
566 bug!("inlined body of uninterpreted function `{did:?}`")
567 };
568 body.reduce(genv)
569 })
570 }
571
572 pub(crate) fn func_sort(&self, genv: GlobalEnv, def_id: FluxDefId) -> rty::PolyFuncSort {
573 run_with_cache(&self.func_sort, def_id, || {
574 def_id.dispatch_query(
575 genv,
576 self,
577 |def_id| {
578 (self.providers.func_sort)(genv, def_id)
580 },
581 |def_id| genv.cstore().func_sort(def_id),
582 |_| {
583 bug!(
584 "cannot generate default function sort, the refinement must be defined somewhere"
585 )
586 },
587 )
588 })
589 }
590
591 pub(crate) fn func_span(&self, genv: GlobalEnv, def_id: FluxDefId) -> Span {
592 run_with_cache(&self.func_span, def_id, || {
593 def_id.dispatch_query(
594 genv,
595 self,
596 |def_id| {
597 (self.providers.func_span)(genv, def_id)
599 },
600 |def_id| genv.cstore().func_span(def_id),
601 |_|
602 bug!(
603 "cannot generate default function sort, the refinement must be defined somewhere"
604 )
605 ,
606 )
607 })
608 }
609
610 pub(crate) fn qualifiers(&self, genv: GlobalEnv) -> QueryResult<&[rty::Qualifier]> {
611 self.qualifiers
612 .get_or_init(|| (self.providers.qualifiers)(genv))
613 .as_deref()
614 .map_err(Clone::clone)
615 }
616
617 pub(crate) fn axioms(&self, genv: GlobalEnv) -> QueryResult<&[rty::Axiom]> {
618 self.axioms
619 .get_or_init(|| (self.providers.axioms)(genv))
620 .as_deref()
621 .map_err(Clone::clone)
622 }
623
624 pub(crate) fn prim_rel(
625 &self,
626 genv: GlobalEnv,
627 ) -> QueryResult<&UnordMap<rty::BinOp, rty::PrimRel>> {
628 self.prim_rel
629 .get_or_init(|| (self.providers.prim_rel)(genv))
630 .as_ref()
631 .map_err(|err| err.clone())
632 }
633
634 pub(crate) fn adt_sort_def_of(
635 &self,
636 genv: GlobalEnv,
637 def_id: DefId,
638 ) -> QueryResult<rty::AdtSortDef> {
639 run_with_cache(&self.adt_sort_def_of, def_id, || {
640 def_id.dispatch_query(
641 genv,
642 self,
643 |def_id| (self.providers.adt_sort_def_of)(genv, def_id),
644 |def_id| genv.cstore().adt_sort_def(def_id),
645 |def_id| {
646 let variants = IndexVec::from([rty::AdtSortVariant::new(vec![])]);
647 Ok(rty::AdtSortDef::new(def_id, vec![], variants, false, true))
648 },
649 )
650 })
651 }
652
653 pub(crate) fn sort_decl_param_count(&self, genv: GlobalEnv, def_id: FluxDefId) -> usize {
654 run_with_cache(&self.sort_decl_param_count, def_id, || {
655 def_id.dispatch_query(
656 genv,
657 self,
658 |def_id| {
659 (self.providers.sort_decl_param_count)(genv, def_id)
660 },
661 |def_id| genv.cstore().sort_decl_param_count(def_id),
662 |_| {
663 bug!(
664 "cannot generate default param count for sort declaration, it must be defined somewhere"
665 )
666 }
667 )
668 })
669 }
670
671 pub(crate) fn check_wf(
672 &self,
673 genv: GlobalEnv<'genv, '_>,
674 def_id: LocalDefId,
675 ) -> QueryResult<Rc<rty::WfckResults>> {
676 run_with_cache(&self.check_wf, def_id, || (self.providers.check_wf)(genv, def_id))
677 }
678
679 pub(crate) fn late_bound_refinement_params(
680 &self,
681 genv: GlobalEnv<'genv, '_>,
682 def_id: LocalDefId,
683 ) -> QueryResult<&'genv [fhir::ParamId]> {
684 run_with_cache(&self.late_bound_refinement_params, def_id, || {
685 (self.providers.late_bound_refinement_params)(genv, def_id)
686 })
687 }
688
689 pub(crate) fn constant_info(
690 &self,
691 genv: GlobalEnv,
692 def_id: DefId,
693 ) -> QueryResult<rty::ConstantInfo> {
694 run_with_cache(&self.constant_info, def_id, || {
695 def_id.dispatch_query(
696 genv,
697 self,
698 |def_id| (self.providers.constant_info)(genv, def_id),
699 |def_id| genv.cstore().constant_info(def_id),
700 |def_id| {
701 let ty = genv.tcx().type_of(def_id).no_bound_vars().unwrap();
703 if ty.is_integral() {
704 let val = genv.tcx().const_eval_poly(def_id).ok().and_then(|val| {
705 let val = val.try_to_scalar_int()?;
706 rty::Constant::from_scalar_int(genv.tcx(), val, &ty)
707 });
708 if let Some(constant_) = val {
709 return Ok(rty::ConstantInfo::Interpreted(
710 rty::Expr::constant(constant_),
711 rty::Sort::Int,
712 ));
713 }
714 }
715 Ok(rty::ConstantInfo::Uninterpreted)
716 },
717 )
718 })
719 }
720
721 pub fn call_graph(&'genv self, genv: GlobalEnv<'genv, 'tcx>) -> &'genv CallGraph<'tcx> {
722 self.call_graph
723 .get_or_init(|| (self.providers.call_graph)(genv))
724 }
725
726 pub fn inferred_no_panic(
728 &'genv self,
729 genv: GlobalEnv<'genv, 'tcx>,
730 ) -> Rc<UnordMap<NodeKey<'tcx>, PanicSpec>> {
731 self.inferred_no_panic
732 .get_or_init(|| Rc::new((self.providers.inferred_no_panic)(genv)))
733 .clone()
734 }
735
736 pub(crate) fn static_info(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::Ty> {
737 run_with_cache(&self.static_info, def_id, || {
738 def_id.dispatch_query(
739 genv,
740 self,
741 |def_id| (self.providers.static_info)(genv, def_id),
742 |def_id| genv.cstore().static_info(def_id),
743 |def_id| rty::refining::default_static_ty(genv, def_id),
744 )
745 })
746 }
747
748 pub(crate) fn no_panic(&self, genv: GlobalEnv, def_id: DefId) -> bool {
749 run_with_cache(&self.no_panic, def_id, || {
750 def_id.dispatch_query(
751 genv,
752 self,
753 |def_id| {
754 let mut current_id = def_id.local_id();
755
756 loop {
758 if genv.is_dummy(current_id) {
760 if let Some(parent) = genv.tcx().opt_local_parent(current_id) {
761 current_id = parent;
762 continue;
763 } else {
764 return false; }
766 }
767
768 if genv.fhir_attr_map(current_id).no_panic() {
770 return true;
771 }
772
773 if let Some(parent) = genv.tcx().opt_local_parent(current_id) {
775 current_id = parent;
776 } else {
777 break; }
779 }
780
781 config::no_panic()
782 },
783 |def_id| genv.cstore().no_panic(def_id),
784 |_| false,
785 )
786 })
787 }
788
789 pub(crate) fn assume_parametric_params(&self, genv: GlobalEnv, def_id: DefId) -> UnordSet<u32> {
790 run_with_cache(&self.assume_parametric_params, def_id, || {
791 def_id.dispatch_query(
792 genv,
793 self,
794 |def_id| {
795 let tcx = genv.tcx();
796 let generics = tcx.generics_of(def_id);
797 genv.fhir_attr_map(def_id.local_id())
798 .parametric_params()
799 .iter()
800 .map(|param_id| generics.param_def_id_to_index(tcx, *param_id).unwrap())
801 .collect()
802 },
803 |def_id| genv.cstore().assume_parametric_params(def_id),
804 |_| UnordSet::default(),
805 )
806 })
807 }
808
809 pub(crate) fn adt_def(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::AdtDef> {
810 run_with_cache(&self.adt_def, def_id, || {
811 def_id.dispatch_query(
812 genv,
813 self,
814 |def_id| (self.providers.adt_def)(genv, def_id),
815 |def_id| genv.cstore().adt_def(def_id),
816 |def_id| {
817 let adt_def = genv.tcx().adt_def(def_id).lower(genv.tcx());
818 Ok(rty::AdtDef::new(adt_def, genv.adt_sort_def_of(def_id)?, false))
819 },
820 )
821 })
822 }
823
824 pub(crate) fn invariants_of(
825 &self,
826 genv: GlobalEnv,
827 def_id: DefId,
828 ) -> rty::EarlyBinder<List<rty::Invariant>> {
829 run_with_cache(&self.invariants_of, def_id, || {
830 def_id.dispatch_query(
831 genv,
832 self,
833 |def_id| (self.providers.invariants_of)(genv, def_id),
834 |def_id| genv.cstore().invariants_of(def_id),
835 |_| rty::EarlyBinder(List::empty()),
836 )
837 })
838 }
839
840 pub(crate) fn generics_of(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::Generics> {
841 if genv.tcx().is_lang_item(def_id, LangItem::OwnedBox) {
845 let generics = genv.lower_generics_of(def_id);
846 debug_assert_eq!(generics.params.len(), 2);
847 let deref_ty = &generics.params[0];
848 let alloc = &generics.params[1];
849 return Ok(rty::Generics {
850 own_params: List::from_arr([
851 refine_generic_param_def(true, deref_ty),
852 refine_generic_param_def(false, alloc),
853 ]),
854 parent: generics.parent(),
855 parent_count: generics.parent_count(),
856 has_self: generics.orig.has_self,
857 });
858 }
859 if genv.tcx().is_lang_item(def_id, LangItem::MetaSized) {
866 let generics = genv.lower_generics_of(def_id);
867 debug_assert_eq!(generics.params.len(), 1);
868 let self_ty = &generics.params[0];
869 return Ok(rty::Generics {
870 own_params: List::from_arr([refine_generic_param_def(true, self_ty)]),
871 parent: generics.parent(),
872 parent_count: generics.parent_count(),
873 has_self: generics.orig.has_self,
874 });
875 }
876
877 run_with_cache(&self.generics_of, def_id, || {
878 def_id.dispatch_query(
879 genv,
880 self,
881 |def_id| (self.providers.generics_of)(genv, def_id),
882 |def_id| genv.cstore().generics_of(def_id),
883 |def_id| Ok(refining::refine_generics(&genv.lower_generics_of(def_id))),
884 )
885 })
886 }
887
888 pub(crate) fn refinement_generics_of(
889 &self,
890 genv: GlobalEnv,
891 def_id: DefId,
892 ) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>> {
893 run_with_cache(&self.refinement_generics_of, def_id, || {
894 def_id.dispatch_query(
895 genv,
896 self,
897 |def_id| (self.providers.refinement_generics_of)(genv, def_id),
898 |def_id| genv.cstore().refinement_generics_of(def_id),
899 |def_id| {
900 let parent = genv.tcx().generics_of(def_id).parent;
901 Ok(rty::EarlyBinder(rty::RefinementGenerics {
902 parent,
903 parent_count: 0,
904 own_params: List::empty(),
905 }))
906 },
907 )
908 })
909 }
910
911 pub(crate) fn item_bounds(
912 &self,
913 genv: GlobalEnv<'genv, 'tcx>,
914 def_id: DefId,
915 ) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>> {
916 run_with_cache(&self.item_bounds, def_id, || {
917 def_id.dispatch_query(
918 genv,
919 self,
920 |def_id| (self.providers.item_bounds)(genv, def_id),
921 |def_id| genv.cstore().item_bounds(def_id),
922 |def_id| {
923 let clauses = genv
924 .tcx()
925 .item_bounds(def_id)
926 .skip_binder()
927 .lower(genv.tcx())
928 .map_err(|err| QueryErr::unsupported(def_id, err))?
929 .refine(&Refiner::default_for_item(genv, def_id)?)?;
930
931 Ok(rty::EarlyBinder(clauses))
932 },
933 )
934 })
935 }
936
937 pub(crate) fn predicates_of(
938 &self,
939 genv: GlobalEnv,
940 def_id: DefId,
941 ) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
942 run_with_cache(&self.predicates_of, def_id, || {
943 def_id.dispatch_query(
944 genv,
945 self,
946 |def_id| (self.providers.predicates_of)(genv, def_id),
947 |def_id| genv.cstore().predicates_of(def_id),
948 |def_id| {
949 let predicates = genv
950 .lower_predicates_of(def_id)?
951 .refine(&Refiner::default_for_item(genv, def_id)?)?;
952 Ok(rty::EarlyBinder(predicates))
953 },
954 )
955 })
956 }
957
958 pub(crate) fn assoc_refinements_of(
959 &self,
960 genv: GlobalEnv,
961 def_id: DefId,
962 ) -> QueryResult<rty::AssocRefinements> {
963 run_with_cache(&self.assoc_refinements_of, def_id, || {
964 def_id.dispatch_query(
965 genv,
966 self,
967 |def_id| (self.providers.assoc_refinements_of)(genv, def_id),
968 |def_id| genv.cstore().assoc_refinements_of(def_id),
969 |def_id| Ok(genv.builtin_assoc_refts(def_id).unwrap_or_default()),
970 )
971 })
972 }
973
974 pub(crate) fn assoc_refinement_body(
975 &self,
976 genv: GlobalEnv,
977 impl_assoc_id: FluxDefId,
978 ) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
979 run_with_cache(&self.assoc_refinement_body, impl_assoc_id, || {
980 impl_assoc_id.dispatch_query(
981 genv,
982 self,
983 |impl_assoc_id| (self.providers.assoc_refinement_body)(genv, impl_assoc_id),
984 |impl_assoc_id| genv.cstore().assoc_refinements_def(impl_assoc_id),
985 |impl_assoc_id| {
986 Err(query_bug!(
987 impl_assoc_id.parent(),
988 "cannot generate default associate refinement for extern impl"
989 ))
990 },
991 )
992 })
993 }
994
995 pub(crate) fn default_assoc_refinement_body(
996 &self,
997 genv: GlobalEnv,
998 trait_assoc_id: FluxDefId,
999 ) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>> {
1000 run_with_cache(&self.default_assoc_refinement_body, trait_assoc_id, || {
1001 trait_assoc_id.dispatch_query(
1002 genv,
1003 self,
1004 |trait_assoc_id| {
1005 (self.providers.default_assoc_refinement_body)(genv, trait_assoc_id)
1006 },
1007 |trait_assoc_id| genv.cstore().default_assoc_refinements_def(trait_assoc_id),
1008 |trait_assoc_id| {
1009 Err(query_bug!(
1010 trait_assoc_id.parent(),
1011 "cannot generate default assoc refinement for extern trait"
1012 ))
1013 },
1014 )
1015 })
1016 }
1017
1018 pub(crate) fn sort_of_assoc_reft(
1019 &self,
1020 genv: GlobalEnv,
1021 assoc_id: FluxDefId,
1022 ) -> QueryResult<rty::EarlyBinder<rty::FuncSort>> {
1023 run_with_cache(&self.sort_of_assoc_reft, assoc_id, || {
1024 assoc_id.dispatch_query(
1025 genv,
1026 self,
1027 |assoc_id| (self.providers.sort_of_assoc_reft)(genv, assoc_id),
1028 |assoc_id| genv.cstore().sort_of_assoc_reft(assoc_id),
1029 |assoc_id| {
1030 genv.builtin_assoc_reft_sort(assoc_id).ok_or_else(|| {
1031 query_bug!(
1032 assoc_id.parent(),
1033 "assoc refinement on extern crate is not builtin"
1034 )
1035 })
1036 },
1037 )
1038 })
1039 }
1040
1041 pub(crate) fn type_of(
1042 &self,
1043 genv: GlobalEnv,
1044 def_id: DefId,
1045 ) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>> {
1046 run_with_cache(&self.type_of, def_id, || {
1047 def_id.dispatch_query(
1048 genv,
1049 self,
1050 |def_id| (self.providers.type_of)(genv, def_id),
1051 |def_id| genv.cstore().type_of(def_id),
1052 |def_id| {
1053 let generics_def_id = match genv.def_kind(def_id) {
1055 DefKind::TyParam => genv.tcx().parent(def_id),
1056 _ => def_id,
1057 };
1058 let ty = genv.lower_type_of(def_id)?.skip_binder();
1059 Ok(rty::EarlyBinder(
1060 Refiner::default_for_item(genv, generics_def_id)?
1061 .refine_ty_or_base(&ty)?
1062 .into(),
1063 ))
1064 },
1065 )
1066 })
1067 }
1068
1069 pub(crate) fn variants_of(
1070 &self,
1071 genv: GlobalEnv,
1072 def_id: DefId,
1073 ) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>> {
1074 run_with_cache(&self.variants_of, def_id, || {
1075 def_id.dispatch_query(
1076 genv,
1077 self,
1078 |def_id| (self.providers.variants_of)(genv, def_id),
1079 |def_id| genv.cstore().variants_of(def_id),
1080 |def_id| {
1081 let variants = genv
1082 .tcx()
1083 .adt_def(def_id)
1084 .variants()
1085 .indices()
1086 .map(|variant_idx| {
1087 Refiner::default_for_item(genv, def_id)?
1088 .refine_variant_def(def_id, variant_idx)
1089 })
1090 .try_collect()?;
1091 Ok(rty::Opaqueness::Transparent(rty::EarlyBinder(variants)))
1092 },
1093 )
1094 })
1095 }
1096
1097 pub(crate) fn fn_sig(
1098 &self,
1099 genv: GlobalEnv,
1100 def_id: DefId,
1101 ) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>> {
1102 run_with_cache(&self.fn_sig, def_id, || {
1103 def_id.dispatch_query(
1104 genv,
1105 self,
1106 |def_id| (self.providers.fn_sig)(genv, def_id),
1107 |def_id| genv.cstore().fn_sig(def_id),
1108 |def_id| {
1109 let tcx = genv.tcx();
1110
1111 let mut poly_sig = genv
1112 .lower_fn_sig(def_id)?
1113 .skip_binder()
1114 .refine(&Refiner::default_for_item(genv, def_id)?)?
1115 .hoist_input_binders();
1116 if genv.is_fn_call(def_id) {
1117 let fn_once_id = tcx.require_lang_item(LangItem::FnOnce, DUMMY_SP);
1118
1119 let fn_once_no_panic = genv
1120 .builtin_assoc_refts(fn_once_id)
1121 .unwrap()
1122 .find(sym::no_panic)
1123 .unwrap();
1124
1125 let args = GenericArg::identity_for_item(genv, fn_once_id)?;
1126
1127 let alias_reft = AliasReft { assoc_id: fn_once_no_panic.def_id, args };
1128
1129 poly_sig = poly_sig.map(|mut fn_sig| {
1130 fn_sig.no_panic = Expr::alias(alias_reft, List::empty());
1131 fn_sig
1132 });
1133 }
1134
1135 #[cfg(feature = "suggestions")]
1141 if genv.weak_kvars_for(def_id).is_none() {
1142 match genv.resolve_id(def_id).as_maybe_extern() {
1146 Some(maybe_extern) if !genv.no_suggestions(maybe_extern.local_id()) => {
1147 poly_sig = poly_sig
1148 .add_weak_kvars(genv, maybe_extern.local_id().into())?;
1149 }
1150 _ => {}
1151 }
1152 }
1153 Ok(rty::EarlyBinder(poly_sig))
1154 },
1155 )
1156 })
1157 }
1158}
1159
1160pub trait DispatchKey: Sized + Copy {
1163 type LocalId;
1164
1165 fn dispatch_query<R>(
1166 self,
1167 genv: GlobalEnv,
1168 queries: &Queries,
1169 local: impl FnOnce(Self::LocalId) -> R,
1170 external: impl FnOnce(Self) -> Option<R>,
1171 default: impl FnOnce(Self) -> R,
1172 ) -> R;
1173
1174 fn def_id(self) -> DefId;
1175}
1176
1177impl DispatchKey for DefId {
1178 type LocalId = MaybeExternId;
1179
1180 fn dispatch_query<R>(
1181 self,
1182 genv: GlobalEnv,
1183 queries: &Queries,
1184 local: impl FnOnce(MaybeExternId) -> R,
1185 external: impl FnOnce(Self) -> Option<R>,
1186 default: impl FnOnce(Self) -> R,
1187 ) -> R {
1188 queries.queried_def_ids.borrow_mut().insert(self);
1189 match genv.resolve_id(self) {
1190 ResolvedDefId::Local(local_id) => {
1191 local(MaybeExternId::Local(local_id))
1193 }
1194 ResolvedDefId::ExternSpec(local_id, def_id) => {
1195 local(MaybeExternId::Extern(local_id, def_id))
1198 }
1199 ResolvedDefId::Extern(def_id) if let Some(v) = external(def_id) => {
1200 v
1203 }
1204 ResolvedDefId::Extern(def_id) => {
1205 default(def_id)
1207 }
1208 }
1209 }
1210
1211 fn def_id(self) -> DefId {
1212 self
1213 }
1214}
1215
1216impl DispatchKey for FluxDefId {
1217 type LocalId = FluxId<MaybeExternId>;
1218
1219 fn dispatch_query<R>(
1220 self,
1221 genv: GlobalEnv,
1222 queries: &Queries,
1223 local: impl FnOnce(FluxId<MaybeExternId>) -> R,
1224 external: impl FnOnce(FluxId<DefId>) -> Option<R>,
1225 default: impl FnOnce(FluxId<DefId>) -> R,
1226 ) -> R {
1227 #[allow(
1228 clippy::disallowed_methods,
1229 reason = "we are mapping the parent id to a different representation which still guarantees the existence of the item"
1230 )]
1231 self.parent().dispatch_query(
1232 genv,
1233 queries,
1234 |container_id| local(FluxId::new(container_id, self.name())),
1235 |container_id| external(FluxId::new(container_id, self.name())),
1236 |container_id| default(FluxId::new(container_id, self.name())),
1237 )
1238 }
1239
1240 fn def_id(self) -> DefId {
1241 self.parent()
1242 }
1243}
1244
1245fn run_with_cache<K, V>(cache: &Cache<K, V>, key: K, f: impl FnOnce() -> V) -> V
1246where
1247 K: std::hash::Hash + Eq,
1248 V: Clone,
1249{
1250 if let Some(v) = cache.borrow().get(&key) {
1251 return v.clone();
1252 }
1253 let v = f();
1254 cache.borrow_mut().insert(key, v.clone());
1255 v
1256}
1257
1258const OPAQUE_STRUCT: DiagMessage = msg!("invalid use of opaque struct");
1259const MISSING_ASSOC_REFT: DiagMessage =
1260 msg!("associated refinement `{$name}` is missing from implementation");
1261
1262impl<'a> Diagnostic<'a> for QueryErr {
1263 #[track_caller]
1264 fn into_diag(
1265 self,
1266 dcx: rustc_errors::DiagCtxtHandle<'a>,
1267 _level: rustc_errors::Level,
1268 ) -> rustc_errors::Diag<'a> {
1269 rustc_middle::ty::tls::with_opt(
1270 #[track_caller]
1271 |tcx| {
1272 let tcx = tcx.expect("no TyCtxt stored in tls");
1273 match self {
1274 QueryErr::Unsupported { def_id, err } => {
1275 let span = err.span.unwrap_or_else(|| tcx.def_span(def_id));
1276 let mut diag = dcx.struct_span_err(span, msg!("unsupported signature"));
1277 diag.code(E0999);
1278 diag.note(err.descr);
1279 diag
1280 }
1281 QueryErr::Ignored { def_id } => {
1282 let def_span = tcx.def_span(def_id);
1283 let mut diag = dcx.struct_span_err(def_span, msg!("use of ignored item"));
1284 diag.code(E0999);
1285 diag
1286 }
1287 QueryErr::NotIncluded { def_id } => {
1288 let def_span = tcx.def_span(def_id);
1289 let mut diag = dcx.struct_span_err(
1290 def_span,
1291 msg!("use of item defined in external crate, but was not included when checking that crate"),
1292 );
1293 diag.code(E0999);
1294 diag
1295 }
1296 QueryErr::InvalidGenericArg { def_id } => {
1297 let def_span = tcx.def_span(def_id);
1298 let mut diag = dcx.struct_span_err(
1299 def_span,
1300 msg!("cannot instantiate base generic with opaque type or a type parameter of kind type"),
1301 );
1302 diag.code(E0999);
1303 diag
1304 }
1305 QueryErr::MissingAssocReft { impl_id, name, .. } => {
1306 let def_span = tcx.def_span(impl_id);
1307 let mut diag = dcx.struct_span_err(def_span, MISSING_ASSOC_REFT);
1308 diag.arg("name", name);
1309 diag.code(E0999);
1310 diag
1311 }
1312 QueryErr::Bug { def_id, location, msg } => {
1313 let mut diag = dcx.struct_err(msg!("internal flux error: {$location}"));
1314 if let Some(def_id) = def_id {
1315 diag.span(tcx.def_span(def_id));
1316 }
1317 diag.arg("location", location);
1318 diag.note(msg);
1319 diag
1320 }
1321 QueryErr::Emitted(_) => {
1322 let mut diag = dcx.struct_err("QueryErr::Emitted should be emitted");
1323 diag.downgrade_to_delayed_bug();
1324 diag
1325 }
1326 QueryErr::OpaqueStruct { struct_id } => {
1327 let struct_span = tcx.def_span(struct_id);
1328 let mut diag = dcx.struct_span_err(struct_span, OPAQUE_STRUCT);
1329 diag.arg("struct", tcx.def_path_str(struct_id));
1330 diag
1331 }
1332 }
1333 },
1334 )
1335 }
1336}
1337
1338impl<'a> Diagnostic<'a> for QueryErrAt {
1339 #[track_caller]
1340 fn into_diag(
1341 self,
1342 dcx: rustc_errors::DiagCtxtHandle<'a>,
1343 level: rustc_errors::Level,
1344 ) -> rustc_errors::Diag<'a> {
1345 rustc_middle::ty::tls::with_opt(
1346 #[track_caller]
1347 |tcx| {
1348 let tcx = tcx.expect("no TyCtxt stored in tls");
1349 let cx_span = self.cx.span();
1350 let mut diag = match self.err {
1351 QueryErr::Unsupported { def_id, err, .. } => {
1352 let mut diag =
1353 dcx.struct_span_err(cx_span, msg!("use of unsupported {$kind}"));
1354 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1355 if let Some(def_ident_span) = tcx.def_ident_span(def_id) {
1356 diag.span_note(
1357 def_ident_span,
1358 msg!("this {$kind} has unsupported features"),
1359 );
1360 }
1361 diag.note(err.descr);
1362 diag
1363 }
1364 QueryErr::Ignored { def_id } => {
1365 let mut diag =
1366 dcx.struct_span_err(cx_span, msg!("use of ignored {$kind} `{$name}`"));
1367 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1368 diag.arg("name", def_id_to_string(def_id));
1369 diag.span_label(cx_span, msg!("help: try ignoring or trusting this code"));
1370 diag
1371 }
1372 QueryErr::NotIncluded { def_id } => {
1373 let mut diag = dcx.struct_span_err(
1374 cx_span,
1375 msg!("use of {$kind} `{$name}` that was not included when checking external crate"),
1376 );
1377 diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
1378 diag.arg("name", def_id_to_string(def_id));
1379 let span = tcx
1380 .def_ident_span(def_id)
1381 .unwrap_or_else(|| tcx.def_span(def_id));
1382 diag.span_help(
1383 span,
1384 msg!("when checking external crate, include the file or module where the excluded item is defined"),
1385 );
1386 diag
1387 }
1388 QueryErr::MissingAssocReft { name, .. } => {
1389 let mut diag = dcx.struct_span_err(cx_span, MISSING_ASSOC_REFT);
1390 diag.arg("name", name);
1391 diag.code(E0999);
1392 diag
1393 }
1394 QueryErr::OpaqueStruct { struct_id } => {
1395 let mut diag = dcx.struct_span_err(cx_span, OPAQUE_STRUCT);
1396 diag.arg("struct", tcx.def_path_str(struct_id));
1397 diag.span_label(
1398 cx_span,
1399 msg!("operation accesses the internal representation of `{$struct}`"),
1400 );
1401 if let ErrCtxt::FnCheck(_, fn_def_id) = self.cx {
1402 let fn_span = tcx.def_span(fn_def_id);
1403 if fn_span.in_derive_expansion() {
1404 diag.span_label(
1406 tcx.def_span(struct_id),
1407 msg!("help: this code was generated by a `#[derive(..)]` and cannot be annotated directly; try annotating this type with `#[flux::trusted_derive]`"),
1408 );
1409 } else {
1410 diag.arg("def_kind", tcx.def_descr(fn_def_id.to_def_id()));
1411 diag.span_label(
1412 fn_span,
1413 msg!("help: try annotating this {$def_kind} with `#[trusted]`"),
1414 );
1415 }
1416 diag.note(
1417 msg!("opaque structs can only be accessed in trusted code (see <https://flux-rs.github.io/flux/guide/specifications.html#opaque-structs>)"),
1418 );
1419 }
1420 diag
1421 }
1422 QueryErr::InvalidGenericArg { .. }
1423 | QueryErr::Emitted(_)
1424 | QueryErr::Bug { .. } => {
1425 let mut diag = self.err.into_diag(dcx, level);
1426 diag.span(cx_span);
1427 diag
1428 }
1429 };
1430 diag.code(E0999);
1431 diag
1432 },
1433 )
1434 }
1435}
1436
1437impl From<ErrorGuaranteed> for QueryErr {
1438 fn from(err: ErrorGuaranteed) -> Self {
1439 Self::Emitted(err)
1440 }
1441}
1442
1443pub fn try_query<T>(f: impl FnOnce() -> QueryResult<T>) -> QueryResult<T> {
1444 f()
1445}