Add and start using TraitRef and ProjectionTy builders

This commit is contained in:
Florian Diebold 2021-04-03 21:50:52 +02:00
parent 2ead65190e
commit cd227f581e
6 changed files with 48 additions and 39 deletions

View file

@ -55,11 +55,10 @@ use hir_ty::{
autoderef, could_unify, autoderef, could_unify,
method_resolution::{self, TyFingerprint}, method_resolution::{self, TyFingerprint},
primitive::UintTy, primitive::UintTy,
to_assoc_type_id,
traits::{FnTrait, Solution, SolutionVariables}, traits::{FnTrait, Solution, SolutionVariables},
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Substitution,
Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, TyVariableKind, WhereClause, TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, TyVariableKind, WhereClause,
}; };
use itertools::Itertools; use itertools::Itertools;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
@ -1785,13 +1784,10 @@ impl Type {
} }
pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
let trait_ref = hir_ty::TraitRef { let trait_ref = TyBuilder::trait_ref(db, trait_.id)
trait_id: hir_ty::to_chalk_trait_id(trait_.id), .push(self.ty.clone())
substitution: Substitution::build_for_def(db, trait_.id) .fill(args.iter().map(|t| t.ty.clone()))
.push(self.ty.clone()) .build();
.fill(args.iter().map(|t| t.ty.clone()))
.build(),
};
let goal = Canonical { let goal = Canonical {
value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)),
@ -1804,11 +1800,10 @@ impl Type {
pub fn normalize_trait_assoc_type( pub fn normalize_trait_assoc_type(
&self, &self,
db: &dyn HirDatabase, db: &dyn HirDatabase,
trait_: Trait,
args: &[Type], args: &[Type],
alias: TypeAlias, alias: TypeAlias,
) -> Option<Type> { ) -> Option<Type> {
let subst = Substitution::build_for_def(db, trait_.id) let projection = TyBuilder::assoc_type_projection(db, alias.id)
.push(self.ty.clone()) .push(self.ty.clone())
.fill(args.iter().map(|t| t.ty.clone())) .fill(args.iter().map(|t| t.ty.clone()))
.build(); .build();
@ -1816,10 +1811,7 @@ impl Type {
InEnvironment::new( InEnvironment::new(
self.env.env.clone(), self.env.env.clone(),
AliasEq { AliasEq {
alias: AliasTy::Projection(ProjectionTy { alias: AliasTy::Projection(projection),
associated_ty_id: to_assoc_type_id(alias.id),
substitution: subst,
}),
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
.intern(&Interner), .intern(&Interner),
} }

View file

@ -42,7 +42,7 @@ use super::{
}; };
use crate::{ use crate::{
db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind,
}; };
// This lint has a false positive here. See the link below for details. // This lint has a false positive here. See the link below for details.
@ -409,16 +409,14 @@ impl<'a> InferenceContext<'a> {
_ => panic!("resolve_associated_type called with non-associated type"), _ => panic!("resolve_associated_type called with non-associated type"),
}; };
let ty = self.table.new_type_var(); let ty = self.table.new_type_var();
let substs = Substitution::build_for_def(self.db, res_assoc_ty) let trait_ref = TyBuilder::trait_ref(self.db, trait_)
.push(inner_ty) .push(inner_ty)
.fill(params.iter().cloned()) .fill(params.iter().cloned())
.build(); .build();
let trait_ref =
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() };
let alias_eq = AliasEq { let alias_eq = AliasEq {
alias: AliasTy::Projection(ProjectionTy { alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(res_assoc_ty), associated_ty_id: to_assoc_type_id(res_assoc_ty),
substitution: substs, substitution: trait_ref.substitution.clone(),
}), }),
ty: ty.clone(), ty: ty.clone(),
}; };

View file

@ -10,9 +10,7 @@ use hir_def::{
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use crate::{ use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId};
method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId,
};
use super::{ExprOrPatId, InferenceContext, TraitRef}; use super::{ExprOrPatId, InferenceContext, TraitRef};
@ -254,18 +252,12 @@ impl<'a> InferenceContext<'a> {
} }
AssocContainerId::TraitId(trait_) => { AssocContainerId::TraitId(trait_) => {
// we're picking this method // we're picking this method
let trait_substs = Substitution::build_for_def(self.db, trait_) let trait_ref = TyBuilder::trait_ref(self.db, trait_)
.push(ty.clone()) .push(ty.clone())
.fill(std::iter::repeat_with(|| self.table.new_type_var())) .fill(std::iter::repeat_with(|| self.table.new_type_var()))
.build(); .build();
self.push_obligation( self.push_obligation(trait_ref.clone().cast(&Interner));
TraitRef { Some(trait_ref.substitution)
trait_id: to_chalk_trait_id(trait_),
substitution: trait_substs.clone(),
}
.cast(&Interner),
);
Some(trait_substs)
} }
AssocContainerId::ModuleId(_) => None, AssocContainerId::ModuleId(_) => None,
}; };

