From 11f86641829273e2b2b7023c2028bb475fce58ee Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 11 Dec 2020 13:49:32 +0100 Subject: Add Lifetimes to the HIR --- crates/hir_ty/src/display.rs | 15 +++++++++- crates/hir_ty/src/infer/expr.rs | 1 + crates/hir_ty/src/lib.rs | 10 +++++-- crates/hir_ty/src/lower.rs | 66 +++++++++++++++++++++++++---------------- crates/hir_ty/src/utils.rs | 24 ++++++++------- 5 files changed, 77 insertions(+), 39 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index e77481906..0d968cc68 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -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 { diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 605951b10..a89fff773 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -848,6 +848,7 @@ impl<'a> InferenceContext<'a> { let ty = self.make_ty(type_ref); substs.push(ty); } + GenericArg::Lifetime(_) => {} } } }; diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 5a8c97198..357bd92f9 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -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. diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 708e2af0f..92f779360 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -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 { 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 + '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::>() + .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 + '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) diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index e3e244268..af880c065 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs @@ -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 { 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), -- cgit v1.2.3