From d035be8e6f7f618ad2e78f2d5a3790c6e310fd67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Sun, 24 Jan 2021 10:32:24 +0300 Subject: [PATCH] typeck: Don't suggest converting LHS exprs Converting LHS of an assignment does not work, so avoid suggesting that. Fixes #81293 --- compiler/rustc_middle/src/hir/map/mod.rs | 11 +++++++++++ compiler/rustc_typeck/src/check/demand.rs | 7 +++++++ src/test/ui/typeck/issue-81293.rs | 9 +++++++++ src/test/ui/typeck/issue-81293.stderr | 24 +++++++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 src/test/ui/typeck/issue-81293.rs create mode 100644 src/test/ui/typeck/issue-81293.stderr diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 9b01a64de8415..3598a4cb4898d 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -564,6 +564,17 @@ impl<'hir> Map<'hir> { ) } + /// Checks if the node is left-hand side of an assignment. + pub fn is_lhs(&self, id: HirId) -> bool { + match self.find(self.get_parent_node(id)) { + Some(Node::Expr(expr)) => match expr.kind { + ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id, + _ => false, + }, + _ => false, + } + } + /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. /// Used exclusively for diagnostics, to avoid suggestion function calls. pub fn is_inside_const_context(&self, hir_id: HirId) -> bool { diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index c22f001744639..3c9c683f4b0cb 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -816,6 +816,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |err: &mut DiagnosticBuilder<'_>, found_to_exp_is_fallible: bool, exp_to_found_is_fallible: bool| { + let exp_is_lhs = + expected_ty_expr.map(|e| self.tcx.hir().is_lhs(e.hir_id)).unwrap_or(false); + + if exp_is_lhs { + return; + } + let always_fallible = found_to_exp_is_fallible && (exp_to_found_is_fallible || expected_ty_expr.is_none()); let msg = if literal_is_ty_suffixed(expr) { diff --git a/src/test/ui/typeck/issue-81293.rs b/src/test/ui/typeck/issue-81293.rs new file mode 100644 index 0000000000000..076b8c944b8a4 --- /dev/null +++ b/src/test/ui/typeck/issue-81293.rs @@ -0,0 +1,9 @@ +fn main() { + let a: u16; + let b: u16 = 42; + let c: usize = 5; + + a = c + b * 5; //~ ERROR: mismatched types [E0308] + //~| ERROR: mismatched types [E0308] + //~| ERROR: cannot add `u16` to `usize` [E0277] +} diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr new file mode 100644 index 0000000000000..1e6ff3b5f9ee7 --- /dev/null +++ b/src/test/ui/typeck/issue-81293.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/issue-81293.rs:6:13 + | +LL | a = c + b * 5; + | ^^^^^ expected `usize`, found `u16` + +error[E0308]: mismatched types + --> $DIR/issue-81293.rs:6:9 + | +LL | a = c + b * 5; + | ^^^^^^^^^ expected `u16`, found `usize` + +error[E0277]: cannot add `u16` to `usize` + --> $DIR/issue-81293.rs:6:11 + | +LL | a = c + b * 5; + | ^ no implementation for `usize + u16` + | + = help: the trait `Add` is not implemented for `usize` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`.