Skip to content

Commit

Permalink
Add queries for lower generic and lower generic predicates (#590)
Browse files Browse the repository at this point in the history
  • Loading branch information
nilehmann authored Jan 2, 2024
1 parent 5652293 commit 2ca82a0
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 86 deletions.
6 changes: 2 additions & 4 deletions crates/flux-fhir-analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ use flux_middle::{
fhir::{self, FluxLocalDefId, WfckResults},
global_env::GlobalEnv,
intern::List,
queries::{Providers, QueryErr, QueryResult},
queries::{Providers, QueryResult},
rty::{self, fold::TypeFoldable, refining::Refiner},
rustc::lowering,
};
use itertools::Itertools;
use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, SubdiagnosticMessage};
Expand Down Expand Up @@ -143,8 +142,7 @@ fn item_bounds(

fn generics_of(genv: &GlobalEnv, local_id: LocalDefId) -> QueryResult<rty::Generics> {
let def_id = local_id.to_def_id();
let rustc_generics = lowering::lower_generics(genv.tcx.generics_of(def_id))
.map_err(|err| QueryErr::unsupported(genv.tcx, def_id, err))?;
let rustc_generics = genv.lower_generics_of(local_id)?;

let def_kind = genv.tcx.def_kind(def_id);
match def_kind {
Expand Down
4 changes: 2 additions & 2 deletions crates/flux-middle/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ middle_unsupported_generic_bound =
# Query Errors

middle_query_unsupported_type =
unsupported type
middle_query_unsupported =
unsupported signature
.note = {$reason}
11 changes: 11 additions & 0 deletions crates/flux-middle/src/global_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ impl<'sess, 'tcx> GlobalEnv<'sess, 'tcx> {
self.queries.mir(self, def_id)
}

pub fn lower_generics_of(&self, def_id: impl Into<DefId>) -> QueryResult<ty::Generics<'tcx>> {
self.queries.lower_generics_of(self, def_id.into())
}

pub fn lower_predicates_of(
&self,
def_id: impl Into<DefId>,
) -> QueryResult<ty::GenericPredicates> {
self.queries.lower_predicates_of(self, def_id.into())
}

pub fn lower_type_of(&self, def_id: impl Into<DefId>) -> QueryResult<ty::EarlyBinder<ty::Ty>> {
self.queries.lower_type_of(self, def_id.into())
}
Expand Down
69 changes: 47 additions & 22 deletions crates/flux-middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::{
},
rustc::{
self,
lowering::{self, UnsupportedReason},
lowering::{self, UnsupportedErr, UnsupportedReason},
ty,
},
};
Expand All @@ -39,7 +39,7 @@ pub type QueryResult<T = ()> = Result<T, QueryErr>;

#[derive(Debug, Clone)]
pub enum QueryErr {
UnsupportedType { def_id: DefId, def_span: Span, reason: UnsupportedReason },
Unsupported { def_id: DefId, def_span: Span, err: UnsupportedErr },
Emitted(ErrorGuaranteed),
}

Expand Down Expand Up @@ -89,6 +89,8 @@ impl Default for Providers {
pub struct Queries<'tcx> {
pub(crate) providers: Providers,
mir: Cache<LocalDefId, QueryResult<Rc<rustc::mir::Body<'tcx>>>>,
lower_generics_of: Cache<DefId, QueryResult<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::Defns>>,
Expand Down Expand Up @@ -118,6 +120,31 @@ impl<'tcx> Queries<'tcx> {
})
}

pub(crate) fn lower_generics_of(
&self,
genv: &GlobalEnv<'_, 'tcx>,
def_id: DefId,
) -> QueryResult<ty::Generics<'tcx>> {
run_with_cache(&self.lower_generics_of, def_id, || {
let generics = genv.tcx.generics_of(def_id);
lowering::lower_generics(generics)
.map_err(UnsupportedReason::to_err)
.map_err(|err| QueryErr::unsupported(genv.tcx, def_id, err))
})
}

