diff options
author | Aleksey Kladov <[email protected]> | 2019-11-26 11:02:57 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-11-26 11:02:57 +0000 |
commit | e5eadb339039e21718d382c0b3d02a4bf053b3f4 (patch) | |
tree | 2f7839288ce5676a89c6d6062cbaf70544e0beed /crates | |
parent | 5901cc736074bbc4d780a8e45079d405ab2cec4b (diff) |
Introduce hir::Type
It should provide a convenient API over more low-level Ty
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/assists/add_explicit_type.rs | 13 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/fill_match_arms.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 166 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 46 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 36 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_postfix.rs | 16 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_record_literal.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_record_pattern.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/presentation.rs | 39 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_type_definition.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/inlay_hints.rs | 23 | ||||
-rw-r--r-- | crates/ra_ide_api/src/syntax_highlighting.rs | 9 |
15 files changed, 253 insertions, 136 deletions
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs index 562a09685..eeb4ff39f 100644 --- a/crates/ra_assists/src/assists/add_explicit_type.rs +++ b/crates/ra_assists/src/assists/add_explicit_type.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{db::HirDatabase, HirDisplay, Ty}; | 1 | use hir::{db::HirDatabase, HirDisplay}; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | ast::{self, AstNode, LetStmt, NameOwner}, | 3 | ast::{self, AstNode, LetStmt, NameOwner}, |
4 | T, | 4 | T, |
@@ -43,7 +43,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi | |||
43 | let analyzer = ctx.source_analyzer(stmt.syntax(), None); | 43 | let analyzer = ctx.source_analyzer(stmt.syntax(), None); |
44 | let ty = analyzer.type_of(db, &expr)?; | 44 | let ty = analyzer.type_of(db, &expr)?; |
45 | // Assist not applicable if the type is unknown | 45 | // Assist not applicable if the type is unknown |
46 | if is_unknown(&ty) { | 46 | if ty.contains_unknown() { |
47 | return None; | 47 | return None; |
48 | } | 48 | } |
49 | 49 | ||
@@ -53,15 +53,6 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi | |||
53 | }) | 53 | }) |
54 | } | 54 | } |
55 | 55 | ||
56 | /// Returns true if any type parameter is unknown | ||
57 | fn is_unknown(ty: &Ty) -> bool { | ||
58 | match ty { | ||
59 | Ty::Unknown => true, | ||
60 | Ty::Apply(a_ty) => a_ty.parameters.iter().any(is_unknown), | ||
61 | _ => false, | ||
62 | } | ||
63 | } | ||
64 | |||
65 | #[cfg(test)] | 56 | #[cfg(test)] |
66 | mod tests { | 57 | mod tests { |
67 | use super::*; | 58 | use super::*; |
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs index 8482897c5..b75bd44eb 100644 --- a/crates/ra_assists/src/assists/fill_match_arms.rs +++ b/crates/ra_assists/src/assists/fill_match_arms.rs | |||
@@ -83,10 +83,11 @@ fn resolve_enum_def( | |||
83 | ) -> Option<ast::EnumDef> { | 83 | ) -> Option<ast::EnumDef> { |
84 | let expr_ty = analyzer.type_of(db, &expr)?; | 84 | let expr_ty = analyzer.type_of(db, &expr)?; |
85 | 85 | ||
86 | analyzer.autoderef(db, expr_ty).find_map(|ty| match ty.as_adt() { | 86 | let res = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() { |
87 | Some((Adt::Enum(e), _)) => Some(e.source(db).value), | 87 | Some(Adt::Enum(e)) => Some(e.source(db).value), |
88 | _ => None, | 88 | _ => None, |
89 | }) | 89 | }); |
90 | res | ||
90 | } | 91 | } |
91 | 92 | ||
92 | fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> { | 93 | fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> { |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index f7fc80d4e..a7bba85e1 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -10,9 +10,9 @@ use hir_def::{ | |||
10 | docs::Documentation, | 10 | docs::Documentation, |
11 | per_ns::PerNs, | 11 | per_ns::PerNs, |
12 | resolver::{HasResolver, TypeNs}, | 12 | resolver::{HasResolver, TypeNs}, |
13 | type_ref::TypeRef, | 13 | type_ref::{Mutability, TypeRef}, |
14 | AstItemDef, ConstId, ContainerId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, | 14 | AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, |
15 | LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, | 15 | ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, |
16 | StaticId, StructId, TraitId, TypeAliasId, UnionId, | 16 | StaticId, StructId, TraitId, TypeAliasId, UnionId, |
17 | }; | 17 | }; |
18 | use hir_expand::{ | 18 | use hir_expand::{ |
@@ -26,8 +26,12 @@ use ra_syntax::{ast, AstNode, SyntaxNode}; | |||
26 | use crate::{ | 26 | use crate::{ |
27 | db::{DefDatabase, HirDatabase}, | 27 | db::{DefDatabase, HirDatabase}, |
28 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, | 28 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, |
29 | ty::{InferenceResult, Namespace, TraitRef}, | 29 | ty::display::HirFormatter, |
30 | Either, Name, Source, Ty, | 30 | ty::{ |
31 | self, InEnvironment, InferenceResult, Namespace, TraitEnvironment, TraitRef, Ty, TypeCtor, | ||
32 | TypeWalk, | ||
33 | }, | ||
34 | CallableDef, Either, HirDisplay, Name, Source, | ||
31 | }; | 35 | }; |
32 | 36 | ||
33 | /// hir::Crate describes a single crate. It's the main interface with which | 37 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -469,6 +473,10 @@ pub enum Adt { | |||
469 | impl_froms!(Adt: Struct, Union, Enum); | 473 | impl_froms!(Adt: Struct, Union, Enum); |
470 | 474 | ||
471 | impl Adt { | 475 | impl Adt { |
476 | pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool { | ||
477 | let subst = db.generic_defaults(self.into()); | ||
478 | subst.iter().any(|ty| ty == &Ty::Unknown) | ||
479 | } | ||
472 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 480 | pub fn ty(self, db: &impl HirDatabase) -> Ty { |
473 | match self { | 481 | match self { |
474 | Adt::Struct(it) => it.ty(db), | 482 | Adt::Struct(it) => it.ty(db), |
@@ -777,6 +785,11 @@ pub struct TypeAlias { | |||
777 | } | 785 | } |
778 | 786 | ||
779 | impl TypeAlias { | 787 | impl TypeAlias { |
788 | pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool { | ||
789 | let subst = db.generic_defaults(self.id.into()); | ||
790 | subst.iter().any(|ty| ty == &Ty::Unknown) | ||
791 | } | ||
792 | |||
780 | pub fn module(self, db: &impl DefDatabase) -> Module { | 793 | pub fn module(self, db: &impl DefDatabase) -> Module { |
781 | Module { id: self.id.lookup(db).module(db) } | 794 | Module { id: self.id.lookup(db).module(db) } |
782 | } | 795 | } |
@@ -927,9 +940,14 @@ impl Local { | |||
927 | self.parent.module(db) | 940 | self.parent.module(db) |
928 | } | 941 | } |
929 | 942 | ||
930 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 943 | pub fn ty(self, db: &impl HirDatabase) -> Type { |
931 | let infer = db.infer(self.parent); | 944 | let infer = db.infer(self.parent); |
932 | infer[self.pat_id].clone() | 945 | let ty = infer[self.pat_id].clone(); |
946 | let def = DefWithBodyId::from(self.parent); | ||
947 | let resolver = def.resolver(db); | ||
948 | let krate = def.module(db).krate; | ||
949 | let environment = TraitEnvironment::lower(db, &resolver); | ||
950 | Type { krate, ty: InEnvironment { value: ty, environment } } | ||
933 | } | 951 | } |
934 | 952 | ||
935 | pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { | 953 | pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { |
@@ -986,6 +1004,140 @@ impl ImplBlock { | |||
986 | } | 1004 | } |
987 | } | 1005 | } |
988 | 1006 | ||
1007 | #[derive(Clone, PartialEq, Eq)] | ||
1008 | pub struct Type { | ||
1009 | pub(crate) krate: CrateId, | ||
1010 | pub(crate) ty: InEnvironment<Ty>, | ||
1011 | } | ||
1012 | |||
1013 | impl Type { | ||
1014 | pub fn is_bool(&self) -> bool { | ||
1015 | match &self.ty.value { | ||
1016 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
1017 | TypeCtor::Bool => true, | ||
1018 | _ => false, | ||
1019 | }, | ||
1020 | _ => false, | ||
1021 | } | ||
1022 | } | ||
1023 | |||
1024 | pub fn is_mutable_reference(&self) -> bool { | ||
1025 | match &self.ty.value { | ||
1026 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
1027 | TypeCtor::Ref(Mutability::Mut) => true, | ||
1028 | _ => false, | ||
1029 | }, | ||
1030 | _ => false, | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | pub fn is_unknown(&self) -> bool { | ||
1035 | match &self.ty.value { | ||
1036 | Ty::Unknown => true, | ||
1037 | _ => false, | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | // FIXME: this method is broken, as it doesn't take closures into account. | ||
1042 | pub fn as_callable(&self) -> Option<CallableDef> { | ||
1043 | Some(self.ty.value.as_callable()?.0) | ||
1044 | } | ||
1045 | |||
1046 | pub fn contains_unknown(&self) -> bool { | ||
1047 | return go(&self.ty.value); | ||
1048 | |||
1049 | fn go(ty: &Ty) -> bool { | ||
1050 | match ty { | ||
1051 | Ty::Unknown => true, | ||
1052 | Ty::Apply(a_ty) => a_ty.parameters.iter().any(go), | ||
1053 | _ => false, | ||
1054 | } | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<(StructField, Type)> { | ||
1059 | let mut res = Vec::new(); | ||
1060 | if let Ty::Apply(a_ty) = &self.ty.value { | ||
1061 | match a_ty.ctor { | ||
1062 | ty::TypeCtor::Adt(Adt::Struct(s)) => { | ||
1063 | for field in s.fields(db) { | ||
1064 | let ty = field.ty(db).subst(&a_ty.parameters); | ||
1065 | res.push((field, self.derived(ty))); | ||
1066 | } | ||
1067 | } | ||
1068 | _ => {} | ||
1069 | } | ||
1070 | }; | ||
1071 | res | ||
1072 | } | ||
1073 | |||
1074 | pub fn tuple_fields(&self, _db: &impl HirDatabase) -> Vec<Type> { | ||
1075 | let mut res = Vec::new(); | ||
1076 | if let Ty::Apply(a_ty) = &self.ty.value { | ||
1077 | match a_ty.ctor { | ||
1078 | ty::TypeCtor::Tuple { .. } => { | ||
1079 | for ty in a_ty.parameters.iter() { | ||
1080 | let ty = ty.clone().subst(&a_ty.parameters); | ||
1081 | res.push(self.derived(ty)); | ||
1082 | } | ||
1083 | } | ||
1084 | _ => {} | ||
1085 | } | ||
1086 | }; | ||
1087 | res | ||
1088 | } | ||
1089 | |||
1090 | pub fn variant_fields( | ||
1091 | &self, | ||
1092 | db: &impl HirDatabase, | ||
1093 | def: VariantDef, | ||
1094 | ) -> Vec<(StructField, Type)> { | ||
1095 | // FIXME: check that ty and def match | ||
1096 | match &self.ty.value { | ||
1097 | Ty::Apply(a_ty) => def | ||
1098 | .fields(db) | ||
1099 | .into_iter() | ||
1100 | .map(|it| (it, self.derived(it.ty(db).subst(&a_ty.parameters)))) | ||
1101 | .collect(), | ||
1102 | _ => Vec::new(), | ||
1103 | } | ||
1104 | } | ||
1105 | |||
1106 | pub fn autoderef<'a>(&'a self, db: &'a impl HirDatabase) -> impl Iterator<Item = Type> + 'a { | ||
1107 | // There should be no inference vars in types passed here | ||
1108 | // FIXME check that? | ||
1109 | let canonical = crate::ty::Canonical { value: self.ty.value.clone(), num_vars: 0 }; | ||
1110 | let environment = self.ty.environment.clone(); | ||
1111 | let ty = InEnvironment { value: canonical, environment: environment.clone() }; | ||
1112 | ty::autoderef(db, Some(self.krate), ty) | ||
1113 | .map(|canonical| canonical.value) | ||
1114 | .map(move |ty| self.derived(ty)) | ||
1115 | } | ||
1116 | |||
1117 | // FIXME: remove | ||
1118 | pub fn into_ty(self) -> Ty { | ||
1119 | self.ty.value | ||
1120 | } | ||
1121 | |||
1122 | pub fn as_adt(&self) -> Option<Adt> { | ||
1123 | let (adt, _subst) = self.ty.value.as_adt()?; | ||
1124 | Some(adt) | ||
1125 | } | ||
1126 | |||
1127 | fn derived(&self, ty: Ty) -> Type { | ||
1128 | Type { | ||
1129 | krate: self.krate, | ||
1130 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | ||
1131 | } | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | impl HirDisplay for Type { | ||
1136 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> std::fmt::Result { | ||
1137 | self.ty.value.hir_fmt(f) | ||
1138 | } | ||
1139 | } | ||
1140 | |||
989 | /// For IDE only | 1141 | /// For IDE only |
990 | pub enum ScopeDef { | 1142 | pub enum ScopeDef { |
991 | ModuleDef(ModuleDef), | 1143 | ModuleDef(ModuleDef), |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 843ce6a88..b88e4c745 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -51,7 +51,7 @@ pub use crate::{ | |||
51 | src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, | 51 | src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, |
52 | DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam, | 52 | DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam, |
53 | HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, | 53 | HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, |
54 | Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, | 54 | Static, Struct, StructField, Trait, Type, TypeAlias, Union, VariantDef, |
55 | }, | 55 | }, |
56 | expr::ExprScopes, | 56 | expr::ExprScopes, |
57 | from_source::FromSource, | 57 | from_source::FromSource, |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index cbfeca3ab..95a94c3f0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -28,10 +28,10 @@ use crate::{ | |||
28 | expr::{BodySourceMap, ExprScopes, ScopeId}, | 28 | expr::{BodySourceMap, ExprScopes, ScopeId}, |
29 | ty::{ | 29 | ty::{ |
30 | method_resolution::{self, implements_trait}, | 30 | method_resolution::{self, implements_trait}, |
31 | TraitEnvironment, | 31 | InEnvironment, TraitEnvironment, Ty, |
32 | }, | 32 | }, |
33 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, | 33 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, |
34 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias, | 34 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { | 37 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { |
@@ -198,14 +198,18 @@ impl SourceAnalyzer { | |||
198 | self.body_source_map.as_ref()?.node_pat(src) | 198 | self.body_source_map.as_ref()?.node_pat(src) |
199 | } | 199 | } |
200 | 200 | ||
201 | pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { | 201 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { |
202 | let expr_id = self.expr_id(expr)?; | 202 | let expr_id = self.expr_id(expr)?; |
203 | Some(self.infer.as_ref()?[expr_id].clone()) | 203 | let ty = self.infer.as_ref()?[expr_id].clone(); |
204 | let environment = TraitEnvironment::lower(db, &self.resolver); | ||
205 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | ||
204 | } | 206 | } |
205 | 207 | ||
206 | pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { | 208 | pub fn type_of_pat(&self, db: &impl HirDatabase, pat: &ast::Pat) -> Option<Type> { |
207 | let pat_id = self.pat_id(pat)?; | 209 | let pat_id = self.pat_id(pat)?; |
208 | Some(self.infer.as_ref()?[pat_id].clone()) | 210 | let ty = self.infer.as_ref()?[pat_id].clone(); |
211 | let environment = TraitEnvironment::lower(db, &self.resolver); | ||
212 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | ||
209 | } | 213 | } |
210 | 214 | ||
211 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 215 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |
@@ -361,14 +365,14 @@ impl SourceAnalyzer { | |||
361 | pub fn iterate_method_candidates<T>( | 365 | pub fn iterate_method_candidates<T>( |
362 | &self, | 366 | &self, |
363 | db: &impl HirDatabase, | 367 | db: &impl HirDatabase, |
364 | ty: Ty, | 368 | ty: &Type, |
365 | name: Option<&Name>, | 369 | name: Option<&Name>, |
366 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 370 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
367 | ) -> Option<T> { | 371 | ) -> Option<T> { |
368 | // There should be no inference vars in types passed here | 372 | // There should be no inference vars in types passed here |
369 | // FIXME check that? | 373 | // FIXME check that? |
370 | // FIXME replace Unknown by bound vars here | 374 | // FIXME replace Unknown by bound vars here |
371 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 375 | let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 }; |
372 | method_resolution::iterate_method_candidates( | 376 | method_resolution::iterate_method_candidates( |
373 | &canonical, | 377 | &canonical, |
374 | db, | 378 | db, |
@@ -403,19 +407,19 @@ impl SourceAnalyzer { | |||
403 | ) | 407 | ) |
404 | } | 408 | } |
405 | 409 | ||
406 | pub fn autoderef<'a>( | 410 | // pub fn autoderef<'a>( |
407 | &'a self, | 411 | // &'a self, |
408 | db: &'a impl HirDatabase, | 412 | // db: &'a impl HirDatabase, |
409 | ty: Ty, | 413 | // ty: Ty, |
410 | ) -> impl Iterator<Item = Ty> + 'a { | 414 | // ) -> impl Iterator<Item = Ty> + 'a { |
411 | // There should be no inference vars in types passed here | 415 | // // There should be no inference vars in types passed here |
412 | // FIXME check that? | 416 | // // FIXME check that? |
413 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 417 | // let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; |
414 | let krate = self.resolver.krate(); | 418 | // let krate = self.resolver.krate(); |
415 | let environment = TraitEnvironment::lower(db, &self.resolver); | 419 | // let environment = TraitEnvironment::lower(db, &self.resolver); |
416 | let ty = crate::ty::InEnvironment { value: canonical, environment }; | 420 | // let ty = crate::ty::InEnvironment { value: canonical, environment }; |
417 | crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) | 421 | // crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) |
418 | } | 422 | // } |
419 | 423 | ||
420 | /// Checks that particular type `ty` implements `std::future::Future`. | 424 | /// Checks that particular type `ty` implements `std::future::Future`. |
421 | /// This function is used in `.await` syntax completion. | 425 | /// This function is used in `.await` syntax completion. |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index a88a78b38..274dd1467 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -489,6 +489,16 @@ impl HasModule for AdtId { | |||
489 | } | 489 | } |
490 | } | 490 | } |
491 | 491 | ||
492 | impl HasModule for DefWithBodyId { | ||
493 | fn module(&self, db: &impl db::DefDatabase) -> ModuleId { | ||
494 | match self { | ||
495 | DefWithBodyId::FunctionId(it) => it.lookup(db).module(db), | ||
496 | DefWithBodyId::StaticId(it) => it.lookup(db).module(db), | ||
497 | DefWithBodyId::ConstId(it) => it.lookup(db).module(db), | ||
498 | } | ||
499 | } | ||
500 | } | ||
501 | |||
492 | impl HasModule for StaticLoc { | 502 | impl HasModule for StaticLoc { |
493 | fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { | 503 | fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { |
494 | self.container | 504 | self.container |
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index 9beceb29c..d0283e410 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -26,8 +26,8 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
26 | ); | 26 | ); |
27 | let (mut call_info, has_self) = match &calling_node { | 27 | let (mut call_info, has_self) = match &calling_node { |
28 | FnCallNode::CallExpr(expr) => { | 28 | FnCallNode::CallExpr(expr) => { |
29 | //FIXME: don't poke into Ty | 29 | //FIXME: Type::as_callable is broken |
30 | let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; | 30 | let callable_def = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; |
31 | match callable_def { | 31 | match callable_def { |
32 | hir::CallableDef::FunctionId(it) => { | 32 | hir::CallableDef::FunctionId(it) => { |
33 | let fn_def = it.into(); | 33 | let fn_def = it.into(); |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 5a3f9b5f6..b6fe48627 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{Adt, Ty, TypeCtor}; | 3 | use hir::Type; |
4 | 4 | ||
5 | use crate::completion::completion_item::CompletionKind; | 5 | use crate::completion::completion_item::CompletionKind; |
6 | use crate::{ | 6 | use crate::{ |
@@ -22,12 +22,12 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
22 | }; | 22 | }; |
23 | 23 | ||
24 | if !ctx.is_call { | 24 | if !ctx.is_call { |
25 | complete_fields(acc, ctx, receiver_ty.clone()); | 25 | complete_fields(acc, ctx, &receiver_ty); |
26 | } | 26 | } |
27 | complete_methods(acc, ctx, receiver_ty.clone()); | 27 | complete_methods(acc, ctx, &receiver_ty); |
28 | 28 | ||
29 | // Suggest .await syntax for types that implement Future trait | 29 | // Suggest .await syntax for types that implement Future trait |
30 | if ctx.analyzer.impls_future(ctx.db, receiver_ty) { | 30 | if ctx.analyzer.impls_future(ctx.db, receiver_ty.into_ty()) { |
31 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") | 31 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") |
32 | .detail("expr.await") | 32 | .detail("expr.await") |
33 | .insert_text("await") | 33 | .insert_text("await") |
@@ -35,28 +35,18 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
38 | fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { | 38 | fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { |
39 | for receiver in ctx.analyzer.autoderef(ctx.db, receiver) { | 39 | for receiver in receiver.autoderef(ctx.db) { |
40 | if let Ty::Apply(a_ty) = receiver { | 40 | for (field, ty) in receiver.fields(ctx.db) { |
41 | match a_ty.ctor { | 41 | acc.add_field(ctx, field, &ty); |
42 | TypeCtor::Adt(Adt::Struct(s)) => { | 42 | } |
43 | for field in s.fields(ctx.db) { | 43 | for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() { |
44 | acc.add_field(ctx, field, &a_ty.parameters); | 44 | acc.add_tuple_field(ctx, i, &ty); |
45 | } | 45 | } |
46 | } | ||
47 | // FIXME unions | ||
48 | TypeCtor::Tuple { .. } => { | ||
49 | for (i, ty) in a_ty.parameters.iter().enumerate() { | ||
50 | acc.add_tuple_field(ctx, i, ty); | ||
51 | } | ||
52 | } | ||
53 | _ => {} | ||
54 | } | ||
55 | }; | ||
56 | } | 46 | } |
57 | } | 47 | } |
58 | 48 | ||
59 | fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { | 49 | fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { |
60 | let mut seen_methods = FxHashSet::default(); | 50 | let mut seen_methods = FxHashSet::default(); |
61 | ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { | 51 | ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { |
62 | if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { | 52 | if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { |
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs index 17b75cf7e..646a30c76 100644 --- a/crates/ra_ide_api/src/completion/complete_postfix.rs +++ b/crates/ra_ide_api/src/completion/complete_postfix.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{Ty, TypeCtor}; | ||
4 | use ra_syntax::{ast::AstNode, TextRange, TextUnit}; | 3 | use ra_syntax::{ast::AstNode, TextRange, TextUnit}; |
5 | use ra_text_edit::TextEdit; | 4 | use ra_text_edit::TextEdit; |
6 | 5 | ||
@@ -30,9 +29,12 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
30 | dot_receiver.syntax().text().to_string() | 29 | dot_receiver.syntax().text().to_string() |
31 | }; | 30 | }; |
32 | 31 | ||
33 | let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver); | 32 | let receiver_ty = match ctx.analyzer.type_of(ctx.db, &dot_receiver) { |
33 | Some(it) => it, | ||
34 | None => return, | ||
35 | }; | ||
34 | 36 | ||
35 | if is_bool_or_unknown(receiver_ty) { | 37 | if receiver_ty.is_bool() || receiver_ty.is_unknown() { |
36 | postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text)) | 38 | postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text)) |
37 | .add_to(acc); | 39 | .add_to(acc); |
38 | postfix_snippet( | 40 | postfix_snippet( |
@@ -75,14 +77,6 @@ fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: | |||
75 | .snippet_edit(edit) | 77 | .snippet_edit(edit) |
76 | } | 78 | } |
77 | 79 | ||
78 | fn is_bool_or_unknown(ty: Option<Ty>) -> bool { | ||
79 | match &ty { | ||
80 | Some(Ty::Apply(app)) if app.ctor == TypeCtor::Bool => true, | ||
81 | Some(Ty::Unknown) | None => true, | ||
82 | Some(_) => false, | ||
83 | } | ||
84 | } | ||
85 | |||
86 | #[cfg(test)] | 80 | #[cfg(test)] |
87 | mod tests { | 81 | mod tests { |
88 | use insta::assert_debug_snapshot; | 82 | use insta::assert_debug_snapshot; |
diff --git a/crates/ra_ide_api/src/completion/complete_record_literal.rs b/crates/ra_ide_api/src/completion/complete_record_literal.rs index 45a4a9738..577c394d2 100644 --- a/crates/ra_ide_api/src/completion/complete_record_literal.rs +++ b/crates/ra_ide_api/src/completion/complete_record_literal.rs | |||
@@ -1,7 +1,5 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::Substs; | ||
4 | |||
5 | use crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
6 | 4 | ||
7 | /// Complete fields in fields literals. | 5 | /// Complete fields in fields literals. |
@@ -15,10 +13,9 @@ pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionCon | |||
15 | Some(it) => it, | 13 | Some(it) => it, |
16 | _ => return, | 14 | _ => return, |
17 | }; | 15 | }; |
18 | let substs = &ty.substs().unwrap_or_else(Substs::empty); | ||
19 | 16 | ||
20 | for field in variant.fields(ctx.db) { | 17 | for (field, field_ty) in ty.variant_fields(ctx.db, variant) { |
21 | acc.add_field(ctx, field, substs); | 18 | acc.add_field(ctx, field, &field_ty); |
22 | } | 19 | } |
23 | } | 20 | } |
24 | 21 | ||
diff --git a/crates/ra_ide_api/src/completion/complete_record_pattern.rs b/crates/ra_ide_api/src/completion/complete_record_pattern.rs index aa0fd6d24..a56c7e3a1 100644 --- a/crates/ra_ide_api/src/completion/complete_record_pattern.rs +++ b/crates/ra_ide_api/src/completion/complete_record_pattern.rs | |||
@@ -1,7 +1,5 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::Substs; | ||
4 | |||
5 | use crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
6 | 4 | ||
7 | pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) { | 5 | pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) { |
@@ -14,10 +12,9 @@ pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionCon | |||
14 | Some(it) => it, | 12 | Some(it) => it, |
15 | _ => return, | 13 | _ => return, |
16 | }; | 14 | }; |
17 | let substs = &ty.substs().unwrap_or_else(Substs::empty); | ||
18 | 15 | ||
19 | for field in variant.fields(ctx.db) { | 16 | for (field, field_ty) in ty.variant_fields(ctx.db, variant) { |
20 | acc.add_field(ctx, field, substs); | 17 | acc.add_field(ctx, field, &field_ty); |
21 | } | 18 | } |
22 | } | 19 | } |
23 | 20 | ||
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index 85b053a6e..5f056730a 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | //! This modules takes care of rendering various definitions as completion items. | 1 | //! This modules takes care of rendering various definitions as completion items. |
2 | 2 | ||
3 | use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; | 3 | use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Type}; |
4 | use join_to_string::join; | 4 | use join_to_string::join; |
5 | use ra_syntax::ast::NameOwner; | 5 | use ra_syntax::ast::NameOwner; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
7 | 7 | ||
8 | use crate::completion::{ | 8 | use crate::completion::{ |
9 | db, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | 9 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::display::{const_label, function_label, macro_label, type_label}; | 12 | use crate::display::{const_label, function_label, macro_label, type_label}; |
@@ -16,7 +16,7 @@ impl Completions { | |||
16 | &mut self, | 16 | &mut self, |
17 | ctx: &CompletionContext, | 17 | ctx: &CompletionContext, |
18 | field: hir::StructField, | 18 | field: hir::StructField, |
19 | substs: &hir::Substs, | 19 | ty: &Type, |
20 | ) { | 20 | ) { |
21 | let is_deprecated = is_deprecated(field, ctx.db); | 21 | let is_deprecated = is_deprecated(field, ctx.db); |
22 | CompletionItem::new( | 22 | CompletionItem::new( |
@@ -25,13 +25,13 @@ impl Completions { | |||
25 | field.name(ctx.db).to_string(), | 25 | field.name(ctx.db).to_string(), |
26 | ) | 26 | ) |
27 | .kind(CompletionItemKind::Field) | 27 | .kind(CompletionItemKind::Field) |
28 | .detail(field.ty(ctx.db).subst(substs).display(ctx.db).to_string()) | 28 | .detail(ty.display(ctx.db).to_string()) |
29 | .set_documentation(field.docs(ctx.db)) | 29 | .set_documentation(field.docs(ctx.db)) |
30 | .set_deprecated(is_deprecated) | 30 | .set_deprecated(is_deprecated) |
31 | .add_to(self); | 31 | .add_to(self); |
32 | } | 32 | } |
33 | 33 | ||
34 | pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &hir::Ty) { | 34 | pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &Type) { |
35 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), field.to_string()) | 35 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), field.to_string()) |
36 | .kind(CompletionItemKind::Field) | 36 | .kind(CompletionItemKind::Field) |
37 | .detail(ty.display(ctx.db).to_string()) | 37 | .detail(ty.display(ctx.db).to_string()) |
@@ -98,7 +98,7 @@ impl Completions { | |||
98 | CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone()); | 98 | CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone()); |
99 | if let ScopeDef::Local(local) = resolution { | 99 | if let ScopeDef::Local(local) = resolution { |
100 | let ty = local.ty(ctx.db); | 100 | let ty = local.ty(ctx.db); |
101 | if ty != Ty::Unknown { | 101 | if !ty.is_unknown() { |
102 | completion_item = completion_item.detail(ty.display(ctx.db).to_string()); | 102 | completion_item = completion_item.detail(ty.display(ctx.db).to_string()); |
103 | } | 103 | } |
104 | }; | 104 | }; |
@@ -108,19 +108,17 @@ impl Completions { | |||
108 | && !ctx.has_type_args | 108 | && !ctx.has_type_args |
109 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") | 109 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") |
110 | { | 110 | { |
111 | let generic_def: Option<hir::GenericDef> = match resolution { | 111 | let has_non_default_type_params = match resolution { |
112 | ScopeDef::ModuleDef(Adt(it)) => Some((*it).into()), | 112 | ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db), |
113 | ScopeDef::ModuleDef(TypeAlias(it)) => Some((*it).into()), | 113 | ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db), |
114 | _ => None, | 114 | _ => false, |
115 | }; | 115 | }; |
116 | if let Some(def) = generic_def { | 116 | if has_non_default_type_params { |
117 | if has_non_default_type_params(def, ctx.db) { | 117 | tested_by!(inserts_angle_brackets_for_generics); |
118 | tested_by!(inserts_angle_brackets_for_generics); | 118 | completion_item = completion_item |
119 | completion_item = completion_item | 119 | .lookup_by(local_name.clone()) |
120 | .lookup_by(local_name.clone()) | 120 | .label(format!("{}<…>", local_name)) |
121 | .label(format!("{}<…>", local_name)) | 121 | .insert_snippet(format!("{}<$0>", local_name)); |
122 | .insert_snippet(format!("{}<$0>", local_name)); | ||
123 | } | ||
124 | } | 122 | } |
125 | } | 123 | } |
126 | 124 | ||
@@ -291,11 +289,6 @@ fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool { | |||
291 | node.attrs(db).by_key("deprecated").exists() | 289 | node.attrs(db).by_key("deprecated").exists() |
292 | } | 290 | } |
293 | 291 | ||
294 | fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { | ||
295 | let subst = db.generic_defaults(def.into()); | ||
296 | subst.iter().any(|ty| ty == &Ty::Unknown) | ||
297 | } | ||
298 | |||
299 | #[cfg(test)] | 292 | #[cfg(test)] |
300 | mod tests { | 293 | mod tests { |
301 | use insta::assert_debug_snapshot; | 294 | use insta::assert_debug_snapshot; |
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs index 28a83a3e2..992a08809 100644 --- a/crates/ra_ide_api/src/goto_type_definition.rs +++ b/crates/ra_ide_api/src/goto_type_definition.rs | |||
@@ -24,7 +24,7 @@ pub(crate) fn goto_type_definition( | |||
24 | 24 | ||
25 | let analyzer = hir::SourceAnalyzer::new(db, token.with_value(&node), None); | 25 | let analyzer = hir::SourceAnalyzer::new(db, token.with_value(&node), None); |
26 | 26 | ||
27 | let ty: hir::Ty = if let Some(ty) = | 27 | let ty: hir::Type = if let Some(ty) = |
28 | ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) | 28 | ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) |
29 | { | 29 | { |
30 | ty | 30 | ty |
@@ -35,7 +35,7 @@ pub(crate) fn goto_type_definition( | |||
35 | return None; | 35 | return None; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | let adt_def = analyzer.autoderef(db, ty).find_map(|ty| ty.as_adt().map(|adt| adt.0))?; | 38 | let adt_def = ty.autoderef(db).find_map(|ty| ty.as_adt())?; |
39 | 39 | ||
40 | let nav = adt_def.to_nav(db); | 40 | let nav = adt_def.to_nav(db); |
41 | Some(RangeInfo::new(node.text_range(), vec![nav])) | 41 | Some(RangeInfo::new(node.text_range(), vec![nav])) |
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs index 24a7ca5e7..45149bf0c 100644 --- a/crates/ra_ide_api/src/inlay_hints.rs +++ b/crates/ra_ide_api/src/inlay_hints.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use crate::{db::RootDatabase, FileId}; | 3 | use crate::{db::RootDatabase, FileId}; |
4 | use hir::{HirDisplay, SourceAnalyzer, Ty}; | 4 | use hir::{HirDisplay, SourceAnalyzer}; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | ast::{self, AstNode, TypeAscriptionOwner}, | 6 | ast::{self, AstNode, TypeAscriptionOwner}, |
7 | match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, | 7 | match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, |
@@ -100,8 +100,11 @@ fn get_pat_type_hints( | |||
100 | .into_iter() | 100 | .into_iter() |
101 | .filter(|pat| !skip_root_pat_hint || pat != original_pat) | 101 | .filter(|pat| !skip_root_pat_hint || pat != original_pat) |
102 | .filter_map(|pat| { | 102 | .filter_map(|pat| { |
103 | get_node_displayable_type(db, &analyzer, &pat) | 103 | let ty = analyzer.type_of_pat(db, &pat)?; |
104 | .map(|pat_type| (pat.syntax().text_range(), pat_type)) | 104 | if ty.is_unknown() { |
105 | return None; | ||
106 | } | ||
107 | Some((pat.syntax().text_range(), ty)) | ||
105 | }) | 108 | }) |
106 | .map(|(range, pat_type)| InlayHint { | 109 | .map(|(range, pat_type)| InlayHint { |
107 | range, | 110 | range, |
@@ -158,20 +161,6 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> { | |||
158 | leaf_pats | 161 | leaf_pats |
159 | } | 162 | } |
160 | 163 | ||
161 | fn get_node_displayable_type( | ||
162 | db: &RootDatabase, | ||
163 | analyzer: &SourceAnalyzer, | ||
164 | node_pat: &ast::Pat, | ||
165 | ) -> Option<Ty> { | ||
166 | analyzer.type_of_pat(db, node_pat).and_then(|resolved_type| { | ||
167 | if let Ty::Apply(_) = resolved_type { | ||
168 | Some(resolved_type) | ||
169 | } else { | ||
170 | None | ||
171 | } | ||
172 | }) | ||
173 | } | ||
174 | |||
175 | #[cfg(test)] | 164 | #[cfg(test)] |
176 | mod tests { | 165 | mod tests { |
177 | use crate::mock_analysis::single_file; | 166 | use crate::mock_analysis::single_file; |
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 2b653fe8f..10165a9bb 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use rustc_hash::{FxHashMap, FxHashSet}; | 3 | use rustc_hash::{FxHashMap, FxHashSet}; |
4 | 4 | ||
5 | use hir::{Mutability, Name, Source}; | 5 | use hir::{Name, Source}; |
6 | use ra_db::SourceDatabase; | 6 | use ra_db::SourceDatabase; |
7 | use ra_prof::profile; | 7 | use ra_prof::profile; |
8 | use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; | 8 | use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; |
@@ -230,11 +230,10 @@ fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { | |||
230 | Local(local) => { | 230 | Local(local) => { |
231 | if local.is_mut(db) { | 231 | if local.is_mut(db) { |
232 | "variable.mut" | 232 | "variable.mut" |
233 | } else if local.ty(db).is_mutable_reference() { | ||
234 | "variable.mut" | ||
233 | } else { | 235 | } else { |
234 | match local.ty(db).as_reference() { | 236 | "variable" |
235 | Some((_, Mutability::Mut)) => "variable.mut", | ||
236 | _ => "variable", | ||
237 | } | ||
238 | } | 237 | } |
239 | } | 238 | } |
240 | } | 239 | } |