diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-25 12:03:57 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-25 12:03:57 +0000 |
commit | 7c9acf2f834c582d9cad4f7d0679a0697c591432 (patch) | |
tree | 5829e5a0e4567c532a5d430ed9406a8cd072f5ca | |
parent | 4f67df904252c5fbbf3b892bb2e8405778bc904a (diff) | |
parent | cff9a7dfadc6069bbc7b49c3ceb8497c78d426ab (diff) |
Merge #897
897: Add basic const/static type inference r=flodiebold a=vipentti
This adds basic const/static type inference discussed in #887.
Currently the inference does not work for const/static declared inside a block. In addition the inference does not work inside the bodies of const/static.
Co-authored-by: Ville Penttinen <[email protected]>
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 42 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/konst.rs | 37 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 35 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_const.snap | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_static.snap | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 37 |
11 files changed, 206 insertions, 20 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 9a44aaa43..da0f1ec94 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -554,11 +554,26 @@ impl Const { | |||
554 | self.id.module(db) | 554 | self.id.module(db) |
555 | } | 555 | } |
556 | 556 | ||
557 | pub fn signature(&self, db: &impl HirDatabase) -> Arc<ConstSignature> { | ||
558 | db.const_signature(*self) | ||
559 | } | ||
560 | |||
557 | /// The containing impl block, if this is a method. | 561 | /// The containing impl block, if this is a method. |
558 | pub fn impl_block(&self, db: &impl PersistentHirDatabase) -> Option<ImplBlock> { | 562 | pub fn impl_block(&self, db: &impl PersistentHirDatabase) -> Option<ImplBlock> { |
559 | let module_impls = db.impls_in_module(self.module(db)); | 563 | let module_impls = db.impls_in_module(self.module(db)); |
560 | ImplBlock::containing(module_impls, (*self).into()) | 564 | ImplBlock::containing(module_impls, (*self).into()) |
561 | } | 565 | } |
566 | |||
567 | // TODO: move to a more general type for 'body-having' items | ||
568 | /// Builds a resolver for code inside this item. | ||
569 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
570 | // take the outer scope... | ||
571 | let r = self | ||
572 | .impl_block(db) | ||
573 | .map(|ib| ib.resolver(db)) | ||
574 | .unwrap_or_else(|| self.module(db).resolver(db)); | ||
575 | r | ||
576 | } | ||
562 | } | 577 | } |
563 | 578 | ||
564 | impl Docs for Const { | 579 | impl Docs for Const { |
@@ -567,6 +582,23 @@ impl Docs for Const { | |||
567 | } | 582 | } |
568 | } | 583 | } |
569 | 584 | ||
585 | /// The declared signature of a const. | ||
586 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
587 | pub struct ConstSignature { | ||
588 | pub(crate) name: Name, | ||
589 | pub(crate) type_ref: TypeRef, | ||
590 | } | ||
591 | |||
592 | impl ConstSignature { | ||
593 | pub fn name(&self) -> &Name { | ||
594 | &self.name | ||
595 | } | ||
596 | |||
597 | pub fn type_ref(&self) -> &TypeRef { | ||
598 | &self.type_ref | ||
599 | } | ||
600 | } | ||
601 | |||
570 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 602 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
571 | pub struct Static { | 603 | pub struct Static { |
572 | pub(crate) id: StaticId, | 604 | pub(crate) id: StaticId, |
@@ -580,6 +612,16 @@ impl Static { | |||
580 | pub fn module(&self, db: &impl PersistentHirDatabase) -> Module { | 612 | pub fn module(&self, db: &impl PersistentHirDatabase) -> Module { |
581 | self.id.module(db) | 613 | self.id.module(db) |
582 | } | 614 | } |
615 | |||
616 | pub fn signature(&self, db: &impl HirDatabase) -> Arc<ConstSignature> { | ||
617 | db.static_signature(*self) | ||
618 | } | ||
619 | |||
620 | /// Builds a resolver for code inside this item. | ||
621 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
622 | // take the outer scope... | ||
623 | self.module(db).resolver(db) | ||
624 | } | ||
583 | } | 625 | } |
584 | 626 | ||
585 | impl Docs for Static { | 627 | impl Docs for Static { |
diff --git a/crates/ra_hir/src/code_model_impl.rs b/crates/ra_hir/src/code_model_impl.rs index 1f28fab74..24df9a113 100644 --- a/crates/ra_hir/src/code_model_impl.rs +++ b/crates/ra_hir/src/code_model_impl.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | mod krate; // `crate` is invalid ident :( | 1 | mod krate; // `crate` is invalid ident :( |
2 | mod konst; // `const` is invalid ident :( | ||
2 | mod module; | 3 | mod module; |
3 | pub(crate) mod function; | 4 | pub(crate) mod function; |
diff --git a/crates/ra_hir/src/code_model_impl/konst.rs b/crates/ra_hir/src/code_model_impl/konst.rs new file mode 100644 index 000000000..ecf4c8122 --- /dev/null +++ b/crates/ra_hir/src/code_model_impl/konst.rs | |||
@@ -0,0 +1,37 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use ra_syntax::ast::{self, NameOwner}; | ||
4 | |||
5 | use crate::{ | ||
6 | Name, AsName, Const, ConstSignature, Static, | ||
7 | type_ref::{TypeRef}, | ||
8 | PersistentHirDatabase, | ||
9 | }; | ||
10 | |||
11 | fn const_signature_for<N: NameOwner>( | ||
12 | node: &N, | ||
13 | type_ref: Option<&ast::TypeRef>, | ||
14 | ) -> Arc<ConstSignature> { | ||
15 | let name = node.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); | ||
16 | let type_ref = TypeRef::from_ast_opt(type_ref); | ||
17 | let sig = ConstSignature { name, type_ref }; | ||
18 | Arc::new(sig) | ||
19 | } | ||
20 | |||
21 | impl ConstSignature { | ||
22 | pub(crate) fn const_signature_query( | ||
23 | db: &impl PersistentHirDatabase, | ||
24 | konst: Const, | ||
25 | ) -> Arc<ConstSignature> { | ||
26 | let (_, node) = konst.source(db); | ||
27 | const_signature_for(&*node, node.type_ref()) | ||
28 | } | ||
29 | |||
30 | pub(crate) fn static_signature_query( | ||
31 | db: &impl PersistentHirDatabase, | ||
32 | konst: Static, | ||
33 | ) -> Arc<ConstSignature> { | ||
34 | let (_, node) = konst.source(db); | ||
35 | const_signature_for(&*node, node.type_ref()) | ||
36 | } | ||
37 | } | ||
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index b8715abab..ec848f1b2 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -8,6 +8,7 @@ use crate::{ | |||
8 | SourceFileItems, SourceItemId, Crate, Module, HirInterner, | 8 | SourceFileItems, SourceItemId, Crate, Module, HirInterner, |
9 | Function, FnSignature, ExprScopes, TypeAlias, | 9 | Function, FnSignature, ExprScopes, TypeAlias, |
10 | Struct, Enum, StructField, | 10 | Struct, Enum, StructField, |
11 | Const, ConstSignature, Static, | ||
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}}, |
@@ -82,6 +83,12 @@ pub trait PersistentHirDatabase: SourceDatabase + AsRef<HirInterner> { | |||
82 | 83 | ||
83 | #[salsa::invoke(crate::type_alias::type_alias_ref_query)] | 84 | #[salsa::invoke(crate::type_alias::type_alias_ref_query)] |
84 | fn type_alias_ref(&self, typ: TypeAlias) -> Arc<TypeRef>; | 85 | fn type_alias_ref(&self, typ: TypeAlias) -> Arc<TypeRef>; |
86 | |||
87 | #[salsa::invoke(crate::ConstSignature::const_signature_query)] | ||
88 | fn const_signature(&self, konst: Const) -> Arc<ConstSignature>; | ||
89 | |||
90 | #[salsa::invoke(crate::ConstSignature::static_signature_query)] | ||
91 | fn static_signature(&self, konst: Static) -> Arc<ConstSignature>; | ||
85 | } | 92 | } |
86 | 93 | ||
87 | #[salsa::query_group(HirDatabaseStorage)] | 94 | #[salsa::query_group(HirDatabaseStorage)] |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index aa5fc5607..edc1b4f57 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -71,6 +71,6 @@ pub use self::code_model_api::{ | |||
71 | Struct, Enum, EnumVariant, | 71 | Struct, Enum, EnumVariant, |
72 | Function, FnSignature, | 72 | Function, FnSignature, |
73 | StructField, FieldSource, | 73 | StructField, FieldSource, |
74 | Static, Const, | 74 | Static, Const, ConstSignature, |
75 | Trait, TypeAlias, | 75 | Trait, TypeAlias, |
76 | }; | 76 | }; |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 921130b71..5e4d49ffb 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -393,17 +393,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
393 | // Attempt to find an impl_item for the type which has a name matching | 393 | // Attempt to find an impl_item for the type which has a name matching |
394 | // the current segment | 394 | // the current segment |
395 | log::debug!("looking for path segment: {:?}", segment); | 395 | log::debug!("looking for path segment: {:?}", segment); |
396 | let item = ty.iterate_impl_items(self.db, |item| match item { | 396 | let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| match item { |
397 | crate::ImplItem::Method(func) => { | 397 | crate::ImplItem::Method(func) => { |
398 | let sig = func.signature(self.db); | 398 | let sig = func.signature(self.db); |
399 | if segment.name == *sig.name() { | 399 | if segment.name == *sig.name() { |
400 | return Some(func); | 400 | return Some(func.into()); |
401 | } | 401 | } |
402 | None | 402 | None |
403 | } | 403 | } |
404 | 404 | ||
405 | // TODO: Resolve associated const | 405 | crate::ImplItem::Const(konst) => { |
406 | crate::ImplItem::Const(_) => None, | 406 | let sig = konst.signature(self.db); |
407 | if segment.name == *sig.name() { | ||
408 | return Some(konst.into()); | ||
409 | } | ||
410 | None | ||
411 | } | ||
407 | 412 | ||
408 | // TODO: Resolve associated types | 413 | // TODO: Resolve associated types |
409 | crate::ImplItem::TypeAlias(_) => None, | 414 | crate::ImplItem::TypeAlias(_) => None, |
@@ -477,9 +482,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
477 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 482 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
478 | (ty, Some(var.into())) | 483 | (ty, Some(var.into())) |
479 | } | 484 | } |
480 | TypableDef::TypeAlias(_) | TypableDef::Function(_) | TypableDef::Enum(_) => { | 485 | TypableDef::TypeAlias(_) |
481 | (Ty::Unknown, None) | 486 | | TypableDef::Function(_) |
482 | } | 487 | | TypableDef::Enum(_) |
488 | | TypableDef::Const(_) | ||
489 | | TypableDef::Static(_) => (Ty::Unknown, None), | ||
483 | } | 490 | } |
484 | } | 491 | } |
485 | 492 | ||
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index b66b8e4a5..f4e055feb 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -11,6 +11,7 @@ use std::sync::Arc; | |||
11 | use crate::{ | 11 | use crate::{ |
12 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, | 12 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, |
13 | ModuleDef, TypeAlias, | 13 | ModuleDef, TypeAlias, |
14 | Const, Static, | ||
14 | HirDatabase, | 15 | HirDatabase, |
15 | type_ref::TypeRef, | 16 | type_ref::TypeRef, |
16 | name::KnownName, | 17 | name::KnownName, |
@@ -125,6 +126,7 @@ impl Ty { | |||
125 | TypableDef::Enum(e) => e.generic_params(db), | 126 | TypableDef::Enum(e) => e.generic_params(db), |
126 | TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db), | 127 | TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db), |
127 | TypableDef::TypeAlias(t) => t.generic_params(db), | 128 | TypableDef::TypeAlias(t) => t.generic_params(db), |
129 | TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(), | ||
128 | }; | 130 | }; |
129 | let parent_param_count = def_generics.count_parent_params(); | 131 | let parent_param_count = def_generics.count_parent_params(); |
130 | substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); | 132 | substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); |
@@ -163,6 +165,8 @@ impl Ty { | |||
163 | TypableDef::Function(_) | 165 | TypableDef::Function(_) |
164 | | TypableDef::Struct(_) | 166 | | TypableDef::Struct(_) |
165 | | TypableDef::Enum(_) | 167 | | TypableDef::Enum(_) |
168 | | TypableDef::Const(_) | ||
169 | | TypableDef::Static(_) | ||
166 | | TypableDef::TypeAlias(_) => last, | 170 | | TypableDef::TypeAlias(_) => last, |
167 | TypableDef::EnumVariant(_) => { | 171 | TypableDef::EnumVariant(_) => { |
168 | // the generic args for an enum variant may be either specified | 172 | // the generic args for an enum variant may be either specified |
@@ -197,12 +201,16 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace | |||
197 | (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), | 201 | (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), |
198 | (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), | 202 | (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), |
199 | (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t), | 203 | (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t), |
204 | (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c), | ||
205 | (TypableDef::Static(c), Namespace::Values) => type_for_static(db, c), | ||
200 | 206 | ||
201 | // 'error' cases: | 207 | // 'error' cases: |
202 | (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, | 208 | (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, |
203 | (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, | 209 | (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, |
204 | (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, | 210 | (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, |
205 | (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown, | 211 | (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown, |
212 | (TypableDef::Const(_), Namespace::Types) => Ty::Unknown, | ||
213 | (TypableDef::Static(_), Namespace::Types) => Ty::Unknown, | ||
206 | } | 214 | } |
207 | } | 215 | } |
208 | 216 | ||
@@ -233,6 +241,22 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | |||
233 | Ty::FnDef { def: def.into(), sig, name, substs } | 241 | Ty::FnDef { def: def.into(), sig, name, substs } |
234 | } | 242 | } |
235 | 243 | ||
244 | /// Build the declared type of a const. | ||
245 | fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { | ||
246 | let signature = def.signature(db); | ||
247 | let resolver = def.resolver(db); | ||
248 | |||
249 | Ty::from_hir(db, &resolver, signature.type_ref()) | ||
250 | } | ||
251 | |||
252 | /// Build the declared type of a static. | ||
253 | fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { | ||
254 | let signature = def.signature(db); | ||
255 | let resolver = def.resolver(db); | ||
256 | |||
257 | Ty::from_hir(db, &resolver, signature.type_ref()) | ||
258 | } | ||
259 | |||
236 | /// Build the type of a tuple struct constructor. | 260 | /// Build the type of a tuple struct constructor. |
237 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | 261 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { |
238 | let var_data = def.variant_data(db); | 262 | let var_data = def.variant_data(db); |
@@ -318,8 +342,10 @@ pub enum TypableDef { | |||
318 | Enum(Enum), | 342 | Enum(Enum), |
319 | EnumVariant(EnumVariant), | 343 | EnumVariant(EnumVariant), |
320 | TypeAlias(TypeAlias), | 344 | TypeAlias(TypeAlias), |
345 | Const(Const), | ||
346 | Static(Static), | ||
321 | } | 347 | } |
322 | impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, TypeAlias); | 348 | impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, TypeAlias, Const, Static); |
323 | 349 | ||
324 | impl From<ModuleDef> for Option<TypableDef> { | 350 | impl From<ModuleDef> for Option<TypableDef> { |
325 | fn from(def: ModuleDef) -> Option<TypableDef> { | 351 | fn from(def: ModuleDef) -> Option<TypableDef> { |
@@ -329,10 +355,9 @@ impl From<ModuleDef> for Option<TypableDef> { | |||
329 | ModuleDef::Enum(e) => e.into(), | 355 | ModuleDef::Enum(e) => e.into(), |
330 | ModuleDef::EnumVariant(v) => v.into(), | 356 | ModuleDef::EnumVariant(v) => v.into(), |
331 | ModuleDef::TypeAlias(t) => t.into(), | 357 | ModuleDef::TypeAlias(t) => t.into(), |
332 | ModuleDef::Const(_) | 358 | ModuleDef::Const(v) => v.into(), |
333 | | ModuleDef::Static(_) | 359 | ModuleDef::Static(v) => v.into(), |
334 | | ModuleDef::Module(_) | 360 | ModuleDef::Module(_) | ModuleDef::Trait(_) => return None, |
335 | | ModuleDef::Trait(_) => return None, | ||
336 | }; | 361 | }; |
337 | Some(res) | 362 | Some(res) |
338 | } | 363 | } |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap index 131d1fa16..51f3fd4c0 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap | |||
@@ -1,14 +1,14 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-02-21T21:51:46.497925200Z" | 2 | created: "2019-02-25T08:36:33.885804400Z" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | source: crates/ra_hir/src/ty/tests.rs | 4 | source: crates/ra_hir/src/ty/tests.rs |
5 | expression: "&result" | 5 | expression: "&result" |
6 | --- | 6 | --- |
7 | [227; 305) '{ ...:ID; }': () | 7 | [227; 305) '{ ...:ID; }': () |
8 | [237; 238) 'x': [unknown] | 8 | [237; 238) 'x': u32 |
9 | [241; 252) 'Struct::FOO': [unknown] | 9 | [241; 252) 'Struct::FOO': u32 |
10 | [262; 263) 'y': [unknown] | 10 | [262; 263) 'y': u32 |
11 | [266; 275) 'Enum::BAR': [unknown] | 11 | [266; 275) 'Enum::BAR': u32 |
12 | [285; 286) 'z': [unknown] | 12 | [285; 286) 'z': u32 |
13 | [289; 302) 'TraitTest::ID': [unknown] | 13 | [289; 302) 'TraitTest::ID': u32 |
14 | 14 | ||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_const.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_const.snap new file mode 100644 index 000000000..a5eba3980 --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_const.snap | |||
@@ -0,0 +1,14 @@ | |||
1 | --- | ||
2 | created: "2019-02-25T07:26:34.115351100Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [95; 213) '{ ...NST; }': () | ||
8 | [138; 139) 'x': [unknown] | ||
9 | [142; 153) 'LOCAL_CONST': [unknown] | ||
10 | [163; 164) 'z': u32 | ||
11 | [167; 179) 'GLOBAL_CONST': u32 | ||
12 | [189; 191) 'id': u32 | ||
13 | [194; 210) 'Foo::A..._CONST': u32 | ||
14 | |||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_static.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_static.snap new file mode 100644 index 000000000..5d90f56ed --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_static.snap | |||
@@ -0,0 +1,16 @@ | |||
1 | --- | ||
2 | created: "2019-02-25T08:20:17.807316Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [85; 280) '{ ...MUT; }': () | ||
8 | [173; 174) 'x': [unknown] | ||
9 | [177; 189) 'LOCAL_STATIC': [unknown] | ||
10 | [199; 200) 'y': [unknown] | ||
11 | [203; 219) 'LOCAL_...IC_MUT': [unknown] | ||
12 | [229; 230) 'z': u32 | ||
13 | [233; 246) 'GLOBAL_STATIC': u32 | ||
14 | [256; 257) 'w': u32 | ||
15 | [260; 277) 'GLOBAL...IC_MUT': u32 | ||
16 | |||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 642259225..8de46a29e 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -1006,6 +1006,43 @@ mod foo { | |||
1006 | assert_eq!("i128", type_at_pos(&db, pos)); | 1006 | assert_eq!("i128", type_at_pos(&db, pos)); |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | #[test] | ||
1010 | fn infer_const() { | ||
1011 | check_inference( | ||
1012 | "infer_const", | ||
1013 | r#" | ||
1014 | struct Foo; | ||
1015 | impl Foo { const ASSOC_CONST: u32 = 0; } | ||
1016 | const GLOBAL_CONST: u32 = 101; | ||
1017 | fn test() { | ||
1018 | const LOCAL_CONST: u32 = 99; | ||
1019 | let x = LOCAL_CONST; | ||
1020 | let z = GLOBAL_CONST; | ||
1021 | let id = Foo::ASSOC_CONST; | ||
1022 | } | ||
1023 | "#, | ||
1024 | ); | ||
1025 | } | ||
1026 | |||
1027 | #[test] | ||
1028 | fn infer_static() { | ||
1029 | check_inference( | ||
1030 | "infer_static", | ||
1031 | r#" | ||
1032 | static GLOBAL_STATIC: u32 = 101; | ||
1033 | static mut GLOBAL_STATIC_MUT: u32 = 101; | ||
1034 | fn test() { | ||
1035 | static LOCAL_STATIC: u32 = 99; | ||
1036 | static mut LOCAL_STATIC_MUT: u32 = 99; | ||
1037 | let x = LOCAL_STATIC; | ||
1038 | let y = LOCAL_STATIC_MUT; | ||
1039 | let z = GLOBAL_STATIC; | ||
1040 | let w = GLOBAL_STATIC_MUT; | ||
1041 | } | ||
1042 | "#, | ||
1043 | ); | ||
1044 | } | ||
1045 | |||
1009 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 1046 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
1010 | let func = source_binder::function_from_position(db, pos).unwrap(); | 1047 | let func = source_binder::function_from_position(db, pos).unwrap(); |
1011 | let body_syntax_mapping = func.body_syntax_mapping(db); | 1048 | let body_syntax_mapping = func.body_syntax_mapping(db); |