diff options
author | Lukas Wirth <[email protected]> | 2020-12-11 12:49:32 +0000 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2020-12-11 23:56:52 +0000 |
commit | 11f86641829273e2b2b7023c2028bb475fce58ee (patch) | |
tree | 8633b96c3f812412ea6c19acb1b6a770292d4697 | |
parent | 41321d96789ed918eebda02ada76758765d19d16 (diff) |
Add Lifetimes to the HIR
-rw-r--r-- | crates/assists/src/ast_transform.rs | 2 | ||||
-rw-r--r-- | crates/hir/src/code_model.rs | 47 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 9 | ||||
-rw-r--r-- | crates/hir_def/src/generics.rs | 69 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 20 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 7 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/type_ref.rs | 50 | ||||
-rw-r--r-- | crates/hir_expand/src/name.rs | 7 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 15 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 1 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 66 | ||||
-rw-r--r-- | crates/hir_ty/src/utils.rs | 24 |
16 files changed, 249 insertions, 96 deletions
diff --git a/crates/assists/src/ast_transform.rs b/crates/assists/src/ast_transform.rs index 66e4634b1..da94e9987 100644 --- a/crates/assists/src/ast_transform.rs +++ b/crates/assists/src/ast_transform.rs | |||
@@ -89,7 +89,7 @@ impl<'a> SubstituteTypeParams<'a> { | |||
89 | let substs = get_syntactic_substs(impl_def).unwrap_or_default(); | 89 | let substs = get_syntactic_substs(impl_def).unwrap_or_default(); |
90 | let generic_def: hir::GenericDef = trait_.into(); | 90 | let generic_def: hir::GenericDef = trait_.into(); |
91 | let substs_by_param: FxHashMap<_, _> = generic_def | 91 | let substs_by_param: FxHashMap<_, _> = generic_def |
92 | .params(source_scope.db) | 92 | .type_params(source_scope.db) |
93 | .into_iter() | 93 | .into_iter() |
94 | // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky | 94 | // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky |
95 | .skip(1) | 95 | .skip(1) |
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 9a1e9ba49..fcc42c6bb 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -19,8 +19,9 @@ use hir_def::{ | |||
19 | src::HasSource as _, | 19 | src::HasSource as _, |
20 | type_ref::{Mutability, TypeRef}, | 20 | type_ref::{Mutability, TypeRef}, |
21 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, DefWithBodyId, EnumId, | 21 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, DefWithBodyId, EnumId, |
22 | FunctionId, GenericDefId, HasModule, ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, | 22 | FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, |
23 | Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, | 23 | LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, |
24 | UnionId, | ||
24 | }; | 25 | }; |
25 | use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility}; | 26 | use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility}; |
26 | use hir_expand::{ | 27 | use hir_expand::{ |
@@ -831,7 +832,7 @@ impl SelfParam { | |||
831 | .params | 832 | .params |
832 | .first() | 833 | .first() |
833 | .map(|param| match *param { | 834 | .map(|param| match *param { |
834 | TypeRef::Reference(_, mutability) => mutability.into(), | 835 | TypeRef::Reference(.., mutability) => mutability.into(), |
835 | _ => Access::Owned, | 836 | _ => Access::Owned, |
836 | }) | 837 | }) |
837 | .unwrap_or(Access::Owned) | 838 | .unwrap_or(Access::Owned) |
@@ -1098,8 +1099,25 @@ impl_from!( | |||
1098 | ); | 1099 | ); |
1099 | 1100 | ||
1100 | impl GenericDef { | 1101 | impl GenericDef { |
1101 | pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeParam> { | 1102 | pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> { |
1102 | let generics: Arc<hir_def::generics::GenericParams> = db.generic_params(self.into()); | 1103 | let generics = db.generic_params(self.into()); |
1104 | let ty_params = generics | ||
1105 | .types | ||
1106 | .iter() | ||
1107 | .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } }) | ||
1108 | .map(GenericParam::TypeParam); | ||
1109 | let lt_params = generics | ||
1110 | .lifetimes | ||
1111 | .iter() | ||
1112 | .map(|(local_id, _)| LifetimeParam { | ||
1113 | id: LifetimeParamId { parent: self.into(), local_id }, | ||
1114 | }) | ||
1115 | .map(GenericParam::LifetimeParam); | ||
1116 | ty_params.chain(lt_params).collect() | ||
1117 | } | ||
1118 | |||
1119 | pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> { | ||
1120 | let generics = db.generic_params(self.into()); | ||
1103 | generics | 1121 | generics |
1104 | .types | 1122 | .types |
1105 | .iter() | 1123 | .iter() |
@@ -1176,6 +1194,13 @@ impl Local { | |||
1176 | } | 1194 | } |
1177 | 1195 | ||
1178 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 1196 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
1197 | pub enum GenericParam { | ||
1198 | TypeParam(TypeParam), | ||
1199 | LifetimeParam(LifetimeParam), | ||
1200 | } | ||
1201 | impl_from!(TypeParam, LifetimeParam for GenericParam); | ||
1202 | |||
1203 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1179 | pub struct TypeParam { | 1204 | pub struct TypeParam { |
1180 | pub(crate) id: TypeParamId, | 1205 | pub(crate) id: TypeParamId, |
1181 | } | 1206 | } |
@@ -1215,6 +1240,18 @@ impl TypeParam { | |||
1215 | } | 1240 | } |
1216 | } | 1241 | } |
1217 | 1242 | ||
1243 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1244 | pub struct LifetimeParam { | ||
1245 | pub(crate) id: LifetimeParamId, | ||
1246 | } | ||
1247 | |||
1248 | impl LifetimeParam { | ||
1249 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1250 | let params = db.generic_params(self.id.parent); | ||
1251 | params.lifetimes[self.id.local_id].name.clone() | ||
1252 | } | ||
1253 | } | ||
1254 | |||
1218 | // FIXME: rename from `ImplDef` to `Impl` | 1255 | // FIXME: rename from `ImplDef` to `Impl` |
1219 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 1256 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
1220 | pub struct ImplDef { | 1257 | pub struct ImplDef { |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 302a52491..0f399a2c6 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -35,8 +35,8 @@ pub use crate::{ | |||
35 | code_model::{ | 35 | code_model::{ |
36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, | 36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, |
37 | Crate, CrateDependency, DefWithBody, Enum, EnumVariant, Field, FieldSource, Function, | 37 | Crate, CrateDependency, DefWithBody, Enum, EnumVariant, Field, FieldSource, Function, |
38 | GenericDef, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, | 38 | GenericDef, HasVisibility, ImplDef, LifetimeParam, Local, MacroDef, Module, ModuleDef, |
39 | Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, | 39 | ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, |
40 | }, | 40 | }, |
41 | has_source::HasSource, | 41 | has_source::HasSource, |
42 | semantics::{PathResolution, Semantics, SemanticsScope}, | 42 | semantics::{PathResolution, Semantics, SemanticsScope}, |
@@ -56,8 +56,9 @@ pub use hir_def::{ | |||
56 | visibility::Visibility, | 56 | visibility::Visibility, |
57 | }; | 57 | }; |
58 | pub use hir_expand::{ | 58 | pub use hir_expand::{ |
59 | name::known, name::AsName, name::Name, ExpandResult, HirFileId, InFile, MacroCallId, | 59 | name::{known, AsName, Name}, |
60 | MacroCallLoc, /* FIXME */ MacroDefId, MacroFile, Origin, | 60 | ExpandResult, HirFileId, InFile, MacroCallId, MacroCallLoc, /* FIXME */ MacroDefId, |
61 | MacroFile, Origin, | ||
61 | }; | 62 | }; |
62 | pub use hir_ty::display::HirDisplay; | 63 | pub use hir_ty::display::HirDisplay; |
63 | 64 | ||
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 835fe3fbd..5189c7e9f 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | keys, | 21 | keys, |
22 | src::HasChildSource, | 22 | src::HasChildSource, |
23 | src::HasSource, | 23 | src::HasSource, |
24 | type_ref::{TypeBound, TypeRef}, | 24 | type_ref::{LifetimeRef, TypeBound, TypeRef}, |
25 | AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, | 25 | AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -33,6 +33,12 @@ pub struct TypeParamData { | |||
33 | pub provenance: TypeParamProvenance, | 33 | pub provenance: TypeParamProvenance, |
34 | } | 34 | } |
35 | 35 | ||
36 | /// Data about a generic parameter (to a function, struct, impl, ...). | ||
37 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
38 | pub struct LifetimeParamData { | ||
39 | pub name: Name, | ||
40 | } | ||
41 | |||
36 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | 42 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
37 | pub enum TypeParamProvenance { | 43 | pub enum TypeParamProvenance { |
38 | TypeParamList, | 44 | TypeParamList, |
@@ -44,7 +50,7 @@ pub enum TypeParamProvenance { | |||
44 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | 50 | #[derive(Clone, PartialEq, Eq, Debug, Default)] |
45 | pub struct GenericParams { | 51 | pub struct GenericParams { |
46 | pub types: Arena<TypeParamData>, | 52 | pub types: Arena<TypeParamData>, |
47 | // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>, | 53 | pub lifetimes: Arena<LifetimeParamData>, |
48 | pub where_predicates: Vec<WherePredicate>, | 54 | pub where_predicates: Vec<WherePredicate>, |
49 | } | 55 | } |
50 | 56 | ||
@@ -53,16 +59,17 @@ pub struct GenericParams { | |||
53 | /// It might still result in multiple actual predicates though, because of | 59 | /// It might still result in multiple actual predicates though, because of |
54 | /// associated type bindings like `Iterator<Item = u32>`. | 60 | /// associated type bindings like `Iterator<Item = u32>`. |
55 | #[derive(Clone, PartialEq, Eq, Debug)] | 61 | #[derive(Clone, PartialEq, Eq, Debug)] |
56 | pub struct WherePredicate { | 62 | pub enum WherePredicate { |
57 | pub target: WherePredicateTarget, | 63 | TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, |
58 | pub bound: TypeBound, | 64 | Lifetime { target: LifetimeRef, bound: LifetimeRef }, |
59 | } | 65 | } |
60 | 66 | ||
61 | #[derive(Clone, PartialEq, Eq, Debug)] | 67 | #[derive(Clone, PartialEq, Eq, Debug)] |
62 | pub enum WherePredicateTarget { | 68 | pub enum WherePredicateTypeTarget { |
63 | TypeRef(TypeRef), | 69 | TypeRef(TypeRef), |
64 | /// For desugared where predicates that can directly refer to a type param. | 70 | /// For desugared where predicates that can directly refer to a type param. |
65 | TypeParam(LocalTypeParamId), | 71 | TypeParam(LocalTypeParamId), |
72 | // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef) | ||
66 | } | 73 | } |
67 | 74 | ||
68 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; | 75 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; |
@@ -123,7 +130,7 @@ impl GenericParams { | |||
123 | } | 130 | } |
124 | 131 | ||
125 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { | 132 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
126 | let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; | 133 | let mut generics = GenericParams::default(); |
127 | let mut sm = ArenaMap::default(); | 134 | let mut sm = ArenaMap::default(); |
128 | 135 | ||
129 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | 136 | // FIXME: add `: Sized` bound for everything except for `Self` in traits |
@@ -171,7 +178,7 @@ impl GenericParams { | |||
171 | // add super traits as bounds on Self | 178 | // add super traits as bounds on Self |
172 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 179 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
173 | let self_param = TypeRef::Path(name![Self].into()); | 180 | let self_param = TypeRef::Path(name![Self].into()); |
174 | generics.fill_bounds(&lower_ctx, &src.value, self_param); | 181 | generics.fill_bounds(&lower_ctx, &src.value, Either::Left(self_param)); |
175 | 182 | ||
176 | generics.fill(&lower_ctx, &mut sm, &src.value); | 183 | generics.fill(&lower_ctx, &mut sm, &src.value); |
177 | src.file_id | 184 | src.file_id |
@@ -218,12 +225,12 @@ impl GenericParams { | |||
218 | &mut self, | 225 | &mut self, |
219 | lower_ctx: &LowerCtx, | 226 | lower_ctx: &LowerCtx, |
220 | node: &dyn ast::TypeBoundsOwner, | 227 | node: &dyn ast::TypeBoundsOwner, |
221 | type_ref: TypeRef, | 228 | target: Either<TypeRef, LifetimeRef>, |
222 | ) { | 229 | ) { |
223 | for bound in | 230 | for bound in |
224 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) | 231 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) |
225 | { | 232 | { |
226 | self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone()); | 233 | self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); |
227 | } | 234 | } |
228 | } | 235 | } |
229 | 236 | ||
@@ -246,19 +253,30 @@ impl GenericParams { | |||
246 | sm.insert(param_id, Either::Right(type_param.clone())); | 253 | sm.insert(param_id, Either::Right(type_param.clone())); |
247 | 254 | ||
248 | let type_ref = TypeRef::Path(name.into()); | 255 | let type_ref = TypeRef::Path(name.into()); |
249 | self.fill_bounds(&lower_ctx, &type_param, type_ref); | 256 | self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); |
257 | } | ||
258 | for lifetime_param in params.lifetime_params() { | ||
259 | let name = lifetime_param | ||
260 | .lifetime_token() | ||
261 | .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok)); | ||
262 | let param = LifetimeParamData { name: name.clone() }; | ||
263 | let _param_id = self.lifetimes.alloc(param); | ||
264 | let lifetime_ref = LifetimeRef::new_name(name); | ||
265 | self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); | ||
250 | } | 266 | } |
251 | } | 267 | } |
252 | 268 | ||
253 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { | 269 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { |
254 | for pred in where_clause.predicates() { | 270 | for pred in where_clause.predicates() { |
255 | let type_ref = match pred.ty() { | 271 | let target = if let Some(type_ref) = pred.ty() { |
256 | Some(type_ref) => type_ref, | 272 | Either::Left(TypeRef::from_ast(lower_ctx, type_ref)) |
257 | None => continue, | 273 | } else if let Some(lifetime_tok) = pred.lifetime_token() { |
274 | Either::Right(LifetimeRef::from_token(lifetime_tok)) | ||
275 | } else { | ||
276 | continue; | ||
258 | }; | 277 | }; |
259 | let type_ref = TypeRef::from_ast(lower_ctx, type_ref); | ||
260 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { | 278 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { |
261 | self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone()); | 279 | self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); |
262 | } | 280 | } |
263 | } | 281 | } |
264 | } | 282 | } |
@@ -267,15 +285,24 @@ impl GenericParams { | |||
267 | &mut self, | 285 | &mut self, |
268 | lower_ctx: &LowerCtx, | 286 | lower_ctx: &LowerCtx, |
269 | bound: ast::TypeBound, | 287 | bound: ast::TypeBound, |
270 | type_ref: TypeRef, | 288 | target: Either<TypeRef, LifetimeRef>, |
271 | ) { | 289 | ) { |
272 | if bound.question_mark_token().is_some() { | 290 | if bound.question_mark_token().is_some() { |
273 | // FIXME: remove this bound | 291 | // FIXME: remove this bound |
274 | return; | 292 | return; |
275 | } | 293 | } |
276 | let bound = TypeBound::from_ast(lower_ctx, bound); | 294 | let bound = TypeBound::from_ast(lower_ctx, bound); |
277 | self.where_predicates | 295 | let predicate = match (target, bound) { |
278 | .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); | 296 | (Either::Left(type_ref), bound) => WherePredicate::TypeBound { |
297 | target: WherePredicateTypeTarget::TypeRef(type_ref), | ||
298 | bound, | ||
299 | }, | ||
300 | (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { | ||
301 | WherePredicate::Lifetime { target: lifetime, bound } | ||
302 | } | ||
303 | _ => return, | ||
304 | }; | ||
305 | self.where_predicates.push(predicate); | ||
279 | } | 306 | } |
280 | 307 | ||
281 | pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { | 308 | pub(crate) fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) { |
@@ -288,8 +315,8 @@ impl GenericParams { | |||
288 | }; | 315 | }; |
289 | let param_id = self.types.alloc(param); | 316 | let param_id = self.types.alloc(param); |
290 | for bound in bounds { | 317 | for bound in bounds { |
291 | self.where_predicates.push(WherePredicate { | 318 | self.where_predicates.push(WherePredicate::TypeBound { |
292 | target: WherePredicateTarget::TypeParam(param_id), | 319 | target: WherePredicateTypeTarget::TypeParam(param_id), |
293 | bound: bound.clone(), | 320 | bound: bound.clone(), |
294 | }); | 321 | }); |
295 | } | 322 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index c017b352d..c6ada271e 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -255,7 +255,7 @@ impl GenericParamsStorage { | |||
255 | } | 255 | } |
256 | 256 | ||
257 | static EMPTY_GENERICS: GenericParams = | 257 | static EMPTY_GENERICS: GenericParams = |
258 | GenericParams { types: Arena::new(), where_predicates: Vec::new() }; | 258 | GenericParams { types: Arena::new(), lifetimes: Arena::new(), where_predicates: Vec::new() }; |
259 | 259 | ||
260 | #[derive(Default, Debug, Eq, PartialEq)] | 260 | #[derive(Default, Debug, Eq, PartialEq)] |
261 | struct ItemTreeData { | 261 | struct ItemTreeData { |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 63b2826f8..f7ce2e26d 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -13,6 +13,7 @@ use syntax::{ | |||
13 | use crate::{ | 13 | use crate::{ |
14 | attr::Attrs, | 14 | attr::Attrs, |
15 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | 15 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, |
16 | type_ref::LifetimeRef, | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | use super::*; | 19 | use super::*; |
@@ -292,12 +293,16 @@ impl Ctx { | |||
292 | let self_type = TypeRef::Path(name![Self].into()); | 293 | let self_type = TypeRef::Path(name![Self].into()); |
293 | match self_param.kind() { | 294 | match self_param.kind() { |
294 | ast::SelfParamKind::Owned => self_type, | 295 | ast::SelfParamKind::Owned => self_type, |
295 | ast::SelfParamKind::Ref => { | 296 | ast::SelfParamKind::Ref => TypeRef::Reference( |
296 | TypeRef::Reference(Box::new(self_type), Mutability::Shared) | 297 | Box::new(self_type), |
297 | } | 298 | self_param.lifetime_token().map(LifetimeRef::from_token), |
298 | ast::SelfParamKind::MutRef => { | 299 | Mutability::Shared, |
299 | TypeRef::Reference(Box::new(self_type), Mutability::Mut) | 300 | ), |
300 | } | 301 | ast::SelfParamKind::MutRef => TypeRef::Reference( |
302 | Box::new(self_type), | ||
303 | self_param.lifetime_token().map(LifetimeRef::from_token), | ||
304 | Mutability::Mut, | ||
305 | ), | ||
301 | } | 306 | } |
302 | } | 307 | } |
303 | }; | 308 | }; |
@@ -629,8 +634,7 @@ impl Ctx { | |||
629 | // add super traits as bounds on Self | 634 | // add super traits as bounds on Self |
630 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 635 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
631 | let self_param = TypeRef::Path(name![Self].into()); | 636 | let self_param = TypeRef::Path(name![Self].into()); |
632 | generics.fill_bounds(&self.body_ctx, trait_def, self_param); | 637 | generics.fill_bounds(&self.body_ctx, trait_def, Either::Left(self_param)); |
633 | |||
634 | generics.fill(&self.body_ctx, &mut sm, node); | 638 | generics.fill(&self.body_ctx, &mut sm, node); |
635 | } | 639 | } |
636 | GenericsOwner::Impl => { | 640 | GenericsOwner::Impl => { |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 02ed30e4d..a1bbc729f 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -224,6 +224,13 @@ pub struct TypeParamId { | |||
224 | pub type LocalTypeParamId = Idx<generics::TypeParamData>; | 224 | pub type LocalTypeParamId = Idx<generics::TypeParamData>; |
225 | 225 | ||
226 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 226 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
227 | pub struct LifetimeParamId { | ||
228 | pub parent: GenericDefId, | ||
229 | pub local_id: LocalLifetimeParamId, | ||
230 | } | ||
231 | pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>; | ||
232 | |||
233 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
227 | pub enum ContainerId { | 234 | pub enum ContainerId { |
228 | ModuleId(ModuleId), | 235 | ModuleId(ModuleId), |
229 | DefWithBodyId(DefWithBodyId), | 236 | DefWithBodyId(DefWithBodyId), |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 5b8c1e449..00a69a8a6 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -7,7 +7,7 @@ use std::{ | |||
7 | sync::Arc, | 7 | sync::Arc, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | use crate::body::LowerCtx; | 10 | use crate::{body::LowerCtx, type_ref::LifetimeRef}; |
11 | use base_db::CrateId; | 11 | use base_db::CrateId; |
12 | use hir_expand::{ | 12 | use hir_expand::{ |
13 | hygiene::Hygiene, | 13 | hygiene::Hygiene, |
@@ -145,7 +145,7 @@ pub struct AssociatedTypeBinding { | |||
145 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 145 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
146 | pub enum GenericArg { | 146 | pub enum GenericArg { |
147 | Type(TypeRef), | 147 | Type(TypeRef), |
148 | // or lifetime... | 148 | Lifetime(LifetimeRef), |
149 | } | 149 | } |
150 | 150 | ||
151 | impl Path { | 151 | impl Path { |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 07b9723ce..60fa7646b 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -15,7 +15,7 @@ use super::AssociatedTypeBinding; | |||
15 | use crate::{ | 15 | use crate::{ |
16 | body::LowerCtx, | 16 | body::LowerCtx, |
17 | path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, | 17 | path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, |
18 | type_ref::{TypeBound, TypeRef}, | 18 | type_ref::{LifetimeRef, TypeBound, TypeRef}, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | pub(super) use lower_use::lower_use_tree; | 21 | pub(super) use lower_use::lower_use_tree; |
@@ -170,8 +170,14 @@ pub(super) fn lower_generic_args( | |||
170 | bindings.push(AssociatedTypeBinding { name, type_ref, bounds }); | 170 | bindings.push(AssociatedTypeBinding { name, type_ref, bounds }); |
171 | } | 171 | } |
172 | } | 172 | } |
173 | // Lifetimes and constants are ignored for now. | 173 | ast::GenericArg::LifetimeArg(lifetime_arg) => { |
174 | ast::GenericArg::LifetimeArg(_) | ast::GenericArg::ConstArg(_) => (), | 174 | if let Some(lifetime) = lifetime_arg.lifetime_token() { |
175 | let lifetime_ref = LifetimeRef::from_token(lifetime); | ||
176 | args.push(GenericArg::Lifetime(lifetime_ref)) | ||
177 | } | ||
178 | } | ||
179 | // constants are ignored for now. | ||
180 | ast::GenericArg::ConstArg(_) => (), | ||
175 | } | 181 | } |
176 | } | 182 | } |
177 | 183 | ||
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index 1a78c1444..347ceabb9 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | //! HIR for references to types. Paths in these are not yet resolved. They can | 1 | //! HIR for references to types. Paths in these are not yet resolved. They can |
2 | //! be directly created from an ast::TypeRef, without further queries. | 2 | //! be directly created from an ast::TypeRef, without further queries. |
3 | use syntax::ast::{self}; | 3 | use hir_expand::name::Name; |
4 | use syntax::{ast, SyntaxToken}; | ||
4 | 5 | ||
5 | use crate::{body::LowerCtx, path::Path}; | 6 | use crate::{body::LowerCtx, path::Path}; |
6 | 7 | ||
@@ -58,7 +59,7 @@ pub enum TypeRef { | |||
58 | Tuple(Vec<TypeRef>), | 59 | Tuple(Vec<TypeRef>), |
59 | Path(Path), | 60 | Path(Path), |
60 | RawPtr(Box<TypeRef>, Mutability), | 61 | RawPtr(Box<TypeRef>, Mutability), |
61 | Reference(Box<TypeRef>, Mutability), | 62 | Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability), |
62 | Array(Box<TypeRef> /*, Expr*/), | 63 | Array(Box<TypeRef> /*, Expr*/), |
63 | Slice(Box<TypeRef>), | 64 | Slice(Box<TypeRef>), |
64 | /// A fn pointer. Last element of the vector is the return type. | 65 | /// A fn pointer. Last element of the vector is the return type. |
@@ -70,10 +71,29 @@ pub enum TypeRef { | |||
70 | } | 71 | } |
71 | 72 | ||
72 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 73 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
74 | pub struct LifetimeRef { | ||
75 | pub name: Name, | ||
76 | } | ||
77 | |||
78 | impl LifetimeRef { | ||
79 | pub(crate) fn new_name(name: Name) -> Self { | ||
80 | LifetimeRef { name } | ||
81 | } | ||
82 | |||
83 | pub(crate) fn from_token(token: SyntaxToken) -> Self { | ||
84 | LifetimeRef { name: Name::new_lifetime(&token) } | ||
85 | } | ||
86 | |||
87 | pub fn missing() -> LifetimeRef { | ||
88 | LifetimeRef { name: Name::missing() } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | ||
73 | pub enum TypeBound { | 93 | pub enum TypeBound { |
74 | Path(Path), | 94 | Path(Path), |
75 | // also for<> bounds | 95 | // ForLifetime(Vec<LifetimeRef>, Path), FIXME ForLifetime |
76 | // also Lifetimes | 96 | Lifetime(LifetimeRef), |
77 | Error, | 97 | Error, |
78 | } | 98 | } |
79 | 99 | ||
@@ -107,8 +127,9 @@ impl TypeRef { | |||
107 | } | 127 | } |
108 | ast::Type::RefType(inner) => { | 128 | ast::Type::RefType(inner) => { |
109 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); | 129 | let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); |
130 | let lifetime = inner.lifetime_token().map(|t| LifetimeRef::from_token(t)); | ||
110 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); | 131 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
111 | TypeRef::Reference(Box::new(inner_ty), mutability) | 132 | TypeRef::Reference(Box::new(inner_ty), lifetime, mutability) |
112 | } | 133 | } |
113 | ast::Type::InferType(_inner) => TypeRef::Placeholder, | 134 | ast::Type::InferType(_inner) => TypeRef::Placeholder, |
114 | ast::Type::FnPtrType(inner) => { | 135 | ast::Type::FnPtrType(inner) => { |
@@ -163,14 +184,14 @@ impl TypeRef { | |||
163 | types.iter().for_each(|t| go(t, f)) | 184 | types.iter().for_each(|t| go(t, f)) |
164 | } | 185 | } |
165 | TypeRef::RawPtr(type_ref, _) | 186 | TypeRef::RawPtr(type_ref, _) |
166 | | TypeRef::Reference(type_ref, _) | 187 | | TypeRef::Reference(type_ref, ..) |
167 | | TypeRef::Array(type_ref) | 188 | | TypeRef::Array(type_ref) |
168 | | TypeRef::Slice(type_ref) => go(&type_ref, f), | 189 | | TypeRef::Slice(type_ref) => go(&type_ref, f), |
169 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { | 190 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { |
170 | for bound in bounds { | 191 | for bound in bounds { |
171 | match bound { | 192 | match bound { |
172 | TypeBound::Path(path) => go_path(path, f), | 193 | TypeBound::Path(path) => go_path(path, f), |
173 | TypeBound::Error => (), | 194 | TypeBound::Lifetime(_) | TypeBound::Error => (), |
174 | } | 195 | } |
175 | } | 196 | } |
176 | } | 197 | } |
@@ -186,8 +207,12 @@ impl TypeRef { | |||
186 | for segment in path.segments().iter() { | 207 | for segment in path.segments().iter() { |
187 | if let Some(args_and_bindings) = segment.args_and_bindings { | 208 | if let Some(args_and_bindings) = segment.args_and_bindings { |
188 | for arg in &args_and_bindings.args { | 209 | for arg in &args_and_bindings.args { |
189 | let crate::path::GenericArg::Type(type_ref) = arg; | 210 | match arg { |
190 | go(type_ref, f); | 211 | crate::path::GenericArg::Type(type_ref) => { |
212 | go(type_ref, f); | ||
213 | } | ||
214 | crate::path::GenericArg::Lifetime(_) => {} | ||
215 | } | ||
191 | } | 216 | } |
192 | for binding in &args_and_bindings.bindings { | 217 | for binding in &args_and_bindings.bindings { |
193 | if let Some(type_ref) = &binding.type_ref { | 218 | if let Some(type_ref) = &binding.type_ref { |
@@ -196,7 +221,7 @@ impl TypeRef { | |||
196 | for bound in &binding.bounds { | 221 | for bound in &binding.bounds { |
197 | match bound { | 222 | match bound { |
198 | TypeBound::Path(path) => go_path(path, f), | 223 | TypeBound::Path(path) => go_path(path, f), |
199 | TypeBound::Error => (), | 224 | TypeBound::Lifetime(_) | TypeBound::Error => (), |
200 | } | 225 | } |
201 | } | 226 | } |
202 | } | 227 | } |
@@ -232,7 +257,10 @@ impl TypeBound { | |||
232 | }; | 257 | }; |
233 | TypeBound::Path(path) | 258 | TypeBound::Path(path) |
234 | } | 259 | } |
235 | ast::TypeBoundKind::ForType(_) | ast::TypeBoundKind::Lifetime(_) => TypeBound::Error, | 260 | ast::TypeBoundKind::ForType(_) => TypeBound::Error, // FIXME ForType |
261 | ast::TypeBoundKind::Lifetime(lifetime) => { | ||
262 | TypeBound::Lifetime(LifetimeRef::from_token(lifetime)) | ||
263 | } | ||
236 | } | 264 | } |
237 | } | 265 | } |
238 | 266 | ||
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index b26ffa1ef..583ed6142 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -38,7 +38,7 @@ impl Name { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn new_lifetime(lt: &syntax::SyntaxToken) -> Name { | 40 | pub fn new_lifetime(lt: &syntax::SyntaxToken) -> Name { |
41 | assert!(lt.kind() == syntax::SyntaxKind::LIFETIME); | 41 | assert_eq!(lt.kind(), syntax::SyntaxKind::LIFETIME); |
42 | Name(Repr::Text(lt.text().clone())) | 42 | Name(Repr::Text(lt.text().clone())) |
43 | } | 43 | } |
44 | 44 | ||
@@ -250,6 +250,8 @@ pub mod known { | |||
250 | pub const SELF_PARAM: super::Name = super::Name::new_inline("self"); | 250 | pub const SELF_PARAM: super::Name = super::Name::new_inline("self"); |
251 | pub const SELF_TYPE: super::Name = super::Name::new_inline("Self"); | 251 | pub const SELF_TYPE: super::Name = super::Name::new_inline("Self"); |
252 | 252 | ||
253 | pub const STATIC_LIFETIME: super::Name = super::Name::new_inline("'static"); | ||
254 | |||
253 | #[macro_export] | 255 | #[macro_export] |
254 | macro_rules! name { | 256 | macro_rules! name { |
255 | (self) => { | 257 | (self) => { |
@@ -258,6 +260,9 @@ pub mod known { | |||
258 | (Self) => { | 260 | (Self) => { |
259 | $crate::name::known::SELF_TYPE | 261 | $crate::name::known::SELF_TYPE |
260 | }; | 262 | }; |
263 | ('static) => { | ||
264 | $crate::name::known::STATIC_LIFETIME | ||
265 | }; | ||
261 | ($ident:ident) => { | 266 | ($ident:ident) => { |
262 | $crate::name::known::$ident | 267 | $crate::name::known::$ident |
263 | }; | 268 | }; |
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; | |||
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, | 6 | db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, |
7 | Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 7 | Lifetime, Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
8 | }; | 8 | }; |
9 | use hir_def::{ | 9 | use hir_def::{ |
10 | find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId, | 10 | find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId, |
@@ -710,6 +710,19 @@ impl HirDisplay for GenericPredicate { | |||
710 | } | 710 | } |
711 | } | 711 | } |
712 | 712 | ||
713 | impl HirDisplay for Lifetime { | ||
714 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
715 | match self { | ||
716 | Lifetime::Parameter(id) => { | ||
717 | let generics = generics(f.db.upcast(), id.parent); | ||
718 | let param_data = &generics.params.lifetimes[id.local_id]; | ||
719 | write!(f, "{}", ¶m_data.name) | ||
720 | } | ||
721 | Lifetime::Static => write!(f, "'static"), | ||
722 | } | ||
723 | } | ||
724 | } | ||
725 | |||
713 | impl HirDisplay for Obligation { | 726 | impl HirDisplay for Obligation { |
714 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 727 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
715 | match self { | 728 | 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> { | |||
848 | let ty = self.make_ty(type_ref); | 848 | let ty = self.make_ty(type_ref); |
849 | substs.push(ty); | 849 | substs.push(ty); |
850 | } | 850 | } |
851 | GenericArg::Lifetime(_) => {} | ||
851 | } | 852 | } |
852 | } | 853 | } |
853 | }; | 854 | }; |
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}; | |||
29 | use hir_def::{ | 29 | use hir_def::{ |
30 | expr::ExprId, | 30 | expr::ExprId, |
31 | type_ref::{Mutability, Rawness}, | 31 | type_ref::{Mutability, Rawness}, |
32 | AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, | 32 | AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, LifetimeParamId, Lookup, |
33 | TypeParamId, | 33 | TraitId, TypeAliasId, TypeParamId, |
34 | }; | 34 | }; |
35 | use itertools::Itertools; | 35 | use itertools::Itertools; |
36 | 36 | ||
@@ -52,6 +52,12 @@ pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironmen | |||
52 | 52 | ||
53 | pub use chalk_ir::{BoundVar, DebruijnIndex}; | 53 | pub use chalk_ir::{BoundVar, DebruijnIndex}; |
54 | 54 | ||
55 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
56 | pub enum Lifetime { | ||
57 | Parameter(LifetimeParamId), | ||
58 | Static, | ||
59 | } | ||
60 | |||
55 | /// A type constructor or type name: this might be something like the primitive | 61 | /// A type constructor or type name: this might be something like the primitive |
56 | /// type `bool`, a struct like `Vec`, or things like function pointers or | 62 | /// type `bool`, a struct like `Vec`, or things like function pointers or |
57 | /// tuples. | 63 | /// 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; | |||
12 | use hir_def::{ | 12 | use hir_def::{ |
13 | adt::StructKind, | 13 | adt::StructKind, |
14 | builtin_type::BuiltinType, | 14 | builtin_type::BuiltinType, |
15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget}, | 15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, |
16 | path::{GenericArg, Path, PathSegment, PathSegments}, | 16 | path::{GenericArg, Path, PathSegment, PathSegments}, |
17 | resolver::{HasResolver, Resolver, TypeNs}, | 17 | resolver::{HasResolver, Resolver, TypeNs}, |
18 | type_ref::{TypeBound, TypeRef}, | 18 | type_ref::{TypeBound, TypeRef}, |
@@ -171,7 +171,7 @@ impl Ty { | |||
171 | let inner_ty = Ty::from_hir(ctx, inner); | 171 | let inner_ty = Ty::from_hir(ctx, inner); |
172 | Ty::apply_one(TypeCtor::Slice, inner_ty) | 172 | Ty::apply_one(TypeCtor::Slice, inner_ty) |
173 | } | 173 | } |
174 | TypeRef::Reference(inner, mutability) => { | 174 | TypeRef::Reference(inner, _, mutability) => { |
175 | let inner_ty = Ty::from_hir(ctx, inner); | 175 | let inner_ty = Ty::from_hir(ctx, inner); |
176 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | 176 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) |
177 | } | 177 | } |
@@ -555,7 +555,7 @@ fn substs_from_path_segment( | |||
555 | 555 | ||
556 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); | 556 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); |
557 | 557 | ||
558 | let mut had_explicit_args = false; | 558 | let mut had_explicit_type_args = false; |
559 | 559 | ||
560 | if let Some(generic_args) = &segment.args_and_bindings { | 560 | if let Some(generic_args) = &segment.args_and_bindings { |
561 | if !generic_args.has_self_type { | 561 | if !generic_args.has_self_type { |
@@ -568,10 +568,11 @@ fn substs_from_path_segment( | |||
568 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { | 568 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { |
569 | match arg { | 569 | match arg { |
570 | GenericArg::Type(type_ref) => { | 570 | GenericArg::Type(type_ref) => { |
571 | had_explicit_args = true; | 571 | had_explicit_type_args = true; |
572 | let ty = Ty::from_hir(ctx, type_ref); | 572 | let ty = Ty::from_hir(ctx, type_ref); |
573 | substs.push(ty); | 573 | substs.push(ty); |
574 | } | 574 | } |
575 | GenericArg::Lifetime(_) => {} | ||
575 | } | 576 | } |
576 | } | 577 | } |
577 | } | 578 | } |
@@ -579,7 +580,7 @@ fn substs_from_path_segment( | |||
579 | // handle defaults. In expression or pattern path segments without | 580 | // handle defaults. In expression or pattern path segments without |
580 | // explicitly specified type arguments, missing type arguments are inferred | 581 | // explicitly specified type arguments, missing type arguments are inferred |
581 | // (i.e. defaults aren't used). | 582 | // (i.e. defaults aren't used). |
582 | if !infer_args || had_explicit_args { | 583 | if !infer_args || had_explicit_type_args { |
583 | if let Some(def_generic) = def_generic { | 584 | if let Some(def_generic) = def_generic { |
584 | let defaults = ctx.db.generic_defaults(def_generic); | 585 | let defaults = ctx.db.generic_defaults(def_generic); |
585 | assert_eq!(total_len, defaults.len()); | 586 | assert_eq!(total_len, defaults.len()); |
@@ -657,7 +658,7 @@ impl TraitRef { | |||
657 | ) -> Option<TraitRef> { | 658 | ) -> Option<TraitRef> { |
658 | match bound { | 659 | match bound { |
659 | TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)), | 660 | TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)), |
660 | TypeBound::Error => None, | 661 | TypeBound::Lifetime(_) | TypeBound::Error => None, |
661 | } | 662 | } |
662 | } | 663 | } |
663 | } | 664 | } |
@@ -667,22 +668,30 @@ impl GenericPredicate { | |||
667 | ctx: &'a TyLoweringContext<'a>, | 668 | ctx: &'a TyLoweringContext<'a>, |
668 | where_predicate: &'a WherePredicate, | 669 | where_predicate: &'a WherePredicate, |
669 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 670 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
670 | let self_ty = match &where_predicate.target { | 671 | match where_predicate { |
671 | WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), | 672 | WherePredicate::TypeBound { target, bound } => { |
672 | WherePredicateTarget::TypeParam(param_id) => { | 673 | let self_ty = match target { |
673 | let generic_def = ctx.resolver.generic_def().expect("generics in scope"); | 674 | WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), |
674 | let generics = generics(ctx.db.upcast(), generic_def); | 675 | WherePredicateTypeTarget::TypeParam(param_id) => { |
675 | let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; | 676 | let generic_def = ctx.resolver.generic_def().expect("generics in scope"); |
676 | match ctx.type_param_mode { | 677 | let generics = generics(ctx.db.upcast(), generic_def); |
677 | TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), | 678 | let param_id = |
678 | TypeParamLoweringMode::Variable => { | 679 | hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; |
679 | let idx = generics.param_idx(param_id).expect("matching generics"); | 680 | match ctx.type_param_mode { |
680 | Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)) | 681 | TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), |
682 | TypeParamLoweringMode::Variable => { | ||
683 | let idx = generics.param_idx(param_id).expect("matching generics"); | ||
684 | Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)) | ||
685 | } | ||
686 | } | ||
681 | } | 687 | } |
682 | } | 688 | }; |
689 | GenericPredicate::from_type_bound(ctx, bound, self_ty) | ||
690 | .collect::<Vec<_>>() | ||
691 | .into_iter() | ||
683 | } | 692 | } |
684 | }; | 693 | WherePredicate::Lifetime { .. } => vec![].into_iter(), |
685 | GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) | 694 | } |
686 | } | 695 | } |
687 | 696 | ||
688 | pub(crate) fn from_type_bound<'a>( | 697 | pub(crate) fn from_type_bound<'a>( |
@@ -707,7 +716,7 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
707 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 716 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
708 | let last_segment = match bound { | 717 | let last_segment = match bound { |
709 | TypeBound::Path(path) => path.segments().last(), | 718 | TypeBound::Path(path) => path.segments().last(), |
710 | TypeBound::Error => None, | 719 | TypeBound::Error | TypeBound::Lifetime(_) => None, |
711 | }; | 720 | }; |
712 | last_segment | 721 | last_segment |
713 | .into_iter() | 722 | .into_iter() |
@@ -872,11 +881,16 @@ pub(crate) fn generic_predicates_for_param_query( | |||
872 | resolver | 881 | resolver |
873 | .where_predicates_in_scope() | 882 | .where_predicates_in_scope() |
874 | // we have to filter out all other predicates *first*, before attempting to lower them | 883 | // we have to filter out all other predicates *first*, before attempting to lower them |
875 | .filter(|pred| match &pred.target { | 884 | .filter(|pred| match pred { |
876 | WherePredicateTarget::TypeRef(type_ref) => { | 885 | WherePredicate::TypeBound { |
877 | Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) | 886 | target: WherePredicateTypeTarget::TypeRef(type_ref), |
878 | } | 887 | .. |
879 | WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.local_id, | 888 | } => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id), |
889 | WherePredicate::TypeBound { | ||
890 | target: WherePredicateTypeTarget::TypeParam(local_id), | ||
891 | .. | ||
892 | } => *local_id == param_id.local_id, | ||
893 | WherePredicate::Lifetime { .. } => false, | ||
880 | }) | 894 | }) |
881 | .flat_map(|pred| { | 895 | .flat_map(|pred| { |
882 | GenericPredicate::from_where_predicate(&ctx, pred) | 896 | 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 @@ | |||
2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). | 2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). |
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::generics::WherePredicateTarget; | ||
6 | use hir_def::{ | 5 | use hir_def::{ |
7 | adt::VariantData, | 6 | adt::VariantData, |
8 | db::DefDatabase, | 7 | db::DefDatabase, |
9 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | 8 | generics::{GenericParams, TypeParamData, TypeParamProvenance, WherePredicateTypeTarget}, |
10 | path::Path, | 9 | path::Path, |
11 | resolver::{HasResolver, TypeNs}, | 10 | resolver::{HasResolver, TypeNs}, |
12 | type_ref::TypeRef, | 11 | type_ref::TypeRef, |
@@ -27,14 +26,19 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | |||
27 | generic_params | 26 | generic_params |
28 | .where_predicates | 27 | .where_predicates |
29 | .iter() | 28 | .iter() |
30 | .filter_map(|pred| match &pred.target { | 29 | .filter_map(|pred| match pred { |
31 | WherePredicateTarget::TypeRef(TypeRef::Path(p)) if p == &Path::from(name![Self]) => { | 30 | hir_def::generics::WherePredicate::TypeBound { target, bound } => match target { |
32 | pred.bound.as_path() | 31 | WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) |
33 | } | 32 | if p == &Path::from(name![Self]) => |
34 | WherePredicateTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { | 33 | { |
35 | pred.bound.as_path() | 34 | bound.as_path() |
36 | } | 35 | } |
37 | _ => None, | 36 | WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { |
37 | bound.as_path() | ||
38 | } | ||
39 | _ => None, | ||
40 | }, | ||
41 | hir_def::generics::WherePredicate::Lifetime { .. } => None, | ||
38 | }) | 42 | }) |
39 | .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { | 43 | .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { |
40 | Some(TypeNs::TraitId(t)) => Some(t), | 44 | Some(TypeNs::TraitId(t)) => Some(t), |