pub(crate) fn lower_predicates_of(
&self,
genv: &GlobalEnv,
def_id: DefId,
) -> QueryResult<ty::GenericPredicates> {
run_with_cache(&self.lower_predicates_of, def_id, || {
let predicates = genv.tcx.predicates_of(def_id);
lowering::lower_generic_predicates(genv.tcx, predicates)
.map_err(|err| QueryErr::unsupported(genv.tcx, def_id, err))
})
}

pub(crate) fn lower_type_of(
&self,
genv: &GlobalEnv,
Expand All @@ -127,7 +154,8 @@ impl<'tcx> Queries<'tcx> {
let ty = genv.tcx.type_of(def_id).instantiate_identity();
Ok(ty::EarlyBinder(
lowering::lower_ty(genv.tcx, ty)
.map_err(|reason| QueryErr::unsupported(genv.tcx, def_id, reason))?,
.map_err(UnsupportedReason::to_err)
.map_err(|err| QueryErr::unsupported(genv.tcx, def_id, err))?,
))
})
}
Expand All @@ -148,7 +176,8 @@ impl<'tcx> Queries<'tcx> {
.normalize(fn_sig.instantiate_identity());
Ok(ty::EarlyBinder(
lowering::lower_fn_sig(genv.tcx, result.value)
.map_err(|reason| QueryErr::unsupported(genv.tcx, def_id, reason))?,
.map_err(UnsupportedReason::to_err)
.map_err(|err| QueryErr::unsupported(genv.tcx, def_id, err))?,
))
})
}
Expand Down Expand Up @@ -209,9 +238,7 @@ impl<'tcx> Queries<'tcx> {
if let Some(local_id) = def_id.as_local() {
(self.providers.generics_of)(genv, local_id)
} else {
let generics = genv.tcx.generics_of(def_id);
let generics = lowering::lower_generics(generics)
.map_err(|reason| QueryErr::unsupported(genv.tcx, def_id, reason))?;
let generics = genv.lower_generics_of(def_id)?;
refining::refine_generics(genv, &generics)
}
})
Expand All @@ -228,11 +255,9 @@ impl<'tcx> Queries<'tcx> {
if let Some(local_id) = def_id.as_local() {
(self.providers.item_bounds)(genv, local_id)
} else {
// If there's any error during lowering we blame the span of the definition of
// the opaque type, i.e. the span of the `impl Trait`
let span = genv.tcx.def_span(def_id);
let bounds = genv.tcx.item_bounds(def_id).skip_binder();
let clauses = lowering::lower_item_bounds(genv.tcx, genv.sess, bounds, span)?;
let clauses = lowering::lower_item_bounds(genv.tcx, bounds)
.map_err(|err| QueryErr::unsupported(genv.tcx, def_id, err))?;

let clauses =
Refiner::default(genv, &genv.generics_of(def_id)?).refine_clauses(&clauses)?;
Expand All @@ -252,10 +277,7 @@ impl<'tcx> Queries<'tcx> {
if let Some(local_id) = def_id.as_local() {
(self.providers.predicates_of)(genv, local_id)
} else {
let predicates = genv.tcx.predicates_of(def_id);
let predicates =
lowering::lower_generic_predicates(genv.tcx, genv.sess, predicates)?;

let predicates = genv.lower_predicates_of(def_id)?;
let predicates = Refiner::default(genv, &genv.generics_of(def_id)?)
.refine_generic_predicates(&predicates)?;
Ok(rty::EarlyBinder(predicates))
Expand Down Expand Up @@ -353,7 +375,8 @@ impl<'tcx> Queries<'tcx> {
let hir_id = genv.hir().local_def_id_to_hir_id(def_id);
let bound_vars = genv.tcx.late_bound_vars(hir_id);
lowering::lower_bound_vars(bound_vars)
.map_err(|reason| QueryErr::unsupported(genv.tcx, def_id.to_def_id(), reason))
.map_err(UnsupportedReason::to_err)
.map_err(|err| QueryErr::unsupported(genv.tcx, def_id.to_def_id(), err))
})
}
}
Expand All @@ -372,8 +395,8 @@ where
}

