use std::{
cell::{OnceCell, RefCell},
rc::Rc,
};
use flux_arc_interner::List;
use flux_errors::{ErrorGuaranteed, E0999};
use flux_rustc_bridge::{
self, def_id_to_string,
lowering::{self, Lower, UnsupportedErr},
mir, ty,
};
use itertools::Itertools;
use rustc_data_structures::unord::{ExtendUnord, UnordMap};
use rustc_errors::Diagnostic;
use rustc_hir::{
def::DefKind,
def_id::{DefId, LocalDefId},
};
use rustc_macros::{Decodable, Encodable};
use rustc_span::{Span, Symbol};
use crate::{
fhir,
global_env::GlobalEnv,
rty::{
self,
refining::{self, Refiner},
},
MaybeExternId, ResolvedDefId,
};
type Cache<K, V> = RefCell<UnordMap<K, V>>;
pub type QueryResult<T = ()> = Result<T, QueryErr>;
#[derive(Debug, Clone, Encodable, Decodable)]
pub enum QueryErr {
Unsupported {
def_id: DefId,
err: UnsupportedErr,
},
Ignored {
def_id: DefId,
},
InvalidGenericArg {
def_id: DefId,
},
InvalidAssocReft {
container_def_id: DefId,
name: Symbol,
},
Bug {
def_id: Option<DefId>,
location: String,
msg: String,
},
Emitted(ErrorGuaranteed),
}
#[macro_export]
macro_rules! query_bug {
($fmt:literal $(,$args:expr)* $(,)?) => {
$crate::queries::QueryErr::bug(None, format_args!($fmt, $($args),*))
};
($def_id:expr, $fmt:literal $(,$args:expr)* $(,)? ) => {{
$crate::queries::QueryErr::bug(Some($def_id.into()), format_args!($fmt, $($args),*))
}};
}
impl QueryErr {
pub fn unsupported(def_id: DefId, err: UnsupportedErr) -> Self {
QueryErr::Unsupported { def_id, err }
}
#[track_caller]
pub fn bug(def_id: Option<DefId>, msg: impl ToString) -> Self {
QueryErr::Bug {
def_id,
location: format!("{}", std::panic::Location::caller()),
msg: msg.to_string(),
}
}
pub fn at(self, span: Span) -> QueryErrAt {
QueryErrAt { span, err: self }
}
}
pub struct QueryErrAt {
span: Span,
err: QueryErr,
}
pub struct Providers {
pub collect_specs: fn(GlobalEnv) -> crate::Specs,
pub resolve_crate: fn(GlobalEnv) -> crate::ResolverOutput,
pub desugar: for<'genv> fn(
GlobalEnv<'genv, '_>,
LocalDefId,
) -> QueryResult<UnordMap<LocalDefId, fhir::Node<'genv>>>,
pub fhir_crate: for<'genv> fn(GlobalEnv<'genv, '_>) -> fhir::FluxItems<'genv>,
pub qualifiers: fn(GlobalEnv) -> QueryResult<Vec<rty::Qualifier>>,
pub spec_func_defns: fn(GlobalEnv) -> QueryResult<rty::SpecFuncDefns>,
pub spec_func_decl: fn(GlobalEnv, Symbol) -> QueryResult<rty::SpecFuncDecl>,
pub adt_sort_def_of: fn(GlobalEnv, LocalDefId) -> QueryResult<rty::AdtSortDef>,
pub check_wf: for<'genv> fn(GlobalEnv, LocalDefId) -> QueryResult<Rc<rty::WfckResults>>,
pub adt_def: fn(GlobalEnv, LocalDefId) -> QueryResult<rty::AdtDef>,
pub type_of: fn(GlobalEnv, LocalDefId) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>>,
pub variants_of: fn(
GlobalEnv,
LocalDefId,
) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>>,
pub fn_sig: fn(GlobalEnv, LocalDefId) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>>,
pub generics_of: fn(GlobalEnv, LocalDefId) -> QueryResult<rty::Generics>,
pub refinement_generics_of: fn(GlobalEnv, LocalDefId) -> QueryResult<rty::RefinementGenerics>,
pub predicates_of:
fn(GlobalEnv, LocalDefId) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>>,
pub assoc_refinements_of: fn(GlobalEnv, LocalDefId) -> QueryResult<rty::AssocRefinements>,
pub sort_of_assoc_reft:
fn(GlobalEnv, LocalDefId, Symbol) -> QueryResult<Option<rty::EarlyBinder<rty::FuncSort>>>,
pub assoc_refinement_def:
fn(GlobalEnv, LocalDefId, Symbol) -> QueryResult<rty::EarlyBinder<rty::Lambda>>,
pub default_assoc_refinement_def:
fn(GlobalEnv, LocalDefId, Symbol) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>>,
pub item_bounds: fn(GlobalEnv, LocalDefId) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>>,
}
macro_rules! empty_query {
() => {
flux_common::bug!("query not provided")
};
}
impl Default for Providers {
fn default() -> Self {
Self {
collect_specs: |_| empty_query!(),
resolve_crate: |_| empty_query!(),
desugar: |_, _| empty_query!(),
fhir_crate: |_| empty_query!(),
spec_func_defns: |_| empty_query!(),
spec_func_decl: |_, _| empty_query!(),
qualifiers: |_| empty_query!(),
adt_sort_def_of: |_, _| empty_query!(),
check_wf: |_, _| empty_query!(),
adt_def: |_, _| empty_query!(),
type_of: |_, _| empty_query!(),
variants_of: |_, _| empty_query!(),
fn_sig: |_, _| empty_query!(),
generics_of: |_, _| empty_query!(),
refinement_generics_of: |_, _| empty_query!(),
predicates_of: |_, _| empty_query!(),
assoc_refinements_of: |_, _| empty_query!(),
assoc_refinement_def: |_, _, _| empty_query!(),
default_assoc_refinement_def: |_, _, _| empty_query!(),
sort_of_assoc_reft: |_, _, _| empty_query!(),
item_bounds: |_, _| empty_query!(),
}
}
}
pub struct Queries<'genv, 'tcx> {
pub(crate) providers: Providers,
mir: Cache<LocalDefId, QueryResult<Rc<mir::Body<'tcx>>>>,
collect_specs: OnceCell<crate::Specs>,
resolve_crate: OnceCell<crate::ResolverOutput>,
desugar: Cache<LocalDefId, QueryResult<fhir::Node<'genv>>>,
fhir_crate: OnceCell<fhir::FluxItems<'genv>>,
lower_generics_of: Cache<DefId, ty::Generics<'tcx>>,
lower_predicates_of: Cache<DefId, QueryResult<ty::GenericPredicates>>,
lower_type_of: Cache<DefId, QueryResult<ty::EarlyBinder<ty::Ty>>>,
lower_fn_sig: Cache<DefId, QueryResult<ty::EarlyBinder<ty::PolyFnSig>>>,
defns: OnceCell<QueryResult<rty::SpecFuncDefns>>,
func_decls: Cache<Symbol, QueryResult<rty::SpecFuncDecl>>,
qualifiers: OnceCell<QueryResult<Vec<rty::Qualifier>>>,
adt_sort_def_of: Cache<DefId, QueryResult<rty::AdtSortDef>>,
check_wf: Cache<LocalDefId, QueryResult<Rc<rty::WfckResults>>>,
adt_def: Cache<DefId, QueryResult<rty::AdtDef>>,
generics_of: Cache<DefId, QueryResult<rty::Generics>>,
refinement_generics_of: Cache<DefId, QueryResult<rty::RefinementGenerics>>,
predicates_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::GenericPredicates>>>,
assoc_refinements_of: Cache<DefId, QueryResult<rty::AssocRefinements>>,
assoc_refinement_def: Cache<(DefId, Symbol), QueryResult<rty::EarlyBinder<rty::Lambda>>>,
default_assoc_refinement_def:
Cache<(DefId, Symbol), QueryResult<Option<rty::EarlyBinder<rty::Lambda>>>>,
sort_of_assoc_reft:
Cache<(DefId, Symbol), QueryResult<Option<rty::EarlyBinder<rty::FuncSort>>>>,
item_bounds: Cache<DefId, QueryResult<rty::EarlyBinder<List<rty::Clause>>>>,
type_of: Cache<DefId, QueryResult<rty::EarlyBinder<rty::TyOrCtor>>>,
variants_of: Cache<DefId, QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>>>,
fn_sig: Cache<DefId, QueryResult<rty::EarlyBinder<rty::PolyFnSig>>>,
lower_late_bound_vars: Cache<LocalDefId, QueryResult<List<ty::BoundVariableKind>>>,
}
impl<'genv, 'tcx> Queries<'genv, 'tcx> {
pub(crate) fn new(providers: Providers) -> Self {
Self {
providers,
mir: Default::default(),
collect_specs: Default::default(),
resolve_crate: Default::default(),
desugar: Default::default(),
fhir_crate: Default::default(),
lower_generics_of: Default::default(),
lower_predicates_of: Default::default(),
lower_type_of: Default::default(),
lower_fn_sig: Default::default(),
defns: Default::default(),
func_decls: Default::default(),
qualifiers: Default::default(),
adt_sort_def_of: Default::default(),
check_wf: Default::default(),
adt_def: Default::default(),
generics_of: Default::default(),
refinement_generics_of: Default::default(),
predicates_of: Default::default(),
assoc_refinements_of: Default::default(),
assoc_refinement_def: Default::default(),
default_assoc_refinement_def: Default::default(),
sort_of_assoc_reft: Default::default(),
item_bounds: Default::default(),
type_of: Default::default(),
variants_of: Default::default(),
fn_sig: Default::default(),
lower_late_bound_vars: Default::default(),
}
}
pub(crate) fn mir(
&self,
genv: GlobalEnv<'genv, 'tcx>,
def_id: LocalDefId,
) -> QueryResult<Rc<mir::Body<'tcx>>> {
run_with_cache(&self.mir, def_id, || {
let mir = unsafe { flux_common::mir_storage::retrieve_mir_body(genv.tcx(), def_id) };
let mir =
lowering::MirLoweringCtxt::lower_mir_body(genv.tcx(), genv.sess(), def_id, mir)?;
Ok(Rc::new(mir))
})
}
pub(crate) fn collect_specs(&'genv self, genv: GlobalEnv<'genv, 'tcx>) -> &'genv crate::Specs {
self.collect_specs
.get_or_init(|| (self.providers.collect_specs)(genv))
}
pub(crate) fn resolve_crate(
&'genv self,
genv: GlobalEnv<'genv, 'tcx>,
) -> &'genv crate::ResolverOutput {
self.resolve_crate
.get_or_init(|| (self.providers.resolve_crate)(genv))
}
pub(crate) fn desugar(
&'genv self,
genv: GlobalEnv<'genv, 'tcx>,
def_id: LocalDefId,
) -> QueryResult<fhir::Node<'genv>> {
if let Some(v) = self.desugar.borrow().get(&def_id) {
return v.clone();
}
match (self.providers.desugar)(genv, def_id) {
Ok(nodes) => {
let mut cache = self.desugar.borrow_mut();
cache.extend_unord(nodes.into_items().map(|(def_id, node)| (def_id, Ok(node))));
cache[&def_id].clone()
}
Err(err) => {
self.desugar.borrow_mut().insert(def_id, Err(err.clone()));
Err(err)
}
}
}
pub(crate) fn fhir_crate(
&'genv self,
genv: GlobalEnv<'genv, 'tcx>,
) -> &'genv fhir::FluxItems<'genv> {
self.fhir_crate
.get_or_init(|| (self.providers.fhir_crate)(genv))
}
pub(crate) fn lower_generics_of(
&self,
genv: GlobalEnv<'genv, 'tcx>,
def_id: DefId,
) -> ty::Generics<'tcx> {
run_with_cache(&self.lower_generics_of, def_id, || {
genv.tcx().generics_of(def_id).lower(genv.tcx())
})
}
pub(crate) fn lower_predicates_of(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<ty::GenericPredicates> {
run_with_cache(&self.lower_predicates_of, def_id, || {
genv.tcx()
.predicates_of(def_id)
.lower(genv.tcx())
.map_err(|err| QueryErr::unsupported(def_id, err))
})
}
pub(crate) fn lower_type_of(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<ty::EarlyBinder<ty::Ty>> {
run_with_cache(&self.lower_type_of, def_id, || {
let ty = genv.tcx().type_of(def_id).instantiate_identity();
Ok(ty::EarlyBinder(
ty.lower(genv.tcx())
.map_err(|err| QueryErr::unsupported(def_id, err.into_err()))?,
))
})
}
pub(crate) fn lower_fn_sig(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<ty::EarlyBinder<ty::PolyFnSig>> {
run_with_cache(&self.lower_fn_sig, def_id, || {
let fn_sig = genv.tcx().fn_sig(def_id).instantiate_identity();
Ok(ty::EarlyBinder(
fn_sig
.lower(genv.tcx())
.map_err(|err| QueryErr::unsupported(def_id, err.into_err()))?,
))
})
}
pub(crate) fn lower_late_bound_vars(
&self,
genv: GlobalEnv,
def_id: LocalDefId,
) -> QueryResult<List<ty::BoundVariableKind>> {
run_with_cache(&self.lower_late_bound_vars, def_id, || {
let hir_id = genv.tcx().local_def_id_to_hir_id(def_id);
genv.tcx()
.late_bound_vars(hir_id)
.lower(genv.tcx())
.map_err(|err| QueryErr::unsupported(def_id.to_def_id(), err.into_err()))
})
}
pub(crate) fn spec_func_defns(&self, genv: GlobalEnv) -> QueryResult<&rty::SpecFuncDefns> {
self.defns
.get_or_init(|| (self.providers.spec_func_defns)(genv))
.as_ref()
.map_err(Clone::clone)
}
pub(crate) fn func_decl(
&self,
genv: GlobalEnv,
name: Symbol,
) -> QueryResult<rty::SpecFuncDecl> {
run_with_cache(&self.func_decls, name, || (self.providers.spec_func_decl)(genv, name))
}
pub(crate) fn qualifiers(&self, genv: GlobalEnv) -> QueryResult<&[rty::Qualifier]> {
self.qualifiers
.get_or_init(|| (self.providers.qualifiers)(genv))
.as_deref()
.map_err(Clone::clone)
}
pub(crate) fn adt_sort_def_of(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<rty::AdtSortDef> {
run_with_cache(&self.adt_sort_def_of, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.adt_sort_def_of)(genv, def_id.local_id()),
|def_id| genv.cstore().adt_sort_def(def_id),
|def_id| Ok(rty::AdtSortDef::new(def_id, vec![], vec![])),
)
})
}
pub(crate) fn check_wf(
&self,
genv: GlobalEnv<'genv, '_>,
def_id: LocalDefId,
) -> QueryResult<Rc<rty::WfckResults>> {
run_with_cache(&self.check_wf, def_id, || (self.providers.check_wf)(genv, def_id))
}
pub(crate) fn adt_def(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::AdtDef> {
run_with_cache(&self.adt_def, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.adt_def)(genv, def_id.local_id()),
|def_id| genv.cstore().adt_def(def_id),
|def_id| {
let adt_def = genv.tcx().adt_def(def_id).lower(genv.tcx());
Ok(rty::AdtDef::new(adt_def, genv.adt_sort_def_of(def_id)?, vec![], false))
},
)
})
}
pub(crate) fn generics_of(&self, genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::Generics> {
run_with_cache(&self.generics_of, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.generics_of)(genv, def_id.local_id()),
|def_id| genv.cstore().generics_of(def_id),
|def_id| refining::refine_generics(genv, def_id, &genv.lower_generics_of(def_id)),
)
})
}
pub(crate) fn refinement_generics_of(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<rty::RefinementGenerics> {
run_with_cache(&self.refinement_generics_of, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.refinement_generics_of)(genv, def_id.local_id()),
|def_id| genv.cstore().refinement_generics_of(def_id),
|def_id| {
let parent = genv.tcx().generics_of(def_id).parent;
Ok(rty::RefinementGenerics { parent, parent_count: 0, params: List::empty() })
},
)
})
}
pub(crate) fn item_bounds(
&self,
genv: GlobalEnv<'genv, 'tcx>,
def_id: DefId,
) -> QueryResult<rty::EarlyBinder<List<rty::Clause>>> {
run_with_cache(&self.item_bounds, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.item_bounds)(genv, def_id.local_id()),
|def_id| genv.cstore().item_bounds(def_id),
|def_id| {
let clauses = genv
.tcx()
.item_bounds(def_id)
.skip_binder()
.lower(genv.tcx())
.map_err(|err| QueryErr::unsupported(def_id, err))?;
let clauses = Refiner::default(genv, def_id)?.refine_clauses(&clauses)?;
Ok(rty::EarlyBinder(clauses))
},
)
})
}
pub(crate) fn predicates_of(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
run_with_cache(&self.predicates_of, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.predicates_of)(genv, def_id.local_id()),
|def_id| genv.cstore().predicates_of(def_id),
|def_id| {
let predicates = genv.lower_predicates_of(def_id)?;
let predicates =
Refiner::default(genv, def_id)?.refine_generic_predicates(&predicates)?;
Ok(rty::EarlyBinder(predicates))
},
)
})
}
pub(crate) fn assoc_refinements_of(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<rty::AssocRefinements> {
run_with_cache(&self.assoc_refinements_of, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.assoc_refinements_of)(genv, def_id.local_id()),
|def_id| genv.cstore().assoc_refinements_of(def_id),
|_| Ok(rty::AssocRefinements::default()),
)
})
}
pub(crate) fn assoc_refinement_def(
&self,
genv: GlobalEnv,
impl_id: DefId,
name: Symbol,
) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
run_with_cache(&self.assoc_refinement_def, (impl_id, name), || {
dispatch_query(
genv,
impl_id,
|impl_id| (self.providers.assoc_refinement_def)(genv, impl_id.local_id(), name),
|impl_id| genv.cstore().assoc_refinements_def((impl_id, name)),
|impl_id| {
Err(query_bug!(
impl_id,
"cannot generate default associate refinement for extern impl"
))
},
)
})
}
pub(crate) fn default_assoc_refinement_def(
&self,
genv: GlobalEnv,
trait_id: DefId,
name: Symbol,
) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>> {
run_with_cache(&self.default_assoc_refinement_def, (trait_id, name), || {
dispatch_query(
genv,
trait_id,
|trait_id| {
(self.providers.default_assoc_refinement_def)(genv, trait_id.local_id(), name)
},
|trait_id| {
genv.cstore()
.default_assoc_refinements_def((trait_id, name))
},
|trait_id| {
Err(query_bug!(
trait_id,
"cannot generate default assoc refinement for extern trait"
))
},
)
})
}
pub(crate) fn sort_of_assoc_reft(
&self,
genv: GlobalEnv,
def_id: DefId,
name: Symbol,
) -> QueryResult<Option<rty::EarlyBinder<rty::FuncSort>>> {
run_with_cache(&self.sort_of_assoc_reft, (def_id, name), || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.sort_of_assoc_reft)(genv, def_id.local_id(), name),
|def_id| genv.cstore().sort_of_assoc_reft((def_id, name)),
|def_id| {
Err(query_bug!(
def_id,
"cannot generate default sort for assoc refinement in extern crate"
))
},
)
})
}
pub(crate) fn type_of(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>> {
run_with_cache(&self.type_of, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.type_of)(genv, def_id.local_id()),
|def_id| genv.cstore().type_of(def_id),
|def_id| {
let generics_def_id = match genv.def_kind(def_id) {
DefKind::TyParam => genv.tcx().parent(def_id),
_ => def_id,
};
let ty = genv.lower_type_of(def_id)?.skip_binder();
Ok(rty::EarlyBinder(
Refiner::default(genv, generics_def_id)?
.refine_ty_or_base(&ty)?
.into(),
))
},
)
})
}
pub(crate) fn variants_of(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>> {
run_with_cache(&self.variants_of, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.variants_of)(genv, def_id.local_id()),
|def_id| genv.cstore().variants(def_id),
|def_id| {
let variants = genv
.tcx()
.adt_def(def_id)
.variants()
.indices()
.map(|variant_idx| {
Refiner::default(genv, def_id)?.refine_variant_def(def_id, variant_idx)
})
.try_collect()?;
Ok(rty::Opaqueness::Transparent(rty::EarlyBinder(variants)))
},
)
})
}
pub(crate) fn fn_sig(
&self,
genv: GlobalEnv,
def_id: DefId,
) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>> {
run_with_cache(&self.fn_sig, def_id, || {
dispatch_query(
genv,
def_id,
|def_id| (self.providers.fn_sig)(genv, def_id.local_id()),
|def_id| genv.cstore().fn_sig(def_id),
|def_id| {
let fn_sig = genv.lower_fn_sig(def_id)?.skip_binder();
let fn_sig = Refiner::default(genv, def_id)?.refine_poly_fn_sig(&fn_sig)?;
Ok(rty::EarlyBinder(fn_sig))
},
)
})
}
}
fn dispatch_query<R>(
genv: GlobalEnv,
def_id: DefId,
local: impl FnOnce(MaybeExternId) -> R,
external: impl FnOnce(DefId) -> Option<R>,
default: impl FnOnce(DefId) -> R,
) -> R {
match genv.resolve_id(def_id) {
ResolvedDefId::Local(local_id) => {
local(MaybeExternId::Local(local_id))
}
ResolvedDefId::ExternSpec(local_id, def_id) => {
local(MaybeExternId::Extern(local_id, def_id))
}
ResolvedDefId::Extern(def_id) if let Some(v) = external(def_id) => {
v
}
ResolvedDefId::Extern(def_id) => {
default(def_id)
}
}
}
fn run_with_cache<K, V>(cache: &Cache<K, V>, key: K, f: impl FnOnce() -> V) -> V
where
K: std::hash::Hash + Eq,
V: Clone,
{
if let Some(v) = cache.borrow().get(&key) {
return v.clone();
}
let v = f();
cache.borrow_mut().insert(key, v.clone());
v
}
impl<'a> Diagnostic<'a> for QueryErr {
#[track_caller]
fn into_diag(
self,
dcx: rustc_errors::DiagCtxtHandle<'a>,
_level: rustc_errors::Level,
) -> rustc_errors::Diag<'a, ErrorGuaranteed> {
use crate::fluent_generated as fluent;
rustc_middle::ty::tls::with_opt(
#[track_caller]
|tcx| {
let tcx = tcx.expect("no TyCtxt stored in tls");
match self {
QueryErr::Unsupported { def_id, err } => {
let span = err.span.unwrap_or_else(|| tcx.def_span(def_id));
let mut diag = dcx.struct_span_err(span, fluent::middle_query_unsupported);
diag.code(E0999);
diag.note(err.descr);
diag
}
QueryErr::Ignored { def_id } => {
let def_span = tcx.def_span(def_id);
let mut diag =
dcx.struct_span_err(def_span, fluent::middle_query_ignored_item);
diag.code(E0999);
diag
}
QueryErr::InvalidGenericArg { def_id } => {
let def_span = tcx.def_span(def_id);
let mut diag =
dcx.struct_span_err(def_span, fluent::middle_query_invalid_generic_arg);
diag.code(E0999);
diag
}
QueryErr::InvalidAssocReft { container_def_id: impl_id, name } => {
let def_span = tcx.def_span(impl_id);
let mut diag =
dcx.struct_span_err(def_span, fluent::middle_query_invalid_assoc_reft);
diag.arg("name", name);
diag.code(E0999);
diag
}
QueryErr::Bug { def_id, location, msg } => {
let mut diag = dcx.struct_err(fluent::middle_query_bug);
if let Some(def_id) = def_id {
diag.span(tcx.def_span(def_id));
}
diag.arg("location", location);
diag.note(msg);
diag
}
QueryErr::Emitted(_) => {
let mut diag = dcx.struct_err("QueryErr::Emitted should be emitted");
diag.downgrade_to_delayed_bug();
diag
}
}
},
)
}
}
impl<'a> Diagnostic<'a> for QueryErrAt {
#[track_caller]
fn into_diag(
self,
dcx: rustc_errors::DiagCtxtHandle<'a>,
level: rustc_errors::Level,
) -> rustc_errors::Diag<'a, ErrorGuaranteed> {
use crate::fluent_generated as fluent;
rustc_middle::ty::tls::with_opt(
#[track_caller]
|tcx| {
let tcx = tcx.expect("no TyCtxt stored in tls");
let mut diag = match self.err {
QueryErr::Unsupported { def_id, err, .. } => {
let mut diag =
dcx.struct_span_err(self.span, fluent::middle_query_unsupported_at);
diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
if let Some(def_ident_span) = tcx.def_ident_span(def_id) {
diag.span_note(def_ident_span, fluent::_subdiag::note);
}
diag.note(err.descr);
diag
}
QueryErr::Ignored { def_id } => {
let mut diag =
dcx.struct_span_err(self.span, fluent::middle_query_ignored_at);
diag.arg("kind", tcx.def_kind(def_id).descr(def_id));
diag.arg("name", def_id_to_string(def_id));
diag.span_label(self.span, fluent::_subdiag::label);
diag
}
QueryErr::InvalidAssocReft { .. } => {
let mut diag = dcx
.struct_span_err(self.span, fluent::middle_query_invalid_assoc_reft_at);
diag.code(E0999);
diag
}
QueryErr::InvalidGenericArg { .. }
| QueryErr::Emitted(_)
| QueryErr::Bug { .. } => {
let mut diag = self.err.into_diag(dcx, level);
diag.span(self.span);
diag
}
};
diag.code(E0999);
diag
},
)
}
}
impl From<ErrorGuaranteed> for QueryErr {
fn from(err: ErrorGuaranteed) -> Self {
Self::Emitted(err)
}
}