7985: Use Chalk Environment more directly r=flodiebold a=flodiebold



Co-authored-by: Florian Diebold <florian.diebold@freiheit.com>
This commit is contained in:
bors[bot] 2021-03-12 19:41:23 +00:00 committed by GitHub
commit 05814e542f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 55 deletions

View file

@ -8,7 +8,7 @@
use std::{iter, sync::Arc}; use std::{iter, sync::Arc};
use base_db::CrateId; use base_db::CrateId;
use chalk_ir::Mutability; use chalk_ir::{cast::Cast, Mutability};
use hir_def::{ use hir_def::{
adt::StructKind, adt::StructKind,
builtin_type::BuiltinType, builtin_type::BuiltinType,
@ -27,6 +27,7 @@ use stdx::impl_from;
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase,
traits::chalk::{Interner, ToChalk},
utils::{ utils::{
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
make_mut_slice, variant_data, make_mut_slice, variant_data,
@ -914,10 +915,21 @@ impl TraitEnvironment {
pub fn lower(db: &dyn HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { pub fn lower(db: &dyn HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> {
let ctx = TyLoweringContext::new(db, &resolver) let ctx = TyLoweringContext::new(db, &resolver)
.with_type_param_mode(TypeParamLoweringMode::Placeholder); .with_type_param_mode(TypeParamLoweringMode::Placeholder);
let mut predicates = resolver let mut traits_in_scope = Vec::new();
.where_predicates_in_scope() let mut clauses = Vec::new();
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) for pred in resolver.where_predicates_in_scope() {
.collect::<Vec<_>>(); for pred in GenericPredicate::from_where_predicate(&ctx, pred) {
if pred.is_error() {
continue;
}
if let GenericPredicate::Implemented(tr) = &pred {
traits_in_scope.push((tr.self_ty().clone(), tr.trait_));
}
let program_clause: chalk_ir::ProgramClause<Interner> =
pred.clone().to_chalk(db).cast(&Interner);
clauses.push(program_clause.into_from_env_clause(&Interner));
}
}
if let Some(def) = resolver.generic_def() { if let Some(def) = resolver.generic_def() {
let container: Option<AssocContainerId> = match def { let container: Option<AssocContainerId> = match def {
@ -938,12 +950,15 @@ impl TraitEnvironment {
let substs = Substs::type_params(db, trait_id); let substs = Substs::type_params(db, trait_id);
let trait_ref = TraitRef { trait_: trait_id, substs }; let trait_ref = TraitRef { trait_: trait_id, substs };
let pred = GenericPredicate::Implemented(trait_ref); let pred = GenericPredicate::Implemented(trait_ref);
let program_clause: chalk_ir::ProgramClause<Interner> =
predicates.push(pred); pred.clone().to_chalk(db).cast(&Interner);
clauses.push(program_clause.into_from_env_clause(&Interner));
} }
} }
Arc::new(TraitEnvironment { predicates }) let env = chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses);
Arc::new(TraitEnvironment { traits_from_clauses: traits_in_scope, env })
} }
} }

View file

@ -528,8 +528,7 @@ fn iterate_trait_method_candidates(
self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
let env_traits = if let Ty::Placeholder(_) = self_ty.value { let env_traits = if let Ty::Placeholder(_) = self_ty.value {
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
env.trait_predicates_for_self_ty(&self_ty.value) env.traits_in_scope_from_clauses(&self_ty.value)
.map(|tr| tr.trait_)
.flat_map(|t| all_super_traits(db.upcast(), t)) .flat_map(|t| all_super_traits(db.upcast(), t))
.collect() .collect()
} else { } else {

View file

@ -38,22 +38,25 @@ fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
/// fn foo<T: Default>(t: T) {} /// fn foo<T: Default>(t: T) {}
/// ``` /// ```
/// we assume that `T: Default`. /// we assume that `T: Default`.
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TraitEnvironment { pub struct TraitEnvironment {
pub predicates: Vec<GenericPredicate>, // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord,
// but for now it's too annoying...
pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>,
pub(crate) env: chalk_ir::Environment<Interner>,
} }
impl TraitEnvironment { impl TraitEnvironment {
/// Returns trait refs with the given self type which are supposed to hold pub(crate) fn traits_in_scope_from_clauses<'a>(
/// in this trait env. E.g. if we are in `foo<T: SomeTrait>()`, this will
/// find that `T: SomeTrait` if we call it for `T`.
pub(crate) fn trait_predicates_for_self_ty<'a>(
&'a self, &'a self,
ty: &'a Ty, ty: &'a Ty,
) -> impl Iterator<Item = &'a TraitRef> + 'a { ) -> impl Iterator<Item = TraitId> + 'a {
self.predicates.iter().filter_map(move |pred| match pred { self.traits_from_clauses.iter().filter_map(move |(self_ty, trait_id)| {
GenericPredicate::Implemented(tr) if tr.self_ty() == ty => Some(tr), if self_ty == ty {
_ => None, Some(*trait_id)
} else {
None
}
}) })
} }
} }

View file

@ -33,13 +33,13 @@ pub(super) mod tls;
mod interner; mod interner;
mod mapping; mod mapping;
pub(super) trait ToChalk { pub(crate) trait ToChalk {
type Chalk; type Chalk;
fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk;
fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self;
} }
pub(super) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T
where where
T: ToChalk<Chalk = ChalkT>, T: ToChalk<Chalk = ChalkT>,
{ {

View file

@ -17,7 +17,7 @@ use crate::{
primitive::UintTy, primitive::UintTy,
traits::{Canonical, Obligation}, traits::{Canonical, Obligation},
AliasTy, CallableDefId, FnPointer, FnSig, GenericPredicate, InEnvironment, OpaqueTy, AliasTy, CallableDefId, FnPointer, FnSig, GenericPredicate, InEnvironment, OpaqueTy,
OpaqueTyId, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty, OpaqueTyId, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitRef, Ty,
}; };
use super::interner::*; use super::interner::*;
@ -536,31 +536,6 @@ where
} }
} }
impl ToChalk for Arc<TraitEnvironment> {
type Chalk = chalk_ir::Environment<Interner>;
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Environment<Interner> {
let mut clauses = Vec::new();
for pred in &self.predicates {
if pred.is_error() {
// for env, we just ignore errors
continue;
}
let program_clause: chalk_ir::ProgramClause<Interner> =
pred.clone().to_chalk(db).cast(&Interner);
clauses.push(program_clause.into_from_env_clause(&Interner));
}
chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses)
}
fn from_chalk(
_db: &dyn HirDatabase,
_env: chalk_ir::Environment<Interner>,
) -> Arc<TraitEnvironment> {
unimplemented!()
}
}
impl<T: ToChalk> ToChalk for InEnvironment<T> impl<T: ToChalk> ToChalk for InEnvironment<T>
where where
T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
@ -569,19 +544,16 @@ where
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
chalk_ir::InEnvironment { chalk_ir::InEnvironment {
environment: self.environment.to_chalk(db), environment: self.environment.env.clone(),
goal: self.value.to_chalk(db), goal: self.value.to_chalk(db),
} }
} }
fn from_chalk( fn from_chalk(
db: &dyn HirDatabase, _db: &dyn HirDatabase,
in_env: chalk_ir::InEnvironment<T::Chalk>, _in_env: chalk_ir::InEnvironment<T::Chalk>,
) -> InEnvironment<T> { ) -> InEnvironment<T> {
InEnvironment { unimplemented!()
environment: from_chalk(db, in_env.environment),
value: from_chalk(db, in_env.goal),
}
} }
} }