Add Lifetimes to the HIR

This commit is contained in:
Lukas Wirth 2020-12-11 13:49:32 +01:00
parent 41321d9678
commit 11f8664182
16 changed files with 249 additions and 96 deletions

View file

@ -4,7 +4,7 @@ use std::fmt;
use crate::{
db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate,
Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
Lifetime, Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
};
use hir_def::{
find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId,
@ -710,6 +710,19 @@ impl HirDisplay for GenericPredicate {
}
}
impl HirDisplay for Lifetime {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
match self {
Lifetime::Parameter(id) => {
let generics = generics(f.db.upcast(), id.parent);
let param_data = &generics.params.lifetimes[id.local_id];
write!(f, "{}", &param_data.name)
}
Lifetime::Static => write!(f, "'static"),
}
}
}
impl HirDisplay for Obligation {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
match self {

View file

@ -848,6 +848,7 @@ impl<'a> InferenceContext<'a> {
let ty = self.make_ty(type_ref);
substs.push(ty);
}
GenericArg::Lifetime(_) => {}
}
}
};

View file

@ -29,8 +29,8 @@ use base_db::{salsa, CrateId};
use hir_def::{
expr::ExprId,
type_ref::{Mutability, Rawness},
AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId,
TypeParamId,
AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, LifetimeParamId, Lookup,
TraitId, TypeAliasId, TypeParamId,
};
use itertools::Itertools;
@ -52,6 +52,12 @@ pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironmen
pub use chalk_ir::{BoundVar, DebruijnIndex};
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum Lifetime {
Parameter(LifetimeParamId),
Static,
}
/// A type constructor or type name: this might be something like the primitive
/// type `bool`, a struct like `Vec`, or things like function pointers or
/// tuples.

View file

@ -12,7 +12,7 @@ use base_db::CrateId;
use hir_def::{
adt::StructKind,
builtin_type::BuiltinType,
generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget},
generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
path::{GenericArg, Path, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs},
type_ref::{TypeBound, TypeRef},
@ -171,7 +171,7 @@ impl Ty {
let inner_ty = Ty::from_hir(ctx, inner);
Ty::apply_one(TypeCtor::Slice, inner_ty)
}
TypeRef::Reference(inner, mutability) => {
TypeRef::Reference(inner, _, mutability) => {
let inner_ty = Ty::from_hir(ctx, inner);
Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
}
@ -555,7 +555,7 @@ fn substs_from_path_segment(
substs.extend(iter::repeat(Ty::Unknown).take(parent_params));
let mut had_explicit_args = false;
let mut had_explicit_type_args = false;
if let Some(generic_args) = &segment.args_and_bindings {
if !generic_args.has_self_type {
@ -568,10 +568,11 @@ fn substs_from_path_segment(
for arg in generic_args.args.iter().skip(skip).take(expected_num) {
match arg {
GenericArg::Type(type_ref) => {
had_explicit_args = true;
had_explicit_type_args = true;
let ty = Ty::from_hir(ctx, type_ref);
substs.push(ty);
}
GenericArg::Lifetime(_) => {}
}
}
}
@ -579,7 +580,7 @@ fn substs_from_path_segment(
// handle defaults. In expression or pattern path segments without
// explicitly specified type arguments, missing type arguments are inferred
// (i.e. defaults aren't used).
if !infer_args || had_explicit_args {
if !infer_args || had_explicit_type_args {
if let Some(def_generic) = def_generic {
let defaults = ctx.db.generic_defaults(def_generic);
assert_eq!(total_len, defaults.len());
@ -657,7 +658,7 @@ impl TraitRef {
) -> Option<TraitRef> {
match bound {
TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)),
TypeBound::Error => None,
TypeBound::Lifetime(_) | TypeBound::Error => None,
}
}
}
@ -667,22 +668,30 @@ impl GenericPredicate {
ctx: &'a TyLoweringContext<'a>,
where_predicate: &'a WherePredicate,
) -> impl Iterator<Item = GenericPredicate> + 'a {
let self_ty = match &where_predicate.target {
WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref),
WherePredicateTarget::TypeParam(param_id) => {
let generic_def = ctx.resolver.generic_def().expect("generics in scope");
let generics = generics(ctx.db.upcast(), generic_def);
let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
TypeParamLoweringMode::Variable => {
let idx = generics.param_idx(param_id).expect("matching generics");
Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
match where_predicate {
WherePredicate::TypeBound { target, bound } => {
let self_ty = match target {
WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref),
WherePredicateTypeTarget::TypeParam(param_id) => {
let generic_def = ctx.resolver.generic_def().expect("generics in scope");
let generics = generics(ctx.db.upcast(), generic_def);
let param_id =
hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
TypeParamLoweringMode::Variable => {
let idx = generics.param_idx(param_id).expect("matching generics");
Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
}
}
}
}
};
GenericPredicate::from_type_bound(ctx, bound, self_ty)
.collect::<Vec<_>>()
.into_iter()
}
};
GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty)
WherePredicate::Lifetime { .. } => vec![].into_iter(),
}
}
pub(crate) fn from_type_bound<'a>(
@ -707,7 +716,7 @@ fn assoc_type_bindings_from_type_bound<'a>(
) -> impl Iterator<Item = GenericPredicate> + 'a {
let last_segment = match bound {
TypeBound::Path(path) => path.segments().last(),
TypeBound::Error => None,
TypeBound::Error | TypeBound::Lifetime(_) => None,
};
last_segment
.into_iter()
@ -872,11 +881,16 @@ pub(crate) fn generic_predicates_for_param_query(
resolver
.where_predicates_in_scope()
// we have to filter out all other predicates *first*, before attempting to lower them
.filter(|pred| match &pred.target {
WherePredicateTarget::TypeRef(type_ref) => {
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
}
WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.local_id,
.filter(|pred| match pred {
WherePredicate::TypeBound {
target: WherePredicateTypeTarget::TypeRef(type_ref),
..
} => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id),
WherePredicate::TypeBound {
target: WherePredicateTypeTarget::TypeParam(local_id),
..
} => *local_id == param_id.local_id,
WherePredicate::Lifetime { .. } => false,
})
.flat_map(|pred| {
GenericPredicate::from_where_predicate(&ctx, pred)

View file

@ -2,11 +2,10 @@
//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
use std::sync::Arc;
use hir_def::generics::WherePredicateTarget;
use hir_def::{
adt::VariantData,
db::DefDatabase,
generics::{GenericParams, TypeParamData, TypeParamProvenance},
generics::{GenericParams, TypeParamData, TypeParamProvenance, WherePredicateTypeTarget},
path::Path,
resolver::{HasResolver, TypeNs},
type_ref::TypeRef,
@ -27,14 +26,19 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
generic_params
.where_predicates
.iter()
.filter_map(|pred| match &pred.target {
WherePredicateTarget::TypeRef(TypeRef::Path(p)) if p == &Path::from(name![Self]) => {
pred.bound.as_path()
}
WherePredicateTarget::TypeParam(local_id) if Some(*local_id) == trait_self => {
pred.bound.as_path()
}
_ => None,
.filter_map(|pred| match pred {
hir_def::generics::WherePredicate::TypeBound { target, bound } => match target {
WherePredicateTypeTarget::TypeRef(TypeRef::Path(p))
if p == &Path::from(name![Self]) =>
{
bound.as_path()
}
WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => {
bound.as_path()
}
_ => None,
},
hir_def::generics::WherePredicate::Lifetime { .. } => None,
})
.filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
Some(TypeNs::TraitId(t)) => Some(t),