aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/diagnostics.rs15
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs27
-rw-r--r--crates/hir_ty/src/tests/macros.rs31
3 files changed, 60 insertions, 13 deletions
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs
index 14e18f5a1..c67a289f2 100644
--- a/crates/hir_ty/src/diagnostics.rs
+++ b/crates/hir_ty/src/diagnostics.rs
@@ -186,9 +186,10 @@ impl Diagnostic for MissingMatchArms {
186 } 186 }
187} 187}
188 188
189// Diagnostic: missing-ok-in-tail-expr 189// Diagnostic: missing-ok-or-some-in-tail-expr
190// 190//
191// This diagnostic is triggered if block that should return `Result` returns a value not wrapped in `Ok`. 191// This diagnostic is triggered if a block that should return `Result` returns a value not wrapped in `Ok`,
192// or if a block that should return `Option` returns a value not wrapped in `Some`.
192// 193//
193// Example: 194// Example:
194// 195//
@@ -198,17 +199,19 @@ impl Diagnostic for MissingMatchArms {
198// } 199// }
199// ``` 200// ```
200#[derive(Debug)] 201#[derive(Debug)]
201pub struct MissingOkInTailExpr { 202pub struct MissingOkOrSomeInTailExpr {
202 pub file: HirFileId, 203 pub file: HirFileId,
203 pub expr: AstPtr<ast::Expr>, 204 pub expr: AstPtr<ast::Expr>,
205 // `Some` or `Ok` depending on whether the return type is Result or Option
206 pub required: String,
204} 207}
205 208
206impl Diagnostic for MissingOkInTailExpr { 209impl Diagnostic for MissingOkOrSomeInTailExpr {
207 fn code(&self) -> DiagnosticCode { 210 fn code(&self) -> DiagnosticCode {
208 DiagnosticCode("missing-ok-in-tail-expr") 211 DiagnosticCode("missing-ok-or-some-in-tail-expr")
209 } 212 }
210 fn message(&self) -> String { 213 fn message(&self) -> String {
211 "wrap return expression in Ok".to_string() 214 format!("wrap return expression in {}", self.required)
212 } 215 }
213 fn display_source(&self) -> InFile<SyntaxNodePtr> { 216 fn display_source(&self) -> InFile<SyntaxNodePtr> {
214 InFile { file_id: self.file, value: self.expr.clone().into() } 217 InFile { file_id: self.file, value: self.expr.clone().into() }
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index b4e453411..a1c484fdf 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -11,8 +11,8 @@ use crate::{
11 db::HirDatabase, 11 db::HirDatabase,
12 diagnostics::{ 12 diagnostics::{
13 match_check::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, 13 match_check::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness},
14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields, 14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
15 RemoveThisSemicolon, 15 MissingPatFields, RemoveThisSemicolon,
16 }, 16 },
17 utils::variant_data, 17 utils::variant_data,
18 ApplicationTy, InferenceResult, Ty, TypeCtor, 18 ApplicationTy, InferenceResult, Ty, TypeCtor,
@@ -306,27 +306,40 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
306 }; 306 };
307 307
308 let core_result_path = path![core::result::Result]; 308 let core_result_path = path![core::result::Result];
309 let core_option_path = path![core::option::Option];
309 310
310 let resolver = self.owner.resolver(db.upcast()); 311 let resolver = self.owner.resolver(db.upcast());
311 let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) { 312 let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) {
312 Some(it) => it, 313 Some(it) => it,
313 _ => return, 314 _ => return,
314 }; 315 };
316 let core_option_enum = match resolver.resolve_known_enum(db.upcast(), &core_option_path) {
317 Some(it) => it,
318 _ => return,
319 };
315 320
316 let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum)); 321 let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum));
317 let params = match &mismatch.expected { 322 let core_option_ctor = TypeCtor::Adt(AdtId::EnumId(core_option_enum));
323
324 let (params, required) = match &mismatch.expected {
318 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => { 325 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => {
319 parameters 326 (parameters, "Ok".to_string())
327 }
328 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_option_ctor => {
329 (parameters, "Some".to_string())
320 } 330 }
321 _ => return, 331 _ => return,
322 }; 332 };
323 333
324 if params.len() == 2 && params[0] == mismatch.actual { 334 if params.len() > 0 && params[0] == mismatch.actual {
325 let (_, source_map) = db.body_with_source_map(self.owner.into()); 335 let (_, source_map) = db.body_with_source_map(self.owner.into());
326 336
327 if let Ok(source_ptr) = source_map.expr_syntax(id) { 337 if let Ok(source_ptr) = source_map.expr_syntax(id) {
328 self.sink 338 self.sink.push(MissingOkOrSomeInTailExpr {
329 .push(MissingOkInTailExpr { file: source_ptr.file_id, expr: source_ptr.value }); 339 file: source_ptr.file_id,
340 expr: source_ptr.value,
341 required,
342 });
330 } 343 }
331 } 344 }
332 } 345 }
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index 1953da7be..c64f0b5b5 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -371,6 +371,37 @@ expand!();
371} 371}
372 372
373#[test] 373#[test]
374fn infer_macro_with_dollar_crate_in_def_site() {
375 check_types(
376 r#"
377//- /main.rs crate:main deps:foo
378use foo::expand;
379
380macro_rules! list {
381 ($($tt:tt)*) => { $($tt)* }
382}
383
384fn test() {
385 let r = expand!();
386 r;
387 //^ u128
388}
389
390//- /lib.rs crate:foo
391#[macro_export]
392macro_rules! expand {
393 () => { list!($crate::m!()) };
394}
395
396#[macro_export]
397macro_rules! m {
398 () => { 0u128 };
399}
400"#,
401 );
402}
403
404#[test]
374fn infer_type_value_non_legacy_macro_use_as() { 405fn infer_type_value_non_legacy_macro_use_as() {
375 check_infer( 406 check_infer(
376 r#" 407 r#"