Use QuantifiedWhereClause in generic_predicates as well

Still far too much binder skipping going on; I find it hard to imagine
this is all correct, but the tests pass.
This commit is contained in:
Florian Diebold 2021-03-21 17:40:14 +01:00
parent 590c416359
commit 1d5c4a77fb
9 changed files with 28 additions and 37 deletions

View file

@ -236,11 +236,7 @@ impl HirDisplay for TypeParam {
write!(f, "{}", self.name(f.db))?; write!(f, "{}", self.name(f.db))?;
let bounds = f.db.generic_predicates_for_param(self.id); let bounds = f.db.generic_predicates_for_param(self.id);
let substs = Substitution::type_params(f.db, self.id.parent); let substs = Substitution::type_params(f.db, self.id.parent);
let predicates = bounds let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
.iter()
.cloned()
.map(|b| hir_ty::Binders::new(0, b.subst(&substs)))
.collect::<Vec<_>>();
if !(predicates.is_empty() || f.omit_verbose_types()) { if !(predicates.is_empty() || f.omit_verbose_types()) {
write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
} }

View file

@ -1460,7 +1460,7 @@ impl TypeParam {
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
db.generic_predicates_for_param(self.id) db.generic_predicates_for_param(self.id)
.into_iter() .into_iter()
.filter_map(|pred| match &pred.value { .filter_map(|pred| match &pred.skip_binders().skip_binders() {
hir_ty::WhereClause::Implemented(trait_ref) => { hir_ty::WhereClause::Implemented(trait_ref) => {
Some(Trait::from(trait_ref.hir_trait_id())) Some(Trait::from(trait_ref.hir_trait_id()))
} }

View file

@ -12,8 +12,8 @@ use la_arena::ArenaMap;
use crate::{ use crate::{
method_resolution::{InherentImpls, TraitImpls}, method_resolution::{InherentImpls, TraitImpls},
traits::chalk, traits::chalk,
Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, ReturnTypeImplTraits, Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig,
TraitRef, Ty, TyDefId, ValueTyDefId, WhereClause, QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
@ -57,10 +57,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::invoke(crate::lower::generic_predicates_for_param_query)] #[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
#[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
fn generic_predicates_for_param(&self, param_id: TypeParamId) -> Arc<[Binders<WhereClause>]>; fn generic_predicates_for_param(
&self,
param_id: TypeParamId,
) -> Arc<[Binders<QuantifiedWhereClause>]>;
#[salsa::invoke(crate::lower::generic_predicates_query)] #[salsa::invoke(crate::lower::generic_predicates_query)]
fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<WhereClause>]>; fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<QuantifiedWhereClause>]>;
#[salsa::invoke(crate::lower::trait_environment_query)] #[salsa::invoke(crate::lower::trait_environment_query)]
fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>;

View file

@ -581,7 +581,7 @@ impl HirDisplay for Ty {
.generic_predicates(id.parent) .generic_predicates(id.parent)
.into_iter() .into_iter()
.map(|pred| pred.clone().subst(&substs)) .map(|pred| pred.clone().subst(&substs))
.filter(|wc| match &wc { .filter(|wc| match &wc.skip_binders() {
WhereClause::Implemented(tr) => tr.self_type_parameter() == self, WhereClause::Implemented(tr) => tr.self_type_parameter() == self,
WhereClause::AliasEq(AliasEq { WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(proj), alias: AliasTy::Projection(proj),
@ -590,15 +590,7 @@ impl HirDisplay for Ty {
_ => false, _ => false,
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
write_bounds_like_dyn_trait_with_prefix( write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?;
"impl",
&bounds
.iter()
.cloned()
.map(crate::Binders::wrap_empty)
.collect::<Vec<_>>(),
f,
)?;
} }
} }
} }

View file

@ -11,6 +11,7 @@ use hir_def::{
AssocContainerId, FieldId, Lookup, AssocContainerId, FieldId, Lookup,
}; };
use hir_expand::name::{name, Name}; use hir_expand::name::{name, Name};
use stdx::always;
use syntax::ast::RangeOp; use syntax::ast::RangeOp;
use crate::{ use crate::{
@ -936,7 +937,9 @@ impl<'a> InferenceContext<'a> {
let def: CallableDefId = from_chalk(self.db, *fn_def); let def: CallableDefId = from_chalk(self.db, *fn_def);
let generic_predicates = self.db.generic_predicates(def.into()); let generic_predicates = self.db.generic_predicates(def.into());
for predicate in generic_predicates.iter() { for predicate in generic_predicates.iter() {
let predicate = predicate.clone().subst(parameters); let (predicate, binders) =
predicate.clone().subst(parameters).into_value_and_skipped_binders();
always!(binders == 0); // quantified where clauses not yet handled
self.obligations.push(predicate.cast(&Interner)); self.obligations.push(predicate.cast(&Interner));
} }
// add obligation for trait implementation, if this is a trait method // add obligation for trait implementation, if this is a trait method

View file

@ -518,6 +518,10 @@ impl<T> Binders<T> {
pub fn skip_binders(&self) -> &T { pub fn skip_binders(&self) -> &T {
&self.value &self.value
} }
pub fn into_value_and_skipped_binders(self) -> (T, usize) {
(self.value, self.num_binders)
}
} }
impl<T: Clone> Binders<&T> { impl<T: Clone> Binders<&T> {
@ -985,7 +989,7 @@ impl Ty {
.generic_predicates(id.parent) .generic_predicates(id.parent)
.into_iter() .into_iter()
.map(|pred| pred.clone().subst(&substs)) .map(|pred| pred.clone().subst(&substs))
.filter(|wc| match &wc { .filter(|wc| match &wc.skip_binders() {
WhereClause::Implemented(tr) => tr.self_type_parameter() == self, WhereClause::Implemented(tr) => tr.self_type_parameter() == self,
WhereClause::AliasEq(AliasEq { WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(proj), alias: AliasTy::Projection(proj),
@ -993,7 +997,6 @@ impl Ty {
}) => proj.self_type_parameter() == self, }) => proj.self_type_parameter() == self,
_ => false, _ => false,
}) })
.map(Binders::wrap_empty)
.collect_vec(); .collect_vec();
Some(predicates) Some(predicates)

View file

@ -825,7 +825,7 @@ pub fn associated_type_shorthand_candidates<R>(
let predicates = db.generic_predicates_for_param(param_id); let predicates = db.generic_predicates_for_param(param_id);
let mut traits_: Vec<_> = predicates let mut traits_: Vec<_> = predicates
.iter() .iter()
.filter_map(|pred| match &pred.value { .filter_map(|pred| match &pred.value.value {
WhereClause::Implemented(tr) => Some(tr.clone()), WhereClause::Implemented(tr) => Some(tr.clone()),
_ => None, _ => None,
}) })
@ -898,10 +898,7 @@ pub(crate) fn field_types_query(
pub(crate) fn generic_predicates_for_param_query( pub(crate) fn generic_predicates_for_param_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
param_id: TypeParamId, param_id: TypeParamId,
) -> Arc<[Binders<WhereClause>]> { ) -> Arc<[Binders<QuantifiedWhereClause>]> {
// FIXME: these binders are for the type parameters of the def. We need to
// introduce another level of binders for quantified where clauses (for<'a>
// ...)
let resolver = param_id.parent.resolver(db.upcast()); let resolver = param_id.parent.resolver(db.upcast());
let ctx = let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
@ -920,7 +917,7 @@ pub(crate) fn generic_predicates_for_param_query(
WherePredicate::Lifetime { .. } => false, WherePredicate::Lifetime { .. } => false,
}) })
.flat_map(|pred| { .flat_map(|pred| {
ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p.value)) ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p))
}) })
.collect() .collect()
} }
@ -929,7 +926,7 @@ pub(crate) fn generic_predicates_for_param_recover(
_db: &dyn HirDatabase, _db: &dyn HirDatabase,
_cycle: &[String], _cycle: &[String],
_param_id: &TypeParamId, _param_id: &TypeParamId,
) -> Arc<[Binders<WhereClause>]> { ) -> Arc<[Binders<QuantifiedWhereClause>]> {
Arc::new([]) Arc::new([])
} }
@ -984,10 +981,7 @@ pub(crate) fn trait_environment_query(
pub(crate) fn generic_predicates_query( pub(crate) fn generic_predicates_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
def: GenericDefId, def: GenericDefId,
) -> Arc<[Binders<WhereClause>]> { ) -> Arc<[Binders<QuantifiedWhereClause>]> {
// FIXME: these binders are for the type parameters of the def. We need to
// introduce another level of binders for quantified where clauses (for<'a>
// ...)
let resolver = def.resolver(db.upcast()); let resolver = def.resolver(db.upcast());
let ctx = let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
@ -995,7 +989,7 @@ pub(crate) fn generic_predicates_query(
resolver resolver
.where_predicates_in_scope() .where_predicates_in_scope()
.flat_map(|pred| { .flat_map(|pred| {
ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p.value)) ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p))
}) })
.collect() .collect()
} }

View file

@ -537,7 +537,7 @@ pub(super) fn convert_where_clauses(
let generic_predicates = db.generic_predicates(def); let generic_predicates = db.generic_predicates(def);
let mut result = Vec::with_capacity(generic_predicates.len()); let mut result = Vec::with_capacity(generic_predicates.len());
for pred in generic_predicates.iter() { for pred in generic_predicates.iter() {
result.push(crate::Binders::wrap_empty(pred.clone().subst(substs)).to_chalk(db)); result.push(pred.clone().subst(substs).to_chalk(db));
} }
result result
} }

View file

@ -63,7 +63,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
db.generic_predicates_for_param(trait_self) db.generic_predicates_for_param(trait_self)
.iter() .iter()
.filter_map(|pred| { .filter_map(|pred| {
pred.as_ref().filter_map(|pred| match pred { pred.as_ref().filter_map(|pred| match pred.skip_binders() {
WhereClause::Implemented(tr) => Some(tr.clone()), WhereClause::Implemented(tr) => Some(tr.clone()),
_ => None, _ => None,
}) })