View file

@ -927,6 +927,35 @@ impl TyBuilder<hir_def::AdtId> {
} }
} }
impl TyBuilder<TraitId> {
pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> {
let generics = generics(db.upcast(), trait_id.into());
let param_count = generics.len();
TyBuilder::new(trait_id, param_count)
}
pub fn build(self) -> TraitRef {
let (trait_id, substitution) = self.build_internal();
TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
}
}
impl TyBuilder<TypeAliasId> {
pub fn assoc_type_projection(
db: &dyn HirDatabase,
type_alias: TypeAliasId,
) -> TyBuilder<TypeAliasId> {
let generics = generics(db.upcast(), type_alias.into());
let param_count = generics.len();
TyBuilder::new(type_alias, param_count)
}
pub fn build(self) -> ProjectionTy {
let (type_alias, substitution) = self.build_internal();
ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
}
}
impl Ty { impl Ty {
pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
match self.kind(&Interner) { match self.kind(&Interner) {

View file

@ -19,10 +19,9 @@ use crate::{
db::HirDatabase, db::HirDatabase,
from_foreign_def_id, from_foreign_def_id,
primitive::{self, FloatTy, IntTy, UintTy}, primitive::{self, FloatTy, IntTy, UintTy},
to_chalk_trait_id,
utils::all_super_traits, utils::all_super_traits,
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId,
InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, Ty, TyBuilder, TyKind,
TypeWalk, TypeWalk,
}; };
@ -813,7 +812,7 @@ fn generic_implements_goal(
self_ty: Canonical<Ty>, self_ty: Canonical<Ty>,
) -> Canonical<InEnvironment<super::DomainGoal>> { ) -> Canonical<InEnvironment<super::DomainGoal>> {
let mut kinds = self_ty.binders.interned().to_vec(); let mut kinds = self_ty.binders.interned().to_vec();
let substs = super::Substitution::build_for_def(db, trait_) let trait_ref = TyBuilder::trait_ref(db, trait_)
.push(self_ty.value) .push(self_ty.value)
.fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
.build(); .build();
@ -822,9 +821,8 @@ fn generic_implements_goal(
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
UniverseIndex::ROOT, UniverseIndex::ROOT,
)) ))
.take(substs.len(&Interner) - 1), .take(trait_ref.substitution.len(&Interner) - 1),
); );
let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
let obligation = trait_ref.cast(&Interner); let obligation = trait_ref.cast(&Interner);
Canonical { Canonical {
binders: CanonicalVarKinds::from_iter(&Interner, kinds), binders: CanonicalVarKinds::from_iter(&Interner, kinds),

View file

@ -234,7 +234,7 @@ fn hint_iterator(
hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias), hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias),
_ => None, _ => None,
})?; })?;
if let Some(ty) = ty.normalize_trait_assoc_type(db, iter_trait, &[], assoc_type_item) { if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) {
const LABEL_START: &str = "impl Iterator<Item = "; const LABEL_START: &str = "impl Iterator<Item = ";
const LABEL_END: &str = ">"; const LABEL_END: &str = ">";