impl QueryErr {
pub fn unsupported(tcx: TyCtxt, def_id: DefId, reason: UnsupportedReason) -> Self {
QueryErr::UnsupportedType { def_id, def_span: tcx.def_span(def_id), reason }
pub fn unsupported(tcx: TyCtxt, def_id: DefId, err: UnsupportedErr) -> Self {
QueryErr::Unsupported { def_id, def_span: tcx.def_span(def_id), err }
}
}

Expand All @@ -384,12 +407,14 @@ impl<'a> IntoDiagnostic<'a> for QueryErr {
) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> {
use crate::fluent_generated as fluent;
match self {
QueryErr::UnsupportedType { reason, .. } => {
let mut builder = handler.struct_err_with_code(
fluent::middle_query_unsupported_type,
QueryErr::Unsupported { err, def_span, .. } => {
let span = err.span.unwrap_or(def_span);
let mut builder = handler.struct_span_err_with_code(
span,
fluent::middle_query_unsupported,
flux_errors::diagnostic_id(),
);
builder.note(reason.descr);
builder.note(err.descr);
builder
}
QueryErr::Emitted(_) => {
Expand Down
100 changes: 43 additions & 57 deletions crates/flux-middle/src/rustc/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,33 @@ pub struct UnsupportedReason {
pub(crate) descr: String,
}

impl UnsupportedReason {
fn new(reason: impl ToString) -> Self {
UnsupportedReason { descr: reason.to_string() }
}

pub(crate) fn to_err(self) -> UnsupportedErr {

Check warning on line 55 in crates/flux-middle/src/rustc/lowering.rs

View workflow job for this annotation

GitHub Actions / clippy

methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference

warning: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference --> crates/flux-middle/src/rustc/lowering.rs:55:26 | 55 | pub(crate) fn to_err(self) -> UnsupportedErr { | ^^^^ | = help: consider choosing a less ambiguous name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention = note: `#[warn(clippy::wrong_self_convention)]` on by default
UnsupportedErr { descr: self.descr, span: None }
}
}

#[derive(Debug, Clone)]
pub struct UnsupportedErr {
pub(crate) descr: String,
pub(crate) span: Option<Span>,
}

impl UnsupportedErr {
fn new(reason: UnsupportedReason) -> Self {
UnsupportedErr { descr: reason.descr, span: None }
}

fn with_span(mut self, span: Span) -> Self {
self.span = Some(span);
self
}
}

impl<'sess, 'tcx> LoweringCtxt<'_, 'sess, 'tcx> {
pub fn lower_mir_body(
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -558,12 +585,6 @@ pub fn lower_place(place: &rustc_mir::Place) -> Result<Place, UnsupportedReason>
Ok(Place { local: place.local, projection })
}

impl UnsupportedReason {
fn new(reason: impl ToString) -> Self {
UnsupportedReason { descr: reason.to_string() }
}
}

pub(crate) fn lower_fn_sig<'tcx>(
tcx: TyCtxt<'tcx>,
fn_sig: rustc_ty::PolyFnSig<'tcx>,
Expand Down Expand Up @@ -752,7 +773,7 @@ fn lower_bound_region(
Ok(BoundRegion { kind: bregion.kind, var: bregion.var })
}

pub fn lower_generics(generics: &rustc_ty::Generics) -> Result<Generics, UnsupportedReason> {
pub(crate) fn lower_generics(generics: &rustc_ty::Generics) -> Result<Generics, UnsupportedReason> {
let params = List::from_vec(
generics
.params
Expand Down Expand Up @@ -781,82 +802,62 @@ fn lower_generic_param_def(

pub(crate) fn lower_generic_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
sess: &FluxSession,
generics: rustc_ty::GenericPredicates<'tcx>,
) -> Result<GenericPredicates, ErrorGuaranteed> {
) -> Result<GenericPredicates, UnsupportedErr> {
let predicates = generics
.predicates
.iter()
.map(|(clause, span)| lower_clause(tcx, sess, clause, *span))
.map(|(clause, span)| {
lower_clause(tcx, clause).map_err(|reason| UnsupportedErr::new(reason).with_span(*span))
})
.try_collect()?;
Ok(GenericPredicates { parent: generics.parent, predicates })
}

pub(crate) fn lower_item_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
sess: &FluxSession,
bounds: &[rustc_ty::Clause<'tcx>],
span: Span,
) -> Result<List<Clause>, ErrorGuaranteed> {
) -> Result<List<Clause>, UnsupportedErr> {
bounds
.iter()
.map(|clause| lower_clause(tcx, sess, clause, span))
.map(|clause| lower_clause(tcx, clause).map_err(UnsupportedErr::new))
.try_collect()
}

fn lower_clause<'tcx>(
tcx: TyCtxt<'tcx>,
sess: &FluxSession,
clause: &rustc_ty::Clause<'tcx>,
span: Span,
) -> Result<Clause, ErrorGuaranteed> {
) -> Result<Clause, UnsupportedReason> {
let Some(kind) = clause.kind().no_bound_vars() else {
return Err(sess.emit_err(errors::UnsupportedGenericBound::new(
span,
"higher-rank trait bounds are not supported",
)));
return Err(UnsupportedReason::new("higher-rank trait bounds are not supported"));
};
let kind = match kind {
rustc_ty::ClauseKind::Trait(trait_pred) => {
ClauseKind::Trait(TraitPredicate {
trait_ref: TraitRef {
def_id: trait_pred.trait_ref.def_id,
args: lower_generic_args(tcx, trait_pred.trait_ref.args)
.map_err(|err| errors::UnsupportedGenericBound::new(span, err.descr))
.emit(sess)?,
args: lower_generic_args(tcx, trait_pred.trait_ref.args)?,
},
})
}
rustc_ty::ClauseKind::Projection(proj_pred) => {
let Some(term) = proj_pred.term.ty() else {
return Err(sess.emit_err(errors::UnsupportedGenericBound::new(
span,
format!("unsupported projection predicate `{proj_pred:?}`"),
return Err(UnsupportedReason::new(format!(
"unsupported projection predicate `{proj_pred:?}`"
)));
};
let proj_ty = proj_pred.projection_ty;
let args = lower_generic_args(tcx, proj_ty.args)
.map_err(|err| errors::UnsupportedGenericBound::new(span, err.descr))
.emit(sess)?;
let args = lower_generic_args(tcx, proj_ty.args)?;

let projection_ty = AliasTy { args, def_id: proj_ty.def_id };
let term = lower_ty(tcx, term)
.map_err(|err| errors::UnsupportedGenericBound::new(span, err.descr))
.emit(sess)?;
let term = lower_ty(tcx, term)?;
ClauseKind::Projection(ProjectionPredicate { projection_ty, term })
}
rustc_ty::ClauseKind::TypeOutlives(outlives_pred) => {
ClauseKind::TypeOutlives(
lower_type_outlives(tcx, outlives_pred)
.map_err(|err| errors::UnsupportedGenericBound::new(span, err.descr))
.emit(sess)?,
)
ClauseKind::TypeOutlives(lower_type_outlives(tcx, outlives_pred)?)
}
_ => {
return Err(sess.emit_err(errors::UnsupportedGenericBound::new(
span,
format!("unsupported clause kind `{kind:?}`"),
)));
return Err(UnsupportedReason::new(format!("unsupported clause kind `{kind:?}`")));
}
};
Ok(Clause::new(kind))
Expand Down Expand Up @@ -941,19 +942,4 @@ mod errors {
)
}
}

#[derive(Diagnostic)]
#[diag(middle_unsupported_generic_bound, code = "FLUX")]
#[note]
pub struct UnsupportedGenericBound {
#[primary_span]
span: Span,
reason: String,
}

impl UnsupportedGenericBound {
pub fn new(span: Span, reason: impl ToString) -> Self {
Self { span, reason: reason.to_string() }
}
}
}
3 changes: 2 additions & 1 deletion crates/flux-middle/src/rustc/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::{
pretty::def_id_to_string,
};

#[derive(Clone)]
pub struct Generics<'tcx> {
pub params: List<GenericParamDef>,
pub orig: &'tcx rustc_middle::ty::Generics,
Expand Down Expand Up @@ -57,7 +58,7 @@ pub enum GenericParamDefKind {
Const { has_default: bool },
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct GenericPredicates {
pub parent: Option<DefId>,
pub predicates: List<Clause>,
Expand Down

0 comments on commit 2ca82a0

Please sign in to comment.