diff options
author | Phil Ellison <[email protected]> | 2019-08-11 15:00:37 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-08-25 10:55:56 +0100 |
commit | a40e390860987a23f9b899abc5947f1525d3709c (patch) | |
tree | 39aa52a99ce47d439ab92d0519681d4524240820 /crates/ra_hir/src | |
parent | 62c2002e2b21b3a74a4e2205ccc40fa93f722b34 (diff) |
Check type rather than just name in ok-wrapping diagnostic. Add test for handling generic functions (which currently fails)
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/expr/validation.rs | 46 | ||||
-rw-r--r-- | crates/ra_hir/src/name.rs | 2 |
2 files changed, 40 insertions, 8 deletions
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs index ca7db61bc..339a7b848 100644 --- a/crates/ra_hir/src/expr/validation.rs +++ b/crates/ra_hir/src/expr/validation.rs | |||
@@ -6,10 +6,13 @@ use ra_syntax::ast::{AstNode, RecordLit}; | |||
6 | use super::{Expr, ExprId, RecordLitField}; | 6 | use super::{Expr, ExprId, RecordLitField}; |
7 | use crate::{ | 7 | use crate::{ |
8 | adt::AdtDef, | 8 | adt::AdtDef, |
9 | code_model::Enum, | ||
9 | diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr}, | 10 | diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr}, |
10 | expr::AstPtr, | 11 | expr::AstPtr, |
12 | name, | ||
13 | path::{PathKind, PathSegment}, | ||
11 | ty::{InferenceResult, Ty, TypeCtor}, | 14 | ty::{InferenceResult, Ty, TypeCtor}, |
12 | Function, HasSource, HirDatabase, Name, Path, | 15 | Function, HasSource, HirDatabase, ModuleDef, Name, Path, PerNs, Resolution |
13 | }; | 16 | }; |
14 | use ra_syntax::ast; | 17 | use ra_syntax::ast; |
15 | 18 | ||
@@ -106,18 +109,45 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
106 | Some(m) => m, | 109 | Some(m) => m, |
107 | None => return, | 110 | None => return, |
108 | }; | 111 | }; |
109 | let ret = match &mismatch.expected { | 112 | |
110 | Ty::Apply(t) => t, | 113 | let std_result_path = Path { |
111 | _ => return, | 114 | kind: PathKind::Abs, |
115 | segments: vec![ | ||
116 | PathSegment { name: name::STD, args_and_bindings: None }, | ||
117 | PathSegment { name: name::RESULT_MOD, args_and_bindings: None }, | ||
118 | PathSegment { name: name::RESULT_TYPE, args_and_bindings: None }, | ||
119 | ] | ||
112 | }; | 120 | }; |
113 | let ret_enum = match ret.ctor { | 121 | |
114 | TypeCtor::Adt(AdtDef::Enum(e)) => e, | 122 | let resolver = self.func.resolver(db); |
123 | let std_result_enum = match resolver.resolve_path_segments(db, &std_result_path).into_fully_resolved() { | ||
124 | PerNs { types: Some(Resolution::Def(ModuleDef::Enum(e))), .. } => e, | ||
115 | _ => return, | 125 | _ => return, |
116 | }; | 126 | }; |
117 | let enum_name = ret_enum.name(db); | 127 | |
118 | if enum_name.is_none() || enum_name.unwrap().to_string() != "Result" { | 128 | let std_result_type = std_result_enum.ty(db); |
129 | |||
130 | fn enum_from_type(ty: &Ty) -> Option<Enum> { | ||
131 | match ty { | ||
132 | Ty::Apply(t) => { | ||
133 | match t.ctor { | ||
134 | TypeCtor::Adt(AdtDef::Enum(e)) => Some(e), | ||
135 | _ => None, | ||
136 | } | ||
137 | } | ||
138 | _ => None | ||
139 | } | ||
140 | } | ||
141 | |||
142 | if enum_from_type(&mismatch.expected) != enum_from_type(&std_result_type) { | ||
119 | return; | 143 | return; |
120 | } | 144 | } |
145 | |||
146 | let ret = match &mismatch.expected { | ||
147 | Ty::Apply(t) => t, | ||
148 | _ => return, | ||
149 | }; | ||
150 | |||
121 | let params = &ret.parameters; | 151 | let params = &ret.parameters; |
122 | if params.len() == 2 && ¶ms[0] == &mismatch.actual { | 152 | if params.len() == 2 && ¶ms[0] == &mismatch.actual { |
123 | let source_map = self.func.body_source_map(db); | 153 | let source_map = self.func.body_source_map(db); |
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index 6d14eea8e..9c4822d91 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs | |||
@@ -120,6 +120,8 @@ pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try") | |||
120 | pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); | 120 | pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); |
121 | pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); | 121 | pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); |
122 | pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); | 122 | pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); |
123 | pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result")); | ||
124 | pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); | ||
123 | pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); | 125 | pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); |
124 | 126 | ||
125 | fn resolve_name(text: &SmolStr) -> SmolStr { | 127 | fn resolve_name(text: &SmolStr) -> SmolStr { |