Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/expr_store/lower/generics.rs')
| -rw-r--r-- | crates/hir-def/src/expr_store/lower/generics.rs | 107 |
1 files changed, 71 insertions, 36 deletions
diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs index 7ef9c80de1..2119f19c06 100644 --- a/crates/hir-def/src/expr_store/lower/generics.rs +++ b/crates/hir-def/src/expr_store/lower/generics.rs @@ -12,10 +12,13 @@ use thin_vec::ThinVec; use crate::{ GenericDefId, TypeOrConstParamId, TypeParamId, - expr_store::{TypePtr, lower::ExprCollector}, + expr_store::{ + TypePtr, + lower::{ExprCollector, LifetimeBoundScope, NamedLifetimeStore}, + }, hir::generics::{ - ConstParamData, GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamData, - TypeParamProvenance, WherePredicate, + ConstParamData, GenericParams, LifetimeBoundType, LifetimeParamData, TypeOrConstParamData, + TypeParamData, TypeParamProvenance, WherePredicate, }, type_ref::{LifetimeRef, LifetimeRefId, TypeBound, TypeRef, TypeRefId}, }; @@ -62,7 +65,7 @@ impl GenericParamsCollector { self.lower_param_list(ec, params) } if let Some(where_clause) = where_clause { - self.lower_where_predicates(ec, where_clause); + self.lower_where_predicates(ec, where_clause) } } @@ -118,7 +121,9 @@ impl GenericParamsCollector { local_id: idx, })); let type_ref = ec.alloc_type_ref_desugared(type_ref); - self.lower_bounds(ec, type_param.type_bound_list(), Either::Left(type_ref)); + ec.with_lifetime_bound_scope(LifetimeBoundScope::WhereClause, |ec| { + self.lower_bounds(ec, type_param.type_bound_list(), Either::Left(type_ref)) + }); } ast::GenericParam::ConstParam(const_param) => { let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); @@ -133,13 +138,18 @@ impl GenericParamsCollector { ast::GenericParam::LifetimeParam(lifetime_param) => { let lifetime = ec.lower_lifetime_ref_opt(lifetime_param.lifetime()); if let LifetimeRef::Named(name) = &ec.store.lifetimes[lifetime] { - let param = LifetimeParamData { name: name.clone() }; + let param = LifetimeParamData { + name: name.clone(), + bound_type: LifetimeBoundType::EarlyBound, + }; let _idx = self.lifetimes.alloc(param); - self.lower_bounds( - ec, - lifetime_param.type_bound_list(), - Either::Right(lifetime), - ); + ec.with_lifetime_bound_scope(LifetimeBoundScope::WhereClause, |ec| { + self.lower_bounds( + ec, + lifetime_param.type_bound_list(), + Either::Right(lifetime), + ) + }); } } } @@ -151,33 +161,35 @@ impl GenericParamsCollector { ec: &mut ExprCollector<'_>, where_clause: ast::WhereClause, ) { - for pred in where_clause.predicates() { - let target = if let Some(type_ref) = pred.ty() { - Either::Left( - ec.lower_type_ref(type_ref, &mut ExprCollector::impl_trait_error_allocator), - ) - } else if let Some(lifetime) = pred.lifetime() { - Either::Right(ec.lower_lifetime_ref(lifetime)) - } else { - continue; - }; + ec.with_lifetime_bound_scope(LifetimeBoundScope::WhereClause, |ec| { + for pred in where_clause.predicates() { + let target = if let Some(type_ref) = pred.ty() { + Either::Left( + ec.lower_type_ref(type_ref, &mut ExprCollector::impl_trait_error_allocator), + ) + } else if let Some(lifetime) = pred.lifetime() { + Either::Right(ec.lower_lifetime_ref(lifetime)) + } else { + continue; + }; - let lifetimes: Option<Box<_>> = - pred.for_binder().and_then(|it| it.generic_param_list()).map(|param_list| { - // Higher-Ranked Trait Bounds - param_list - .lifetime_params() - .map(|lifetime_param| { - lifetime_param - .lifetime() - .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text())) - }) - .collect() - }); - for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { - self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target); + let lifetimes: Option<Box<_>> = + pred.for_binder().and_then(|it| it.generic_param_list()).map(|param_list| { + // Higher-Ranked Trait Bounds + param_list + .lifetime_params() + .map(|lifetime_param| { + lifetime_param + .lifetime() + .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text())) + }) + .collect() + }); + for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { + self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target); + } } - } + }); } fn lower_bounds( @@ -221,6 +233,9 @@ impl GenericParamsCollector { } (Either::Right(_), TypeBound::ForLifetime(..) | TypeBound::Path(..)) => return, }; + if let WherePredicate::Lifetime { target, .. } = predicate { + ec.push_named_target_lifetime(target); + } self.where_predicates.push(predicate); } @@ -269,4 +284,24 @@ impl GenericParamsCollector { self.lower_bounds(ec, Some(bounds), Either::Left(self_)); } } + + pub(crate) fn update_to_late_bound_lifetimes( + &mut self, + named_lifetime_store: &NamedLifetimeStore, + ) { + for (_param_id, lifetime) in self.lifetimes.iter_mut() { + let lifetime_name = &lifetime.name; + if named_lifetime_store.lifetimes_in_where_clause.contains(lifetime_name) { + continue; + } + + if !named_lifetime_store.lifetimes_constrained_by_input.contains(lifetime_name) + && named_lifetime_store.lifetimes_in_output.contains(lifetime_name) + { + continue; + } + + lifetime.bound_type = LifetimeBoundType::LateBound + } + } } |