mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Add and start using TraitRef and ProjectionTy builders
This commit is contained in:
parent
2ead65190e
commit
cd227f581e
6 changed files with 48 additions and 39 deletions
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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 = ">";
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue