diff options
33 files changed, 418 insertions, 149 deletions
diff --git a/Cargo.lock b/Cargo.lock index d3aec4c99..8cb5fd7ad 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -261,9 +261,9 @@ dependencies = [ | |||
261 | 261 | ||
262 | [[package]] | 262 | [[package]] |
263 | name = "const_fn" | 263 | name = "const_fn" |
264 | version = "0.4.3" | 264 | version = "0.4.4" |
265 | source = "registry+https://github.com/rust-lang/crates.io-index" | 265 | source = "registry+https://github.com/rust-lang/crates.io-index" |
266 | checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" | 266 | checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" |
267 | 267 | ||
268 | [[package]] | 268 | [[package]] |
269 | name = "crc32fast" | 269 | name = "crc32fast" |
@@ -990,9 +990,9 @@ dependencies = [ | |||
990 | 990 | ||
991 | [[package]] | 991 | [[package]] |
992 | name = "net2" | 992 | name = "net2" |
993 | version = "0.2.36" | 993 | version = "0.2.37" |
994 | source = "registry+https://github.com/rust-lang/crates.io-index" | 994 | source = "registry+https://github.com/rust-lang/crates.io-index" |
995 | checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02" | 995 | checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" |
996 | dependencies = [ | 996 | dependencies = [ |
997 | "cfg-if 0.1.10", | 997 | "cfg-if 0.1.10", |
998 | "libc", | 998 | "libc", |
@@ -2021,18 +2021,18 @@ dependencies = [ | |||
2021 | 2021 | ||
2022 | [[package]] | 2022 | [[package]] |
2023 | name = "xshell" | 2023 | name = "xshell" |
2024 | version = "0.1.6" | 2024 | version = "0.1.7" |
2025 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2025 | source = "registry+https://github.com/rust-lang/crates.io-index" |
2026 | checksum = "3e9bbfccbb2233e6b0473b7870d4b0811a402e9e249a5e8394e768e5a5c9c37d" | 2026 | checksum = "ed0728d188f2ae530490b7d92435728aba53c6aed06d07e1951da9bd4c1d0798" |
2027 | dependencies = [ | 2027 | dependencies = [ |
2028 | "xshell-macros", | 2028 | "xshell-macros", |
2029 | ] | 2029 | ] |
2030 | 2030 | ||
2031 | [[package]] | 2031 | [[package]] |
2032 | name = "xshell-macros" | 2032 | name = "xshell-macros" |
2033 | version = "0.1.6" | 2033 | version = "0.1.7" |
2034 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2034 | source = "registry+https://github.com/rust-lang/crates.io-index" |
2035 | checksum = "b94f1c632d730a1704b21dc551a4c74fbed713cfa59593708f94943548206134" | 2035 | checksum = "367f903cc3f8bc4f4b2400d47dfa6c9e3e121ffb51a30cf0fb67a72c0a0f9617" |
2036 | 2036 | ||
2037 | [[package]] | 2037 | [[package]] |
2038 | name = "xtask" | 2038 | name = "xtask" |
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/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index d85767b4e..2e56bd7ff 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -212,7 +212,7 @@ fn update_reference( | |||
212 | find_node_at_offset::<ast::PathExpr>(source_file.syntax(), offset) | 212 | find_node_at_offset::<ast::PathExpr>(source_file.syntax(), offset) |
213 | { | 213 | { |
214 | // tuple variant | 214 | // tuple variant |
215 | (path_expr.path()?.segment()?, path_expr.syntax().parent()?.clone()) | 215 | (path_expr.path()?.segment()?, path_expr.syntax().parent()?) |
216 | } else if let Some(record_expr) = | 216 | } else if let Some(record_expr) = |
217 | find_node_at_offset::<ast::RecordExpr>(source_file.syntax(), offset) | 217 | find_node_at_offset::<ast::RecordExpr>(source_file.syntax(), offset) |
218 | { | 218 | { |
diff --git a/crates/assists/src/handlers/qualify_path.rs b/crates/assists/src/handlers/qualify_path.rs index 6f9810fe8..98cb09214 100644 --- a/crates/assists/src/handlers/qualify_path.rs +++ b/crates/assists/src/handlers/qualify_path.rs | |||
@@ -150,7 +150,7 @@ impl QualifyCandidate<'_> { | |||
150 | import, | 150 | import, |
151 | trait_method_name, | 151 | trait_method_name, |
152 | generics, | 152 | generics, |
153 | match arg_list.clone() { | 153 | match arg_list { |
154 | Some(args) => make::arg_list(iter::once(receiver).chain(args)), | 154 | Some(args) => make::arg_list(iter::once(receiver).chain(args)), |
155 | None => make::arg_list(iter::once(receiver)), | 155 | None => make::arg_list(iter::once(receiver)), |
156 | } | 156 | } |
diff --git a/crates/cfg/src/dnf.rs b/crates/cfg/src/dnf.rs index 580c9a9a2..30f4bcdf7 100644 --- a/crates/cfg/src/dnf.rs +++ b/crates/cfg/src/dnf.rs | |||
@@ -30,7 +30,7 @@ impl DnfExpr { | |||
30 | pub fn new(expr: CfgExpr) -> Self { | 30 | pub fn new(expr: CfgExpr) -> Self { |
31 | let builder = Builder { expr: DnfExpr { conjunctions: Vec::new() } }; | 31 | let builder = Builder { expr: DnfExpr { conjunctions: Vec::new() } }; |
32 | 32 | ||
33 | builder.lower(expr.clone()) | 33 | builder.lower(expr) |
34 | } | 34 | } |
35 | 35 | ||
36 | /// Computes a list of present or absent atoms in `opts` that cause this expression to evaluate | 36 | /// Computes a list of present or absent atoms in `opts` that cause this expression to evaluate |
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index 2b0924ae5..b9315f6c0 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -147,7 +147,7 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<() | |||
147 | .filter_map(|(import_path, definition)| { | 147 | .filter_map(|(import_path, definition)| { |
148 | render_resolution_with_import( | 148 | render_resolution_with_import( |
149 | RenderContext::new(ctx), | 149 | RenderContext::new(ctx), |
150 | ImportEdit { import_path: import_path.clone(), import_scope: import_scope.clone() }, | 150 | ImportEdit { import_path, import_scope: import_scope.clone() }, |
151 | &definition, | 151 | &definition, |
152 | ) | 152 | ) |
153 | }); | 153 | }); |
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs index d16005249..316e05b52 100644 --- a/crates/completion/src/render/function.rs +++ b/crates/completion/src/render/function.rs | |||
@@ -91,7 +91,7 @@ impl<'a> FunctionRender<'a> { | |||
91 | .zip(params_ty) | 91 | .zip(params_ty) |
92 | .flat_map(|(pat, param_ty)| { | 92 | .flat_map(|(pat, param_ty)| { |
93 | let pat = pat?; | 93 | let pat = pat?; |
94 | let name = pat.to_string(); | 94 | let name = pat; |
95 | let arg = name.trim_start_matches("mut ").trim_start_matches('_'); | 95 | let arg = name.trim_start_matches("mut ").trim_start_matches('_'); |
96 | Some(self.add_arg(arg, param_ty.ty())) | 96 | Some(self.add_arg(arg, param_ty.ty())) |
97 | }) | 97 | }) |
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/attr.rs b/crates/hir_def/src/attr.rs index ff8fb7483..c64b78445 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -23,7 +23,7 @@ use crate::{ | |||
23 | }; | 23 | }; |
24 | 24 | ||
25 | /// Holds documentation | 25 | /// Holds documentation |
26 | #[derive(Debug, Clone, PartialEq, Eq)] | 26 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
27 | pub struct Documentation(String); | 27 | pub struct Documentation(String); |
28 | 28 | ||
29 | impl Documentation { | 29 | impl Documentation { |
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 a75d4d302..7e2199a9c 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -225,6 +225,13 @@ pub struct TypeParamId { | |||
225 | pub type LocalTypeParamId = Idx<generics::TypeParamData>; | 225 | pub type LocalTypeParamId = Idx<generics::TypeParamData>; |
226 | 226 | ||
227 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 227 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
228 | pub struct LifetimeParamId { | ||
229 | pub parent: GenericDefId, | ||
230 | pub local_id: LocalLifetimeParamId, | ||
231 | } | ||
232 | pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>; | ||
233 | |||
234 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
228 | pub enum ContainerId { | 235 | pub enum ContainerId { |
229 | ModuleId(ModuleId), | 236 | ModuleId(ModuleId), |
230 | DefWithBodyId(DefWithBodyId), | 237 | 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/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index e59487e54..1c72f766e 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -624,4 +624,14 @@ fn foo() { break; } | |||
624 | "#, | 624 | "#, |
625 | ); | 625 | ); |
626 | } | 626 | } |
627 | |||
628 | #[test] | ||
629 | fn missing_semicolon() { | ||
630 | check_diagnostics( | ||
631 | r#" | ||
632 | fn test() -> i32 { 123; } | ||
633 | //^^^ Remove this semicolon | ||
634 | "#, | ||
635 | ); | ||
636 | } | ||
627 | } | 637 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index aa286c8c2..0e827a29e 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, |
@@ -718,6 +718,19 @@ impl HirDisplay for GenericPredicate { | |||
718 | } | 718 | } |
719 | } | 719 | } |
720 | 720 | ||
721 | impl HirDisplay for Lifetime { | ||
722 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
723 | match self { | ||
724 | Lifetime::Parameter(id) => { | ||
725 | let generics = generics(f.db.upcast(), id.parent); | ||
726 | let param_data = &generics.params.lifetimes[id.local_id]; | ||
727 | write!(f, "{}", ¶m_data.name) | ||
728 | } | ||
729 | Lifetime::Static => write!(f, "'static"), | ||
730 | } | ||
731 | } | ||
732 | } | ||
733 | |||
721 | impl HirDisplay for Obligation { | 734 | impl HirDisplay for Obligation { |
722 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 735 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
723 | match self { | 736 | match self { |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 605951b10..ca005bc99 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -137,10 +137,24 @@ impl<'a> InferenceContext<'a> { | |||
137 | 137 | ||
138 | self.coerce_merge_branch(&then_ty, &else_ty) | 138 | self.coerce_merge_branch(&then_ty, &else_ty) |
139 | } | 139 | } |
140 | Expr::Block { statements, tail, .. } => { | 140 | Expr::Block { statements, tail, label } => match label { |
141 | // FIXME: Breakable block inference | 141 | Some(_) => { |
142 | self.infer_block(statements, *tail, expected) | 142 | let break_ty = self.table.new_type_var(); |
143 | } | 143 | self.breakables.push(BreakableContext { |
144 | may_break: false, | ||
145 | break_ty: break_ty.clone(), | ||
146 | label: label.clone(), | ||
147 | }); | ||
148 | let ty = self.infer_block(statements, *tail, &Expectation::has_type(break_ty)); | ||
149 | let ctxt = self.breakables.pop().expect("breakable stack broken"); | ||
150 | if ctxt.may_break { | ||
151 | ctxt.break_ty | ||
152 | } else { | ||
153 | ty | ||
154 | } | ||
155 | } | ||
156 | None => self.infer_block(statements, *tail, expected), | ||
157 | }, | ||
144 | Expr::Unsafe { body } => self.infer_expr(*body, expected), | 158 | Expr::Unsafe { body } => self.infer_expr(*body, expected), |
145 | Expr::TryBlock { body } => { | 159 | Expr::TryBlock { body } => { |
146 | let _inner = self.infer_expr(*body, expected); | 160 | let _inner = self.infer_expr(*body, expected); |
@@ -848,6 +862,7 @@ impl<'a> InferenceContext<'a> { | |||
848 | let ty = self.make_ty(type_ref); | 862 | let ty = self.make_ty(type_ref); |
849 | substs.push(ty); | 863 | substs.push(ty); |
850 | } | 864 | } |
865 | GenericArg::Lifetime(_) => {} | ||
851 | } | 866 | } |
852 | } | 867 | } |
853 | }; | 868 | }; |
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/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 4f72582b6..a569223b4 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -2075,6 +2075,62 @@ fn infer_labelled_break_with_val() { | |||
2075 | } | 2075 | } |
2076 | 2076 | ||
2077 | #[test] | 2077 | #[test] |
2078 | fn infer_labelled_block_break_with_val() { | ||
2079 | check_infer( | ||
2080 | r#" | ||
2081 | fn default<T>() -> T { loop {} } | ||
2082 | fn foo() { | ||
2083 | let _x = 'outer: { | ||
2084 | let inner = 'inner: { | ||
2085 | let i = default(); | ||
2086 | if (break 'outer i) { | ||
2087 | break 'inner 5i8; | ||
2088 | } else if true { | ||
2089 | break 'inner 6; | ||
2090 | } | ||
2091 | break 'inner 'innermost: { 0 }; | ||
2092 | 42 | ||
2093 | }; | ||
2094 | break 'outer inner < 8; | ||
2095 | }; | ||
2096 | } | ||
2097 | "#, | ||
2098 | expect![[r#" | ||
2099 | 21..32 '{ loop {} }': T | ||
2100 | 23..30 'loop {}': ! | ||
2101 | 28..30 '{}': () | ||
2102 | 42..381 '{ ... }; }': () | ||
2103 | 52..54 '_x': bool | ||
2104 | 65..378 '{ ... }': bool | ||
2105 | 79..84 'inner': i8 | ||
2106 | 95..339 '{ ... }': i8 | ||
2107 | 113..114 'i': bool | ||
2108 | 117..124 'default': fn default<bool>() -> bool | ||
2109 | 117..126 'default()': bool | ||
2110 | 140..270 'if (br... }': () | ||
2111 | 144..158 'break 'outer i': ! | ||
2112 | 157..158 'i': bool | ||
2113 | 160..209 '{ ... }': () | ||
2114 | 178..194 'break ...er 5i8': ! | ||
2115 | 191..194 '5i8': i8 | ||
2116 | 215..270 'if tru... }': () | ||
2117 | 218..222 'true': bool | ||
2118 | 223..270 '{ ... }': () | ||
2119 | 241..255 'break 'inner 6': ! | ||
2120 | 254..255 '6': i8 | ||
2121 | 283..313 'break ... { 0 }': ! | ||
2122 | 308..313 '{ 0 }': i8 | ||
2123 | 310..311 '0': i8 | ||
2124 | 327..329 '42': i8 | ||
2125 | 349..371 'break ...er < 8': ! | ||
2126 | 362..367 'inner': i8 | ||
2127 | 362..371 'inner < 8': bool | ||
2128 | 370..371 '8': i8 | ||
2129 | "#]], | ||
2130 | ); | ||
2131 | } | ||
2132 | |||
2133 | #[test] | ||
2078 | fn generic_default() { | 2134 | fn generic_default() { |
2079 | check_infer( | 2135 | check_infer( |
2080 | r#" | 2136 | r#" |
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), |
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index 4790d648a..234f80a3a 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -1,11 +1,13 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use either::Either; | 3 | use either::Either; |
4 | use hir::{AssocItem, FieldSource, HasSource, InFile, ModuleSource}; | 4 | use hir::{ |
5 | AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirFileId, InFile, ModuleSource, | ||
6 | }; | ||
5 | use ide_db::base_db::{FileId, SourceDatabase}; | 7 | use ide_db::base_db::{FileId, SourceDatabase}; |
6 | use ide_db::{defs::Definition, RootDatabase}; | 8 | use ide_db::{defs::Definition, RootDatabase}; |
7 | use syntax::{ | 9 | use syntax::{ |
8 | ast::{self, DocCommentsOwner, NameOwner}, | 10 | ast::{self, NameOwner}, |
9 | match_ast, AstNode, SmolStr, | 11 | match_ast, AstNode, SmolStr, |
10 | SyntaxKind::{self, IDENT_PAT, TYPE_PARAM}, | 12 | SyntaxKind::{self, IDENT_PAT, TYPE_PARAM}, |
11 | TextRange, | 13 | TextRange, |
@@ -43,7 +45,7 @@ pub struct NavigationTarget { | |||
43 | pub kind: SyntaxKind, | 45 | pub kind: SyntaxKind, |
44 | pub container_name: Option<SmolStr>, | 46 | pub container_name: Option<SmolStr>, |
45 | pub description: Option<String>, | 47 | pub description: Option<String>, |
46 | pub docs: Option<String>, | 48 | pub docs: Option<Documentation>, |
47 | } | 49 | } |
48 | 50 | ||
49 | pub(crate) trait ToNav { | 51 | pub(crate) trait ToNav { |
@@ -71,7 +73,7 @@ impl NavigationTarget { | |||
71 | frange.range, | 73 | frange.range, |
72 | src.value.syntax().kind(), | 74 | src.value.syntax().kind(), |
73 | ); | 75 | ); |
74 | res.docs = src.value.doc_comment_text(); | 76 | res.docs = module.attrs(db).docs(); |
75 | res.description = src.value.short_label(); | 77 | res.description = src.value.short_label(); |
76 | return res; | 78 | return res; |
77 | } | 79 | } |
@@ -214,14 +216,14 @@ impl ToNavFromAst for hir::Trait {} | |||
214 | 216 | ||
215 | impl<D> ToNav for D | 217 | impl<D> ToNav for D |
216 | where | 218 | where |
217 | D: HasSource + ToNavFromAst + Copy, | 219 | D: HasSource + ToNavFromAst + Copy + HasAttrs, |
218 | D::Ast: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, | 220 | D::Ast: ast::NameOwner + ShortLabel, |
219 | { | 221 | { |
220 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 222 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
221 | let src = self.source(db); | 223 | let src = self.source(db); |
222 | let mut res = | 224 | let mut res = |
223 | NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner)); | 225 | NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner)); |
224 | res.docs = src.value.doc_comment_text(); | 226 | res.docs = self.docs(db); |
225 | res.description = src.value.short_label(); | 227 | res.description = src.value.short_label(); |
226 | res | 228 | res |
227 | } | 229 | } |
@@ -274,7 +276,7 @@ impl ToNav for hir::Field { | |||
274 | match &src.value { | 276 | match &src.value { |
275 | FieldSource::Named(it) => { | 277 | FieldSource::Named(it) => { |
276 | let mut res = NavigationTarget::from_named(db, src.with_value(it)); | 278 | let mut res = NavigationTarget::from_named(db, src.with_value(it)); |
277 | res.docs = it.doc_comment_text(); | 279 | res.docs = self.docs(db); |
278 | res.description = it.short_label(); | 280 | res.description = it.short_label(); |
279 | res | 281 | res |
280 | } | 282 | } |
@@ -298,7 +300,7 @@ impl ToNav for hir::MacroDef { | |||
298 | log::debug!("nav target {:#?}", src.value.syntax()); | 300 | log::debug!("nav target {:#?}", src.value.syntax()); |
299 | let mut res = | 301 | let mut res = |
300 | NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner)); | 302 | NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner)); |
301 | res.docs = src.value.doc_comment_text(); | 303 | res.docs = self.docs(db); |
302 | res | 304 | res |
303 | } | 305 | } |
304 | } | 306 | } |
@@ -374,26 +376,28 @@ impl ToNav for hir::TypeParam { | |||
374 | } | 376 | } |
375 | } | 377 | } |
376 | 378 | ||
377 | pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { | 379 | pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<Documentation> { |
378 | let parse = db.parse(symbol.file_id); | 380 | let parse = db.parse(symbol.file_id); |
379 | let node = symbol.ptr.to_node(parse.tree().syntax()); | 381 | let node = symbol.ptr.to_node(parse.tree().syntax()); |
382 | let file_id = HirFileId::from(symbol.file_id); | ||
380 | 383 | ||
381 | match_ast! { | 384 | let it = match_ast! { |
382 | match node { | 385 | match node { |
383 | ast::Fn(it) => it.doc_comment_text(), | 386 | ast::Fn(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
384 | ast::Struct(it) => it.doc_comment_text(), | 387 | ast::Struct(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
385 | ast::Enum(it) => it.doc_comment_text(), | 388 | ast::Enum(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
386 | ast::Trait(it) => it.doc_comment_text(), | 389 | ast::Trait(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
387 | ast::Module(it) => it.doc_comment_text(), | 390 | ast::Module(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
388 | ast::TypeAlias(it) => it.doc_comment_text(), | 391 | ast::TypeAlias(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
389 | ast::Const(it) => it.doc_comment_text(), | 392 | ast::Const(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
390 | ast::Static(it) => it.doc_comment_text(), | 393 | ast::Static(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
391 | ast::RecordField(it) => it.doc_comment_text(), | 394 | ast::RecordField(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
392 | ast::Variant(it) => it.doc_comment_text(), | 395 | ast::Variant(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
393 | ast::MacroCall(it) => it.doc_comment_text(), | 396 | ast::MacroCall(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)), |
394 | _ => None, | 397 | _ => return None, |
395 | } | 398 | } |
396 | } | 399 | }; |
400 | it.docs() | ||
397 | } | 401 | } |
398 | 402 | ||
399 | /// Get a description of a symbol. | 403 | /// Get a description of a symbol. |
diff --git a/crates/mbe/src/mbe_expander/matcher.rs b/crates/mbe/src/mbe_expander/matcher.rs index 3f8445897..93ee77908 100644 --- a/crates/mbe/src/mbe_expander/matcher.rs +++ b/crates/mbe/src/mbe_expander/matcher.rs | |||
@@ -356,6 +356,18 @@ impl<'a> TtIter<'a> { | |||
356 | ExpandResult { value: _, err: Some(_) } => None, | 356 | ExpandResult { value: _, err: Some(_) } => None, |
357 | } | 357 | } |
358 | } | 358 | } |
359 | |||
360 | pub(crate) fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> { | ||
361 | let mut fork = self.clone(); | ||
362 | match fork.expect_char(c) { | ||
363 | Ok(_) => { | ||
364 | let tt = self.next().cloned(); | ||
365 | *self = fork; | ||
366 | tt | ||
367 | } | ||
368 | Err(_) => None, | ||
369 | } | ||
370 | } | ||
359 | } | 371 | } |
360 | 372 | ||
361 | pub(super) fn match_repeat( | 373 | pub(super) fn match_repeat( |
@@ -447,10 +459,22 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragmen | |||
447 | .expect_lifetime() | 459 | .expect_lifetime() |
448 | .map(|tt| Some(tt)) | 460 | .map(|tt| Some(tt)) |
449 | .map_err(|()| err!("expected lifetime")), | 461 | .map_err(|()| err!("expected lifetime")), |
450 | "literal" => input | 462 | "literal" => { |
451 | .expect_literal() | 463 | let neg = input.eat_char('-'); |
452 | .map(|literal| Some(tt::Leaf::from(literal.clone()).into())) | 464 | input |
453 | .map_err(|()| err!()), | 465 | .expect_literal() |
466 | .map(|literal| { | ||
467 | let lit = tt::Leaf::from(literal.clone()); | ||
468 | match neg { | ||
469 | None => Some(lit.into()), | ||
470 | Some(neg) => Some(tt::TokenTree::Subtree(tt::Subtree { | ||
471 | delimiter: None, | ||
472 | token_trees: vec![neg, lit.into()], | ||
473 | })), | ||
474 | } | ||
475 | }) | ||
476 | .map_err(|()| err!()) | ||
477 | } | ||
454 | // `vis` is optional | 478 | // `vis` is optional |
455 | "vis" => match input.eat_vis() { | 479 | "vis" => match input.eat_vis() { |
456 | Some(vis) => Ok(Some(vis)), | 480 | Some(vis) => Ok(Some(vis)), |
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index 0796ceee1..843054fe8 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs | |||
@@ -1008,11 +1008,20 @@ fn test_literal() { | |||
1008 | parse_macro( | 1008 | parse_macro( |
1009 | r#" | 1009 | r#" |
1010 | macro_rules! foo { | 1010 | macro_rules! foo { |
1011 | ($ type:ty $ lit:literal) => { const VALUE: $ type = $ lit;}; | 1011 | ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;}; |
1012 | } | 1012 | } |
1013 | "#, | 1013 | "#, |
1014 | ) | 1014 | ) |
1015 | .assert_expand_items(r#"foo!(u8 0);"#, r#"const VALUE : u8 = 0 ;"#); | 1015 | .assert_expand_items(r#"foo!(u8,0);"#, r#"const VALUE : u8 = 0 ;"#); |
1016 | |||
1017 | parse_macro( | ||
1018 | r#" | ||
1019 | macro_rules! foo { | ||
1020 | ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;}; | ||
1021 | } | ||
1022 | "#, | ||
1023 | ) | ||
1024 | .assert_expand_items(r#"foo!(i32,-1);"#, r#"const VALUE : i32 = - 1 ;"#); | ||
1016 | } | 1025 | } |
1017 | 1026 | ||
1018 | #[test] | 1027 | #[test] |
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 7f4a7e56b..68a235ce3 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -475,7 +475,7 @@ fn add_target_crate_root( | |||
475 | Some(display_name), | 475 | Some(display_name), |
476 | cfg_options, | 476 | cfg_options, |
477 | env, | 477 | env, |
478 | proc_macro.clone(), | 478 | proc_macro, |
479 | ); | 479 | ); |
480 | 480 | ||
481 | crate_id | 481 | crate_id |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index a5f7647b8..ec3d5e060 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -658,7 +658,6 @@ impl GlobalState { | |||
658 | log::trace!("updating notifications for {:?}", subscriptions); | 658 | log::trace!("updating notifications for {:?}", subscriptions); |
659 | if self.config.publish_diagnostics { | 659 | if self.config.publish_diagnostics { |
660 | let snapshot = self.snapshot(); | 660 | let snapshot = self.snapshot(); |
661 | let subscriptions = subscriptions.clone(); | ||
662 | self.task_pool.handle.spawn(move || { | 661 | self.task_pool.handle.spawn(move || { |
663 | let diagnostics = subscriptions | 662 | let diagnostics = subscriptions |
664 | .into_iter() | 663 | .into_iter() |
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index aa3a4b606..820af2d20 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -55,7 +55,7 @@ impl ast::Attr { | |||
55 | let key = self.simple_name()?; | 55 | let key = self.simple_name()?; |
56 | let value_token = lit.syntax().first_token()?; | 56 | let value_token = lit.syntax().first_token()?; |
57 | 57 | ||
58 | let value: SmolStr = ast::String::cast(value_token.clone())?.value()?.into(); | 58 | let value: SmolStr = ast::String::cast(value_token)?.value()?.into(); |
59 | 59 | ||
60 | Some((key, value)) | 60 | Some((key, value)) |
61 | } | 61 | } |
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index 52b7285dd..5e9620a40 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs | |||
@@ -599,7 +599,7 @@ impl ast::IntNumber { | |||
599 | text = &text[radix.prefix_len()..]; | 599 | text = &text[radix.prefix_len()..]; |
600 | 600 | ||
601 | let buf; | 601 | let buf; |
602 | if text.contains("_") { | 602 | if text.contains('_') { |
603 | buf = text.replace('_', ""); | 603 | buf = text.replace('_', ""); |
604 | text = buf.as_str(); | 604 | text = buf.as_str(); |
605 | }; | 605 | }; |
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index d7c85ebe9..be218dea1 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs | |||
@@ -134,7 +134,7 @@ r#####" | |||
134 | 134 | ||
135 | buf.push_str(&test) | 135 | buf.push_str(&test) |
136 | } | 136 | } |
137 | let buf = reformat(&buf.to_string())?; | 137 | let buf = reformat(&buf)?; |
138 | codegen::update(&project_root().join("crates/assists/src/tests/generated.rs"), &buf, mode) | 138 | codegen::update(&project_root().join("crates/assists/src/tests/generated.rs"), &buf, mode) |
139 | } | 139 | } |
140 | 140 | ||