diff options
author | Phil Ellison <[email protected]> | 2019-08-17 06:31:53 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-08-25 10:56:23 +0100 |
commit | 6620949caee25128416acf285590b0d5558e4597 (patch) | |
tree | 089ec21abfb2df0a5d3256855973b4f878739335 | |
parent | 6a04e9ce147cba1ae4da177f271a29eb296a9bef (diff) |
Simplify checking return type, add new test
-rw-r--r-- | crates/ra_hir/src/expr/validation.rs | 25 | ||||
-rw-r--r-- | crates/ra_ide_api/src/diagnostics.rs | 30 |
2 files changed, 32 insertions, 23 deletions
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs index e35990d2e..5d9d59ff8 100644 --- a/crates/ra_hir/src/expr/validation.rs +++ b/crates/ra_hir/src/expr/validation.rs | |||
@@ -6,12 +6,11 @@ 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, | ||
10 | diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr}, | 9 | diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr}, |
11 | expr::AstPtr, | 10 | expr::AstPtr, |
12 | name, | 11 | name, |
13 | path::{PathKind, PathSegment}, | 12 | path::{PathKind, PathSegment}, |
14 | ty::{InferenceResult, Ty, TypeCtor}, | 13 | ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, |
15 | Function, HasSource, HirDatabase, ModuleDef, Name, Path, PerNs, Resolution, | 14 | Function, HasSource, HirDatabase, ModuleDef, Name, Path, PerNs, Resolution, |
16 | }; | 15 | }; |
17 | use ra_syntax::ast; | 16 | use ra_syntax::ast; |
@@ -120,28 +119,12 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
120 | _ => return, | 119 | _ => return, |
121 | }; | 120 | }; |
122 | 121 | ||
123 | let std_result_type = std_result_enum.ty(db); | 122 | let std_result_ctor = TypeCtor::Adt(AdtDef::Enum(std_result_enum)); |
124 | 123 | let params = match &mismatch.expected { | |
125 | fn enum_from_type(ty: &Ty) -> Option<Enum> { | 124 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, |
126 | match ty { | ||
127 | Ty::Apply(t) => match t.ctor { | ||
128 | TypeCtor::Adt(AdtDef::Enum(e)) => Some(e), | ||
129 | _ => None, | ||
130 | }, | ||
131 | _ => None, | ||
132 | } | ||
133 | } | ||
134 | |||
135 | if enum_from_type(&mismatch.expected) != enum_from_type(&std_result_type) { | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | let ret = match &mismatch.expected { | ||
140 | Ty::Apply(t) => t, | ||
141 | _ => return, | 125 | _ => return, |
142 | }; | 126 | }; |
143 | 127 | ||
144 | let params = &ret.parameters; | ||
145 | if params.len() == 2 && ¶ms[0] == &mismatch.actual { | 128 | if params.len() == 2 && ¶ms[0] == &mismatch.actual { |
146 | let source_map = self.func.body_source_map(db); | 129 | let source_map = self.func.body_source_map(db); |
147 | let file_id = self.func.source(db).file_id; | 130 | let file_id = self.func.source(db).file_id; |
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index 0b9bb5a66..94424dc16 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs | |||
@@ -79,7 +79,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
79 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { | 79 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { |
80 | let node = d.ast(db); | 80 | let node = d.ast(db); |
81 | let mut builder = TextEditBuilder::default(); | 81 | let mut builder = TextEditBuilder::default(); |
82 | let replacement = format!("Ok({})", node.syntax().text()); | 82 | let replacement = format!("Ok({})", node.syntax()); |
83 | builder.replace(node.syntax().text_range(), replacement); | 83 | builder.replace(node.syntax().text_range(), replacement); |
84 | let fix = SourceChange::source_file_edit_from("wrap with ok", file_id, builder.finish()); | 84 | let fix = SourceChange::source_file_edit_from("wrap with ok", file_id, builder.finish()); |
85 | res.borrow_mut().push(Diagnostic { | 85 | res.borrow_mut().push(Diagnostic { |
@@ -353,7 +353,7 @@ fn div(x: i32, y: i32) -> MyResult<i32> { | |||
353 | } | 353 | } |
354 | 354 | ||
355 | #[test] | 355 | #[test] |
356 | fn test_wrap_return_type_not_applicable() { | 356 | fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { |
357 | let content = r#" | 357 | let content = r#" |
358 | //- /main.rs | 358 | //- /main.rs |
359 | use std::{string::String, result::Result::{self, Ok, Err}}; | 359 | use std::{string::String, result::Result::{self, Ok, Err}}; |
@@ -374,6 +374,32 @@ fn div(x: i32, y: i32) -> MyResult<i32> { | |||
374 | } | 374 | } |
375 | 375 | ||
376 | #[test] | 376 | #[test] |
377 | fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { | ||
378 | let content = r#" | ||
379 | //- /main.rs | ||
380 | use std::{string::String, result::Result::{self, Ok, Err}}; | ||
381 | |||
382 | enum SomeOtherEnum { | ||
383 | Ok(i32), | ||
384 | Err(String), | ||
385 | } | ||
386 | |||
387 | fn foo() -> SomeOtherEnum { | ||
388 | 0 | ||
389 | } | ||
390 | |||
391 | //- /std/lib.rs | ||
392 | pub mod string { | ||
393 | pub struct String { } | ||
394 | } | ||
395 | pub mod result { | ||
396 | pub enum Result<T, E> { Ok(T), Err(E) } | ||
397 | } | ||
398 | "#; | ||
399 | check_no_diagnostic_for_target_file("/main.rs", content); | ||
400 | } | ||
401 | |||
402 | #[test] | ||
377 | fn test_fill_struct_fields_empty() { | 403 | fn test_fill_struct_fields_empty() { |
378 | let before = r" | 404 | let before = r" |
379 | struct TestStruct { | 405 | struct TestStruct { |