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