mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +00:00
Add Lifetimes to the HIR
This commit is contained in:
parent
41321d9678
commit
11f8664182
16 changed files with 249 additions and 96 deletions
|
@ -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, "{}", ¶m_data.name)
|
||||
}
|
||||
Lifetime::Static => write!(f, "'static"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HirDisplay for Obligation {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
match self {
|
||||
|
|
|
@ -848,6 +848,7 @@ impl<'a> InferenceContext<'a> {
|
|||
let ty = self.make_ty(type_ref);
|
||||
substs.push(ty);
|
||||
}
|
||||
GenericArg::Lifetime(_) => {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue