diff options
-rw-r--r-- | crates/ra_hir/src/adt.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/generics.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 150 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap | 12 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 33 |
12 files changed, 200 insertions, 106 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 4cca09351..3caf60ee6 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -9,19 +9,27 @@ use ra_syntax::{ | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, | 12 | DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId, |
13 | HirDatabase, DefKind, | 13 | HirDatabase, DefKind, |
14 | SourceItemId, | 14 | SourceItemId, |
15 | type_ref::TypeRef, | 15 | type_ref::TypeRef, |
16 | ids::{StructLoc}, | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | impl Struct { | 19 | impl Struct { |
19 | pub(crate) fn new(def_id: DefId) -> Self { | 20 | pub(crate) fn from_ast( |
20 | Struct { def_id } | 21 | db: &impl HirDatabase, |
22 | module: Module, | ||
23 | file_id: HirFileId, | ||
24 | ast: &ast::StructDef, | ||
25 | ) -> Struct { | ||
26 | let loc: StructLoc = StructLoc::from_ast(db, module, file_id, ast); | ||
27 | let id = loc.id(db); | ||
28 | Struct { id } | ||
21 | } | 29 | } |
22 | 30 | ||
23 | pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { | 31 | pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { |
24 | db.struct_data(self.def_id).variant_data.clone() | 32 | db.struct_data((*self).into()).variant_data.clone() |
25 | } | 33 | } |
26 | } | 34 | } |
27 | 35 | ||
@@ -39,13 +47,9 @@ impl StructData { | |||
39 | StructData { name, variant_data } | 47 | StructData { name, variant_data } |
40 | } | 48 | } |
41 | 49 | ||
42 | pub(crate) fn struct_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<StructData> { | 50 | pub(crate) fn struct_data_query(db: &impl HirDatabase, struct_: Struct) -> Arc<StructData> { |
43 | let def_loc = def_id.loc(db); | 51 | let (_, struct_def) = struct_.source(db); |
44 | assert!(def_loc.kind == DefKind::Struct); | 52 | Arc::new(StructData::new(&*struct_def)) |
45 | let syntax = db.file_item(def_loc.source_item_id); | ||
46 | let struct_def = | ||
47 | ast::StructDef::cast(&syntax).expect("struct def should point to StructDef node"); | ||
48 | Arc::new(StructData::new(struct_def)) | ||
49 | } | 53 | } |
50 | } | 54 | } |
51 | 55 | ||
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 905615127..948718aa6 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -10,13 +10,13 @@ use crate::{ | |||
10 | nameres::{ModuleScope, lower::ImportId}, | 10 | nameres::{ModuleScope, lower::ImportId}, |
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | expr::BodySyntaxMapping, | 12 | expr::BodySyntaxMapping, |
13 | ty::InferenceResult, | 13 | ty::{InferenceResult, VariantDef}, |
14 | adt::VariantData, | 14 | adt::VariantData, |
15 | generics::GenericParams, | 15 | generics::GenericParams, |
16 | code_model_impl::def_id_to_ast, | 16 | code_model_impl::def_id_to_ast, |
17 | docs::{Documentation, Docs, docs_from_ast}, | 17 | docs::{Documentation, Docs, docs_from_ast}, |
18 | module_tree::ModuleId, | 18 | module_tree::ModuleId, |
19 | ids::FunctionId, | 19 | ids::{FunctionId, StructId}, |
20 | }; | 20 | }; |
21 | 21 | ||
22 | /// hir::Crate describes a single crate. It's the main interface with which | 22 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -68,6 +68,7 @@ pub struct Module { | |||
68 | pub enum ModuleDef { | 68 | pub enum ModuleDef { |
69 | Module(Module), | 69 | Module(Module), |
70 | Function(Function), | 70 | Function(Function), |
71 | Struct(Struct), | ||
71 | Def(DefId), | 72 | Def(DefId), |
72 | } | 73 | } |
73 | 74 | ||
@@ -83,6 +84,12 @@ impl Into<ModuleDef> for Function { | |||
83 | } | 84 | } |
84 | } | 85 | } |
85 | 86 | ||
87 | impl Into<ModuleDef> for Struct { | ||
88 | fn into(self) -> ModuleDef { | ||
89 | ModuleDef::Struct(self) | ||
90 | } | ||
91 | } | ||
92 | |||
86 | impl Into<ModuleDef> for DefId { | 93 | impl Into<ModuleDef> for DefId { |
87 | fn into(self) -> ModuleDef { | 94 | fn into(self) -> ModuleDef { |
88 | ModuleDef::Def(self) | 95 | ModuleDef::Def(self) |
@@ -187,7 +194,7 @@ impl Module { | |||
187 | 194 | ||
188 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 195 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
189 | pub struct StructField { | 196 | pub struct StructField { |
190 | parent: DefId, | 197 | parent: VariantDef, |
191 | name: Name, | 198 | name: Name, |
192 | } | 199 | } |
193 | 200 | ||
@@ -201,38 +208,38 @@ impl StructField { | |||
201 | } | 208 | } |
202 | } | 209 | } |
203 | 210 | ||
204 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 211 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
205 | pub struct Struct { | 212 | pub struct Struct { |
206 | pub(crate) def_id: DefId, | 213 | pub(crate) id: StructId, |
207 | } | 214 | } |
208 | 215 | ||
209 | impl Struct { | 216 | impl Struct { |
210 | pub fn def_id(&self) -> DefId { | 217 | pub fn module(&self, db: &impl HirDatabase) -> Module { |
211 | self.def_id | 218 | self.id.loc(db).module |
212 | } | 219 | } |
213 | 220 | ||
214 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 221 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { |
215 | db.struct_data(self.def_id).name.clone() | 222 | db.struct_data(*self).name.clone() |
216 | } | 223 | } |
217 | 224 | ||
218 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { | 225 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { |
219 | db.struct_data(self.def_id) | 226 | db.struct_data(*self) |
220 | .variant_data | 227 | .variant_data |
221 | .fields() | 228 | .fields() |
222 | .iter() | 229 | .iter() |
223 | .map(|it| StructField { | 230 | .map(|it| StructField { |
224 | parent: self.def_id, | 231 | parent: (*self).into(), |
225 | name: it.name.clone(), | 232 | name: it.name.clone(), |
226 | }) | 233 | }) |
227 | .collect() | 234 | .collect() |
228 | } | 235 | } |
229 | 236 | ||
230 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { | 237 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { |
231 | def_id_to_ast(db, self.def_id) | 238 | self.id.loc(db).source(db) |
232 | } | 239 | } |
233 | 240 | ||
234 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 241 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { |
235 | db.generic_params(self.def_id.into()) | 242 | db.generic_params((*self).into()) |
236 | } | 243 | } |
237 | } | 244 | } |
238 | 245 | ||
@@ -310,7 +317,7 @@ impl EnumVariant { | |||
310 | .fields() | 317 | .fields() |
311 | .iter() | 318 | .iter() |
312 | .map(|it| StructField { | 319 | .map(|it| StructField { |
313 | parent: self.def_id, | 320 | parent: self.def_id.into(), |
314 | name: it.name.clone(), | 321 | name: it.name.clone(), |
315 | }) | 322 | }) |
316 | .collect() | 323 | .collect() |
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index b2828c7be..42f10e941 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -135,7 +135,7 @@ impl Module { | |||
135 | None => PerNs::none(), | 135 | None => PerNs::none(), |
136 | } | 136 | } |
137 | } | 137 | } |
138 | ModuleDef::Function(_) => PerNs::none(), | 138 | ModuleDef::Function(_) | ModuleDef::Struct(_) => PerNs::none(), |
139 | ModuleDef::Def(def) => { | 139 | ModuleDef::Def(def) => { |
140 | match def.resolve(db) { | 140 | match def.resolve(db) { |
141 | Def::Enum(e) => { | 141 | Def::Enum(e) => { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 97de7da31..75935c30f 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -8,10 +8,11 @@ use crate::{ | |||
8 | SourceFileItems, SourceItemId, Crate, Module, HirInterner, | 8 | SourceFileItems, SourceItemId, Crate, Module, HirInterner, |
9 | query_definitions, | 9 | query_definitions, |
10 | Function, FnSignature, FnScopes, | 10 | Function, FnSignature, FnScopes, |
11 | Struct, | ||
11 | macros::MacroExpansion, | 12 | macros::MacroExpansion, |
12 | module_tree::ModuleTree, | 13 | module_tree::ModuleTree, |
13 | nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, | 14 | nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, |
14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef}, | 15 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef}, |
15 | adt::{StructData, EnumData, EnumVariantData}, | 16 | adt::{StructData, EnumData, EnumVariantData}, |
16 | impl_block::ModuleImplBlocks, | 17 | impl_block::ModuleImplBlocks, |
17 | generics::{GenericParams, GenericDef}, | 18 | generics::{GenericParams, GenericDef}, |
@@ -29,7 +30,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> { | |||
29 | fn fn_scopes(&self, func: Function) -> Arc<FnScopes>; | 30 | fn fn_scopes(&self, func: Function) -> Arc<FnScopes>; |
30 | 31 | ||
31 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] | 32 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] |
32 | fn struct_data(&self, def_id: DefId) -> Arc<StructData>; | 33 | fn struct_data(&self, struct_: Struct) -> Arc<StructData>; |
33 | 34 | ||
34 | #[salsa::invoke(crate::adt::EnumData::enum_data_query)] | 35 | #[salsa::invoke(crate::adt::EnumData::enum_data_query)] |
35 | fn enum_data(&self, def_id: DefId) -> Arc<EnumData>; | 36 | fn enum_data(&self, def_id: DefId) -> Arc<EnumData>; |
@@ -44,7 +45,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> { | |||
44 | fn type_for_def(&self, def: TypableDef) -> Ty; | 45 | fn type_for_def(&self, def: TypableDef) -> Ty; |
45 | 46 | ||
46 | #[salsa::invoke(crate::ty::type_for_field)] | 47 | #[salsa::invoke(crate::ty::type_for_field)] |
47 | fn type_for_field(&self, def_id: DefId, field: Name) -> Option<Ty>; | 48 | fn type_for_field(&self, def: VariantDef, field: Name) -> Option<Ty>; |
48 | 49 | ||
49 | #[salsa::invoke(query_definitions::file_items)] | 50 | #[salsa::invoke(query_definitions::file_items)] |
50 | fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; | 51 | fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; |
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 88c53705f..e10b85ec9 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -7,7 +7,7 @@ use std::sync::Arc; | |||
7 | 7 | ||
8 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; | 8 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; |
9 | 9 | ||
10 | use crate::{db::HirDatabase, DefId, Name, AsName, Function}; | 10 | use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct}; |
11 | 11 | ||
12 | /// Data about a generic parameter (to a function, struct, impl, ...). | 12 | /// Data about a generic parameter (to a function, struct, impl, ...). |
13 | #[derive(Clone, PartialEq, Eq, Debug)] | 13 | #[derive(Clone, PartialEq, Eq, Debug)] |
@@ -25,6 +25,7 @@ pub struct GenericParams { | |||
25 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | 25 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] |
26 | pub enum GenericDef { | 26 | pub enum GenericDef { |
27 | Function(Function), | 27 | Function(Function), |
28 | Struct(Struct), | ||
28 | Def(DefId), | 29 | Def(DefId), |
29 | } | 30 | } |
30 | 31 | ||
@@ -34,6 +35,12 @@ impl From<Function> for GenericDef { | |||
34 | } | 35 | } |
35 | } | 36 | } |
36 | 37 | ||
38 | impl From<Struct> for GenericDef { | ||
39 | fn from(func: Struct) -> GenericDef { | ||
40 | GenericDef::Struct(func) | ||
41 | } | ||
42 | } | ||
43 | |||
37 | impl From<DefId> for GenericDef { | 44 | impl From<DefId> for GenericDef { |
38 | fn from(def_id: DefId) -> GenericDef { | 45 | fn from(def_id: DefId) -> GenericDef { |
39 | GenericDef::Def(def_id) | 46 | GenericDef::Def(def_id) |
@@ -53,6 +60,12 @@ impl GenericParams { | |||
53 | generics.fill(type_param_list) | 60 | generics.fill(type_param_list) |
54 | } | 61 | } |
55 | } | 62 | } |
63 | GenericDef::Struct(s) => { | ||
64 | let (_, struct_def) = s.source(db); | ||
65 | if let Some(type_param_list) = struct_def.type_param_list() { | ||
66 | generics.fill(type_param_list) | ||
67 | } | ||
68 | } | ||
56 | GenericDef::Def(def_id) => { | 69 | GenericDef::Def(def_id) => { |
57 | let (_file_id, node) = def_id.source(db); | 70 | let (_file_id, node) = def_id.source(db); |
58 | if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) { | 71 | if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) { |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 51e3cfb81..2791149dd 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -5,7 +5,7 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; | |||
5 | use ra_arena::{Arena, RawId, impl_arena_id}; | 5 | use ra_arena::{Arena, RawId, impl_arena_id}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | HirDatabase, Def, Struct, Enum, EnumVariant, Crate, | 8 | HirDatabase, Def, Enum, EnumVariant, Crate, |
9 | Module, Trait, Type, Static, Const, | 9 | Module, Trait, Type, Static, Const, |
10 | }; | 10 | }; |
11 | 11 | ||
@@ -257,10 +257,7 @@ impl DefId { | |||
257 | pub fn resolve(self, db: &impl HirDatabase) -> Def { | 257 | pub fn resolve(self, db: &impl HirDatabase) -> Def { |
258 | let loc = self.loc(db); | 258 | let loc = self.loc(db); |
259 | match loc.kind { | 259 | match loc.kind { |
260 | DefKind::Struct => { | 260 | DefKind::Struct => unreachable!(), |
261 | let struct_def = Struct::new(self); | ||
262 | Def::Struct(struct_def) | ||
263 | } | ||
264 | DefKind::Enum => Def::Enum(Enum::new(self)), | 261 | DefKind::Enum => Def::Enum(Enum::new(self)), |
265 | DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), | 262 | DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), |
266 | DefKind::Const => { | 263 | DefKind::Const => { |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index a6246a5e9..5d6371892 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -43,7 +43,7 @@ pub use self::{ | |||
43 | ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner}, | 43 | ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner}, |
44 | macros::{MacroDef, MacroInput, MacroExpansion}, | 44 | macros::{MacroDef, MacroInput, MacroExpansion}, |
45 | nameres::{ItemMap, PerNs, Namespace, Resolution}, | 45 | nameres::{ItemMap, PerNs, Namespace, Resolution}, |
46 | ty::Ty, | 46 | ty::{Ty, AdtDef}, |
47 | impl_block::{ImplBlock, ImplItem}, | 47 | impl_block::{ImplBlock, ImplItem}, |
48 | code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, | 48 | code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, |
49 | docs::{Docs, Documentation} | 49 | docs::{Docs, Documentation} |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 1f8adc7eb..b0c4aa819 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -10,7 +10,7 @@ use rustc_hash::FxHashMap; | |||
10 | use crate::{ | 10 | use crate::{ |
11 | SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, | 11 | SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, |
12 | HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, | 12 | HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, |
13 | ModuleDef, Module, | 13 | ModuleDef, Module, Struct, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 16 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -147,7 +147,14 @@ impl LoweredModule { | |||
147 | item: &ast::ModuleItem, | 147 | item: &ast::ModuleItem, |
148 | ) { | 148 | ) { |
149 | let name = match item.kind() { | 149 | let name = match item.kind() { |
150 | ast::ModuleItemKind::StructDef(it) => it.name(), | 150 | ast::ModuleItemKind::StructDef(it) => { |
151 | if let Some(name) = it.name() { | ||
152 | let s = Struct::from_ast(db, module, file_id, it); | ||
153 | let s: ModuleDef = s.into(); | ||
154 | self.declarations.insert(name.as_name(), PerNs::both(s, s)); | ||
155 | } | ||
156 | return; | ||
157 | } | ||
151 | ast::ModuleItemKind::EnumDef(it) => it.name(), | 158 | ast::ModuleItemKind::EnumDef(it) => it.name(), |
152 | ast::ModuleItemKind::FnDef(it) => { | 159 | ast::ModuleItemKind::FnDef(it) => { |
153 | if let Some(name) = it.name() { | 160 | if let Some(name) = it.name() { |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index f9cdbcab3..fc699a2ae 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -32,7 +32,7 @@ use rustc_hash::FxHashMap; | |||
32 | 32 | ||
33 | use crate::{ | 33 | use crate::{ |
34 | Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, | 34 | Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, |
35 | FnSignature, FnScopes, ModuleDef, | 35 | FnSignature, FnScopes, ModuleDef, Crate, |
36 | db::HirDatabase, | 36 | db::HirDatabase, |
37 | type_ref::{TypeRef, Mutability}, | 37 | type_ref::{TypeRef, Mutability}, |
38 | name::KnownName, | 38 | name::KnownName, |
@@ -163,6 +163,33 @@ impl Substs { | |||
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
167 | pub enum AdtDef { | ||
168 | Struct(Struct), | ||
169 | Def(DefId), // Enum | ||
170 | } | ||
171 | |||
172 | impl From<Struct> for AdtDef { | ||
173 | fn from(struct_: Struct) -> AdtDef { | ||
174 | AdtDef::Struct(struct_) | ||
175 | } | ||
176 | } | ||
177 | |||
178 | impl From<DefId> for AdtDef { | ||
179 | fn from(def_id: DefId) -> AdtDef { | ||
180 | AdtDef::Def(def_id) | ||
181 | } | ||
182 | } | ||
183 | |||
184 | impl AdtDef { | ||
185 | fn krate(self, db: &impl HirDatabase) -> Option<Crate> { | ||
186 | match self { | ||
187 | AdtDef::Struct(s) => s.module(db).krate(db), | ||
188 | AdtDef::Def(def_id) => def_id.krate(db), | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | |||
166 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). | 193 | /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). |
167 | /// | 194 | /// |
168 | /// This should be cheap to clone. | 195 | /// This should be cheap to clone. |
@@ -184,7 +211,7 @@ pub enum Ty { | |||
184 | /// Structures, enumerations and unions. | 211 | /// Structures, enumerations and unions. |
185 | Adt { | 212 | Adt { |
186 | /// The DefId of the struct/enum. | 213 | /// The DefId of the struct/enum. |
187 | def_id: DefId, | 214 | def_id: AdtDef, |
188 | /// The name, for displaying. | 215 | /// The name, for displaying. |
189 | name: Name, | 216 | name: Name, |
190 | /// Substitutions for the generic parameters of the type. | 217 | /// Substitutions for the generic parameters of the type. |
@@ -384,6 +411,7 @@ impl Ty { | |||
384 | let resolved = match module.resolve_path(db, path).take_types() { | 411 | let resolved = match module.resolve_path(db, path).take_types() { |
385 | Some(ModuleDef::Def(r)) => r.into(), | 412 | Some(ModuleDef::Def(r)) => r.into(), |
386 | Some(ModuleDef::Function(f)) => f.into(), | 413 | Some(ModuleDef::Function(f)) => f.into(), |
414 | Some(ModuleDef::Struct(s)) => s.into(), | ||
387 | None | Some(ModuleDef::Module(_)) => return Ty::Unknown, | 415 | None | Some(ModuleDef::Module(_)) => return Ty::Unknown, |
388 | }; | 416 | }; |
389 | let ty = db.type_for_def(resolved); | 417 | let ty = db.type_for_def(resolved); |
@@ -409,6 +437,7 @@ impl Ty { | |||
409 | .expect("path should have at least one segment"); | 437 | .expect("path should have at least one segment"); |
410 | let (def_generics, segment) = match resolved { | 438 | let (def_generics, segment) = match resolved { |
411 | TypableDef::Function(func) => (func.generic_params(db), last), | 439 | TypableDef::Function(func) => (func.generic_params(db), last), |
440 | TypableDef::Struct(s) => (s.generic_params(db), last), | ||
412 | TypableDef::Def(def_id) => match def_id.resolve(db) { | 441 | TypableDef::Def(def_id) => match def_id.resolve(db) { |
413 | Def::Struct(s) => (s.generic_params(db), last), | 442 | Def::Struct(s) => (s.generic_params(db), last), |
414 | Def::Enum(e) => (e.generic_params(db), last), | 443 | Def::Enum(e) => (e.generic_params(db), last), |
@@ -642,7 +671,7 @@ fn make_substs(generics: &GenericParams) -> Substs { | |||
642 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 671 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
643 | let generics = s.generic_params(db); | 672 | let generics = s.generic_params(db); |
644 | Ty::Adt { | 673 | Ty::Adt { |
645 | def_id: s.def_id(), | 674 | def_id: s.into(), |
646 | name: s.name(db).unwrap_or_else(Name::missing), | 675 | name: s.name(db).unwrap_or_else(Name::missing), |
647 | substs: make_substs(&generics), | 676 | substs: make_substs(&generics), |
648 | } | 677 | } |
@@ -651,7 +680,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | |||
651 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 680 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
652 | let generics = s.generic_params(db); | 681 | let generics = s.generic_params(db); |
653 | Ty::Adt { | 682 | Ty::Adt { |
654 | def_id: s.def_id(), | 683 | def_id: s.def_id().into(), |
655 | name: s.name(db).unwrap_or_else(Name::missing), | 684 | name: s.name(db).unwrap_or_else(Name::missing), |
656 | substs: make_substs(&generics), | 685 | substs: make_substs(&generics), |
657 | } | 686 | } |
@@ -666,6 +695,7 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T | |||
666 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 695 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
667 | pub enum TypableDef { | 696 | pub enum TypableDef { |
668 | Function(Function), | 697 | Function(Function), |
698 | Struct(Struct), | ||
669 | Def(DefId), | 699 | Def(DefId), |
670 | } | 700 | } |
671 | 701 | ||
@@ -675,6 +705,12 @@ impl From<Function> for TypableDef { | |||
675 | } | 705 | } |
676 | } | 706 | } |
677 | 707 | ||
708 | impl From<Struct> for TypableDef { | ||
709 | fn from(struct_: Struct) -> TypableDef { | ||
710 | TypableDef::Struct(struct_) | ||
711 | } | ||
712 | } | ||
713 | |||
678 | impl From<DefId> for TypableDef { | 714 | impl From<DefId> for TypableDef { |
679 | fn from(func: DefId) -> TypableDef { | 715 | fn from(func: DefId) -> TypableDef { |
680 | TypableDef::Def(func) | 716 | TypableDef::Def(func) |
@@ -684,8 +720,8 @@ impl From<DefId> for TypableDef { | |||
684 | pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | 720 | pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { |
685 | match def { | 721 | match def { |
686 | TypableDef::Function(f) => type_for_fn(db, f), | 722 | TypableDef::Function(f) => type_for_fn(db, f), |
723 | TypableDef::Struct(s) => type_for_struct(db, s), | ||
687 | TypableDef::Def(def_id) => match def_id.resolve(db) { | 724 | TypableDef::Def(def_id) => match def_id.resolve(db) { |
688 | Def::Struct(s) => type_for_struct(db, s), | ||
689 | Def::Enum(e) => type_for_enum(db, e), | 725 | Def::Enum(e) => type_for_enum(db, e), |
690 | Def::EnumVariant(ev) => type_for_enum_variant(db, ev), | 726 | Def::EnumVariant(ev) => type_for_enum_variant(db, ev), |
691 | _ => { | 727 | _ => { |
@@ -700,22 +736,44 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | |||
700 | } | 736 | } |
701 | } | 737 | } |
702 | 738 | ||
703 | pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { | 739 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
704 | let def = def_id.resolve(db); | 740 | pub enum VariantDef { |
705 | let (variant_data, generics) = match def { | 741 | Struct(Struct), |
706 | Def::Struct(s) => (s.variant_data(db), s.generic_params(db)), | 742 | Def(DefId), // EnumVariant |
707 | Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)), | 743 | } |
708 | // TODO: unions | 744 | |
709 | Def::Enum(_) => { | 745 | impl From<Struct> for VariantDef { |
710 | // this can happen in (invalid) code, but enums don't have fields themselves | 746 | fn from(struct_: Struct) -> VariantDef { |
711 | return None; | 747 | VariantDef::Struct(struct_) |
712 | } | 748 | } |
713 | _ => panic!( | 749 | } |
714 | "trying to get type for field {:?} in non-struct/variant {:?}", | 750 | |
715 | field, def_id | 751 | impl From<DefId> for VariantDef { |
716 | ), | 752 | fn from(def_id: DefId) -> VariantDef { |
753 | VariantDef::Def(def_id) | ||
754 | } | ||
755 | } | ||
756 | |||
757 | pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> { | ||
758 | let (variant_data, generics, module) = match def { | ||
759 | VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)), | ||
760 | VariantDef::Def(def_id) => match def_id.resolve(db) { | ||
761 | Def::EnumVariant(ev) => ( | ||
762 | ev.variant_data(db), | ||
763 | ev.parent_enum(db).generic_params(db), | ||
764 | def_id.module(db), | ||
765 | ), | ||
766 | // TODO: unions | ||
767 | Def::Enum(_) => { | ||
768 | // this can happen in (invalid) code, but enums don't have fields themselves | ||
769 | return None; | ||
770 | } | ||
771 | _ => panic!( | ||
772 | "trying to get type for field {:?} in non-struct/variant {:?}", | ||
773 | field, def_id | ||
774 | ), | ||
775 | }, | ||
717 | }; | 776 | }; |
718 | let module = def_id.module(db); | ||
719 | // We can't have an impl block ere, right? | 777 | // We can't have an impl block ere, right? |
720 | // let impl_block = def_id.impl_block(db); | 778 | // let impl_block = def_id.impl_block(db); |
721 | let type_ref = variant_data.get_field_type_ref(&field)?; | 779 | let type_ref = variant_data.get_field_type_ref(&field)?; |
@@ -1076,17 +1134,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1076 | }; | 1134 | }; |
1077 | 1135 | ||
1078 | // resolve in module | 1136 | // resolve in module |
1079 | let resolved = match self.module.resolve_path(self.db, &path).take_values()? { | 1137 | let typable = match self.module.resolve_path(self.db, &path).take_values()? { |
1080 | ModuleDef::Def(it) => it.into(), | 1138 | ModuleDef::Def(it) => it.into(), |
1081 | ModuleDef::Function(func) => func.into(), | 1139 | ModuleDef::Function(func) => func.into(), |
1140 | ModuleDef::Struct(s) => s.into(), | ||
1082 | ModuleDef::Module(_) => return None, | 1141 | ModuleDef::Module(_) => return None, |
1083 | }; | 1142 | }; |
1084 | let ty = self.db.type_for_def(resolved); | 1143 | let ty = self.db.type_for_def(typable); |
1085 | let ty = self.insert_type_vars(ty); | 1144 | let ty = self.insert_type_vars(ty); |
1086 | Some(ty) | 1145 | Some(ty) |
1087 | } | 1146 | } |
1088 | 1147 | ||
1089 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) { | 1148 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { |
1090 | let path = match path { | 1149 | let path = match path { |
1091 | Some(path) => path, | 1150 | Some(path) => path, |
1092 | None => return (Ty::Unknown, None), | 1151 | None => return (Ty::Unknown, None), |
@@ -1094,7 +1153,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1094 | let def = match self.module.resolve_path(self.db, &path).take_types() { | 1153 | let def = match self.module.resolve_path(self.db, &path).take_types() { |
1095 | Some(ModuleDef::Def(def_id)) => def_id.into(), | 1154 | Some(ModuleDef::Def(def_id)) => def_id.into(), |
1096 | Some(ModuleDef::Function(func)) => func.into(), | 1155 | Some(ModuleDef::Function(func)) => func.into(), |
1097 | _ => return (Ty::Unknown, None), | 1156 | Some(ModuleDef::Struct(s)) => s.into(), |
1157 | None | Some(ModuleDef::Module(_)) => return (Ty::Unknown, None), | ||
1098 | }; | 1158 | }; |
1099 | // TODO remove the duplication between here and `Ty::from_path`? | 1159 | // TODO remove the duplication between here and `Ty::from_path`? |
1100 | // TODO provide generics of function | 1160 | // TODO provide generics of function |
@@ -1109,37 +1169,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1109 | ); | 1169 | ); |
1110 | match def { | 1170 | match def { |
1111 | TypableDef::Def(def_id) => match def_id.resolve(self.db) { | 1171 | TypableDef::Def(def_id) => match def_id.resolve(self.db) { |
1112 | Def::Struct(s) => { | ||
1113 | let ty = type_for_struct(self.db, s); | ||
1114 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
1115 | (ty, Some(def_id)) | ||
1116 | } | ||
1117 | Def::EnumVariant(ev) => { | 1172 | Def::EnumVariant(ev) => { |
1118 | let ty = type_for_enum_variant(self.db, ev); | 1173 | let ty = type_for_enum_variant(self.db, ev); |
1119 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1174 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1120 | (ty, Some(def_id)) | 1175 | (ty, Some(def_id.into())) |
1121 | } | 1176 | } |
1122 | _ => (Ty::Unknown, None), | 1177 | _ => (Ty::Unknown, None), |
1123 | }, | 1178 | }, |
1124 | TypableDef::Function(_) => (Ty::Unknown, None), | 1179 | TypableDef::Function(_) => (Ty::Unknown, None), |
1180 | TypableDef::Struct(s) => { | ||
1181 | let ty = type_for_struct(self.db, s); | ||
1182 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
1183 | (ty, Some(s.into())) | ||
1184 | } | ||
1125 | } | 1185 | } |
1126 | } | 1186 | } |
1127 | 1187 | ||
1128 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { | 1188 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { |
1129 | let (ty, def_id) = self.resolve_variant(path); | 1189 | let (ty, def) = self.resolve_variant(path); |
1130 | let def_id = def_id?; | 1190 | match def? { |
1131 | let def = def_id.resolve(self.db); | 1191 | VariantDef::Struct(s) => { |
1132 | |||
1133 | match def { | ||
1134 | Def::Struct(s) => { | ||
1135 | let fields = s.fields(self.db); | 1192 | let fields = s.fields(self.db); |
1136 | Some((ty, fields)) | 1193 | Some((ty, fields)) |
1137 | } | 1194 | } |
1138 | Def::EnumVariant(ev) => { | 1195 | VariantDef::Def(def_id) => match def_id.resolve(self.db) { |
1139 | let fields = ev.fields(self.db); | 1196 | Def::EnumVariant(ev) => { |
1140 | Some((ty, fields)) | 1197 | let fields = ev.fields(self.db); |
1141 | } | 1198 | Some((ty, fields)) |
1142 | _ => None, | 1199 | } |
1200 | _ => None, | ||
1201 | }, | ||
1143 | } | 1202 | } |
1144 | } | 1203 | } |
1145 | 1204 | ||
@@ -1240,6 +1299,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1240 | .and_then(|module_def| match module_def { | 1299 | .and_then(|module_def| match module_def { |
1241 | ModuleDef::Def(it) => Some(it.into()), | 1300 | ModuleDef::Def(it) => Some(it.into()), |
1242 | ModuleDef::Function(func) => Some(func.into()), | 1301 | ModuleDef::Function(func) => Some(func.into()), |
1302 | ModuleDef::Struct(s) => Some(s.into()), | ||
1243 | ModuleDef::Module(_) => None, | 1303 | ModuleDef::Module(_) => None, |
1244 | }) | 1304 | }) |
1245 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), | 1305 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), |
@@ -1433,7 +1493,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1433 | for field in fields { | 1493 | for field in fields { |
1434 | let field_ty = if let Some(def_id) = def_id { | 1494 | let field_ty = if let Some(def_id) = def_id { |
1435 | self.db | 1495 | self.db |
1436 | .type_for_field(def_id, field.name.clone()) | 1496 | .type_for_field(def_id.into(), field.name.clone()) |
1437 | .unwrap_or(Ty::Unknown) | 1497 | .unwrap_or(Ty::Unknown) |
1438 | .subst(&substs) | 1498 | .subst(&substs) |
1439 | } else { | 1499 | } else { |
@@ -1457,10 +1517,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1457 | i.and_then(|i| fields.get(i).cloned()) | 1517 | i.and_then(|i| fields.get(i).cloned()) |
1458 | } | 1518 | } |
1459 | Ty::Adt { | 1519 | Ty::Adt { |
1460 | def_id, ref substs, .. | 1520 | def_id: AdtDef::Struct(s), |
1521 | ref substs, | ||
1522 | .. | ||
1461 | } => self | 1523 | } => self |
1462 | .db | 1524 | .db |
1463 | .type_for_field(def_id, name.clone()) | 1525 | .type_for_field(s.into(), name.clone()) |
1464 | .map(|ty| ty.subst(substs)), | 1526 | .map(|ty| ty.subst(substs)), |
1465 | _ => None, | 1527 | _ => None, |
1466 | }) | 1528 | }) |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 0084b24dc..9a571c2aa 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -7,16 +7,16 @@ use std::sync::Arc; | |||
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, | 10 | HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function, |
11 | impl_block::{ImplId, ImplBlock, ImplItem}, | 11 | impl_block::{ImplId, ImplBlock, ImplItem}, |
12 | generics::GenericParams | 12 | generics::GenericParams, |
13 | ty::{AdtDef, Ty} | ||
13 | }; | 14 | }; |
14 | use super::Ty; | ||
15 | 15 | ||
16 | /// This is used as a key for indexing impls. | 16 | /// This is used as a key for indexing impls. |
17 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 17 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
18 | pub enum TyFingerprint { | 18 | pub enum TyFingerprint { |
19 | Adt(DefId), | 19 | Adt(AdtDef), |
20 | // we'll also want to index impls for primitive types etc. | 20 | // we'll also want to index impls for primitive types etc. |
21 | } | 21 | } |
22 | 22 | ||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap index c4a2d5cf8..8747fae18 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap | |||
@@ -1,19 +1,19 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-22T14:45:00.058678600+00:00" | 2 | created: "2019-01-24T14:51:32.808861856+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: "crates\\ra_hir\\src\\ty\\tests.rs" | 5 | source: crates/ra_hir/src/ty/tests.rs |
6 | --- | 6 | --- |
7 | [72; 154) '{ ...a.c; }': () | 7 | [72; 154) '{ ...a.c; }': () |
8 | [82; 83) 'c': [unknown] | 8 | [82; 83) 'c': [unknown] |
9 | [86; 87) 'C': [unknown] | 9 | [86; 87) 'C': C |
10 | [86; 90) 'C(1)': [unknown] | 10 | [86; 90) 'C(1)': [unknown] |
11 | [88; 89) '1': i32 | 11 | [88; 89) '1': i32 |
12 | [96; 97) 'B': [unknown] | 12 | [96; 97) 'B': B |
13 | [107; 108) 'a': A | 13 | [107; 108) 'a': A |
14 | [114; 133) 'A { b:...C(1) }': A | 14 | [114; 133) 'A { b:...C(1) }': A |
15 | [121; 122) 'B': B | 15 | [121; 122) 'B': B |
16 | [127; 128) 'C': [unknown] | 16 | [127; 128) 'C': C |
17 | [127; 131) 'C(1)': C | 17 | [127; 131) 'C(1)': C |
18 | [129; 130) '1': i32 | 18 | [129; 130) '1': i32 |
19 | [139; 140) 'a': A | 19 | [139; 140) 'a': A |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 32fd497be..1a2b0b2f6 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{Ty, Def}; | 1 | use hir::{Ty, Def, AdtDef}; |
2 | 2 | ||
3 | use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; | 3 | use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; |
4 | use crate::completion::completion_item::CompletionKind; | 4 | use crate::completion::completion_item::CompletionKind; |
@@ -28,21 +28,24 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
28 | Ty::Adt { | 28 | Ty::Adt { |
29 | def_id, ref substs, .. | 29 | def_id, ref substs, .. |
30 | } => { | 30 | } => { |
31 | match def_id.resolve(ctx.db) { | 31 | match def_id { |
32 | Def::Struct(s) => { | 32 | AdtDef::Struct() => {} |
33 | for field in s.fields(ctx.db) { | 33 | AdtDef::Def(def_id) => match def_id.resolve(ctx.db) { |
34 | CompletionItem::new( | 34 | Def::Struct(s) => { |
35 | CompletionKind::Reference, | 35 | for field in s.fields(ctx.db) { |
36 | ctx.source_range(), | 36 | CompletionItem::new( |
37 | field.name().to_string(), | 37 | CompletionKind::Reference, |
38 | ) | 38 | ctx.source_range(), |
39 | .kind(CompletionItemKind::Field) | 39 | field.name().to_string(), |
40 | .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) | 40 | ) |
41 | .add_to(acc); | 41 | .kind(CompletionItemKind::Field) |
42 | .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) | ||
43 | .add_to(acc); | ||
44 | } | ||
42 | } | 45 | } |
43 | } | 46 | // TODO unions |
44 | // TODO unions | 47 | _ => {} |
45 | _ => {} | 48 | }, |
46 | } | 49 | } |
47 | } | 50 | } |
48 | Ty::Tuple(fields) => { | 51 | Ty::Tuple(fields) => { |