aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorPhil Ellison <[email protected]>2019-08-17 06:31:53 +0100
committerAleksey Kladov <[email protected]>2019-08-25 10:56:23 +0100
commit6620949caee25128416acf285590b0d5558e4597 (patch)
tree089ec21abfb2df0a5d3256855973b4f878739335 /crates
parent6a04e9ce147cba1ae4da177f271a29eb296a9bef (diff)
Simplify checking return type, add new test
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/expr/validation.rs25
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs30
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};
6use super::{Expr, ExprId, RecordLitField}; 6use super::{Expr, ExprId, RecordLitField};
7use crate::{ 7use 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};
17use ra_syntax::ast; 16use 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 && &params[0] == &mismatch.actual { 128 if params.len() == 2 && &params[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 {