From 98ad0af60b28edae325237857a4544f634d0191f Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Sun, 6 Dec 2020 01:14:21 +0100 Subject: [PATCH 1/4] Properly suggest deref in else block --- compiler/rustc_typeck/src/check/demand.rs | 22 ++++++++++++++++++++++ src/test/ui/deref-suggestion.rs | 10 ++++++++++ src/test/ui/deref-suggestion.stderr | 11 ++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index f9f67769e96a4..8107cfbf32dbc 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -366,6 +366,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + crate fn hir_id_sole_block_element( + &self, + hir_id: hir::HirId, + ) -> Option<&'tcx rustc_hir::Expr<'tcx>> { + let node: Option> = self.tcx.hir().find(hir_id); + match node { + Some(Node::Expr(rustc_hir::Expr { + kind: rustc_hir::ExprKind::Block(block, ..), + .. + })) if block.stmts.len() == 0 => block.expr, + _ => None, + } + } + /// This function is used to determine potential "simple" improvements or users' errors and /// provide them useful help. For example: /// @@ -652,6 +666,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let suggestion = if is_struct_pat_shorthand_field { format!("{}: *{}", code, code) + } else if let Some(expr) = + self.hir_id_sole_block_element(expr.hir_id) + { + if let Ok(inner_code) = sm.span_to_snippet(expr.span) { + format!("*{}", inner_code) + } else { + format!("*{}", code) + } } else { format!("*{}", code) }; diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs index 580410aecf4f8..5cb680541dd9c 100644 --- a/src/test/ui/deref-suggestion.rs +++ b/src/test/ui/deref-suggestion.rs @@ -45,4 +45,14 @@ fn main() { //~^ ERROR mismatched types let r = R { i: i }; //~^ ERROR mismatched types + + + let a = &1; + let b = &2; + let val: i32 = if true { + a + 1 + } else { + b + //~^ ERROR mismatched types + }; } diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index f59f05db9c047..6eef06b68cb0e 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -89,6 +89,15 @@ LL | let r = R { i: i }; | expected `u32`, found `&{integer}` | help: consider dereferencing the borrow: `*i` -error: aborting due to 10 previous errors +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:55:9 + | +LL | b + | ^ + | | + | expected `i32`, found `&{integer}` + | help: consider dereferencing the borrow: `*b` + +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0308`. From e603f994b127881961b53bea988f87a7c7632f25 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Thu, 17 Dec 2020 13:24:51 +0100 Subject: [PATCH 2/4] Address review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Léo Lanteri Thauvin --- compiler/rustc_typeck/src/check/demand.rs | 18 +++++------------- src/test/ui/deref-suggestion.rs | 8 ++++++++ src/test/ui/deref-suggestion.stderr | 11 ++++++++++- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 8107cfbf32dbc..2d84e7830c21b 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -366,16 +366,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - crate fn hir_id_sole_block_element( - &self, - hir_id: hir::HirId, - ) -> Option<&'tcx rustc_hir::Expr<'tcx>> { - let node: Option> = self.tcx.hir().find(hir_id); - match node { - Some(Node::Expr(rustc_hir::Expr { - kind: rustc_hir::ExprKind::Block(block, ..), - .. - })) if block.stmts.len() == 0 => block.expr, + /// If the given `HirId` corresponds to a block with a trailing expression, return that expression + crate fn maybe_get_block_expr(&self, hir_id: hir::HirId) -> Option<&'tcx hir::Expr<'tcx>> { + match self.tcx.hir().find(hir_id)? { + Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, ..), .. }) => block.expr, _ => None, } } @@ -666,9 +660,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let suggestion = if is_struct_pat_shorthand_field { format!("{}: *{}", code, code) - } else if let Some(expr) = - self.hir_id_sole_block_element(expr.hir_id) - { + } else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) { if let Ok(inner_code) = sm.span_to_snippet(expr.span) { format!("*{}", inner_code) } else { diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs index 5cb680541dd9c..e62e8467bd28a 100644 --- a/src/test/ui/deref-suggestion.rs +++ b/src/test/ui/deref-suggestion.rs @@ -55,4 +55,12 @@ fn main() { b //~^ ERROR mismatched types }; + let val: i32 = if true { + let _ = 2; + a + 1 + } else { + let _ = 2; + b + //~^ ERROR mismatched types + }; } diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index 6eef06b68cb0e..0de125695e60b 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -98,6 +98,15 @@ LL | b | expected `i32`, found `&{integer}` | help: consider dereferencing the borrow: `*b` -error: aborting due to 11 previous errors +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:63:9 + | +LL | b + | ^ + | | + | expected `i32`, found `&{integer}` + | help: consider dereferencing the borrow: `*b` + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0308`. From 08879449c645c224d3628bebb3e5b5a50a88cc3f Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 25 Mar 2021 21:53:56 +0100 Subject: [PATCH 3/4] Add additional test Co-authored-by: Camelid --- src/test/ui/deref-suggestion.rs | 8 ++++++++ src/test/ui/deref-suggestion.stderr | 31 ++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs index e62e8467bd28a..4fd695585ba06 100644 --- a/src/test/ui/deref-suggestion.rs +++ b/src/test/ui/deref-suggestion.rs @@ -63,4 +63,12 @@ fn main() { b //~^ ERROR mismatched types }; + let val = if true { + *a + } else if true { + //~^ ERROR incompatible types + b + } else { + &0 + }; } diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index 0de125695e60b..1720421c7f60e 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -107,6 +107,35 @@ LL | b | expected `i32`, found `&{integer}` | help: consider dereferencing the borrow: `*b` -error: aborting due to 12 previous errors +error[E0308]: `if` and `else` have incompatible types + --> $DIR/deref-suggestion.rs:68:12 + | +LL | let val = if true { + | _______________- +LL | | *a + | | -- expected because of this +LL | | } else if true { + | |____________^ +LL | || +LL | || b +LL | || } else { +LL | || &0 +LL | || }; + | || ^ + | ||_____| + | |______`if` and `else` have incompatible types + | expected `i32`, found `&{integer}` + | +help: consider dereferencing the borrow + | +LL | } else *if true { +LL | +LL | b +LL | } else { +LL | &0 +LL | }; + | + +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0308`. From fb7cf0982b6cba2a77e40ef6b5919e7584a07a95 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 2 Apr 2021 00:07:16 +0200 Subject: [PATCH 4/4] Don't suggest dereferencing an `else if` expression --- compiler/rustc_typeck/src/check/demand.rs | 24 ++++++++++++++++++----- src/test/ui/deref-suggestion.stderr | 10 ---------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 2d84e7830c21b..d879b6e97dcfb 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -374,6 +374,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Returns whether the given expression is an `else if`. + crate fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool { + if let hir::ExprKind::If(..) = expr.kind { + let parent_id = self.tcx.hir().get_parent_node(expr.hir_id); + if let Some(Node::Expr(hir::Expr { + kind: hir::ExprKind::If(_, _, Some(else_expr)), + .. + })) = self.tcx.hir().find(parent_id) + { + return else_expr.hir_id == expr.hir_id; + } + } + false + } + /// This function is used to determine potential "simple" improvements or users' errors and /// provide them useful help. For example: /// @@ -660,12 +675,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let suggestion = if is_struct_pat_shorthand_field { format!("{}: *{}", code, code) + } else if self.is_else_if_block(expr) { + // Don't suggest nonsense like `else *if` + return None; } else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) { - if let Ok(inner_code) = sm.span_to_snippet(expr.span) { - format!("*{}", inner_code) - } else { - format!("*{}", code) - } + format!("*{}", sm.span_to_snippet(expr.span).unwrap_or(code)) } else { format!("*{}", code) }; diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index 1720421c7f60e..632a279d79623 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -125,16 +125,6 @@ LL | || }; | ||_____| | |______`if` and `else` have incompatible types | expected `i32`, found `&{integer}` - | -help: consider dereferencing the borrow - | -LL | } else *if true { -LL | -LL | b -LL | } else { -LL | &0 -LL | }; - | error: aborting due to 13 previous errors