From 37a11a96a1b3ad68c40cc293270cf8ffbe7904de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 6 May 2021 19:09:35 -0700 Subject: [PATCH 1/3] On type mismatch caused by assignment, point at assignee * Do not emit unnecessary E0308 after E0070 * Show fewer errors on `while let` missing `let` * Hide redundant E0308 on `while let` missing `let` * Point at binding definition when possible on invalid assignment * do not point at closure twice * do not suggest `if let` for literals in lhs * account for parameter types --- compiler/rustc_ast_lowering/src/expr.rs | 16 +++- compiler/rustc_typeck/src/check/coercion.rs | 20 ++++- compiler/rustc_typeck/src/check/demand.rs | 81 +++++++++++++++++-- compiler/rustc_typeck/src/check/expr.rs | 57 +++++++++++-- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 18 +++++ compiler/rustc_typeck/src/check/op.rs | 2 +- src/test/ui/dst/dst-bad-assign-3.stderr | 4 +- src/test/ui/dst/dst-bad-assign.stderr | 4 +- src/test/ui/error-codes/E0070.rs | 1 - src/test/ui/error-codes/E0070.stderr | 11 +-- .../fully-qualified-type-name1.rs | 8 +- .../fully-qualified-type-name1.stderr | 6 +- .../ui/impl-trait/impl-trait-in-macro.stderr | 2 + .../universal-two-impl-traits.stderr | 1 + .../ui/integral-variable-unification-error.rs | 6 +- ...integral-variable-unification-error.stderr | 7 +- src/test/ui/issues/issue-13407.rs | 1 - src/test/ui/issues/issue-13407.stderr | 10 +-- src/test/ui/issues/issue-2951.stderr | 1 + src/test/ui/issues/issue-53348.rs | 2 +- src/test/ui/issues/issue-53348.stderr | 3 + src/test/ui/issues/issue-77218.rs | 11 --- src/test/ui/issues/issue-77218.stderr | 40 --------- .../ui/issues/issue-77218/issue-77218-2.fixed | 7 ++ .../ui/issues/issue-77218/issue-77218-2.rs | 7 ++ .../issues/issue-77218/issue-77218-2.stderr | 16 ++++ .../ui/issues/issue-77218/issue-77218.fixed | 6 ++ src/test/ui/issues/issue-77218/issue-77218.rs | 6 ++ .../ui/issues/issue-77218/issue-77218.stderr | 18 +++++ .../ui/mismatched_types/issue-84976.stderr | 6 ++ src/test/ui/output-type-mismatch.stderr | 4 +- .../ui/static/static-mut-bad-types.stderr | 4 +- src/test/ui/suggestions/if-let-typo.stderr | 5 -- .../suggestions/mut-ref-reassignment.stderr | 8 ++ .../argument-types.stderr | 2 + .../assignment-expected-bool.stderr | 4 - .../type/type-check/assignment-in-if.stderr | 4 - src/test/ui/typeck/issue-81293.stderr | 3 + ...sue-87771-ice-assign-assign-to-bool.stderr | 2 + 39 files changed, 297 insertions(+), 117 deletions(-) delete mode 100644 src/test/ui/issues/issue-77218.rs delete mode 100644 src/test/ui/issues/issue-77218.stderr create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.fixed create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.rs create mode 100644 src/test/ui/issues/issue-77218/issue-77218-2.stderr create mode 100644 src/test/ui/issues/issue-77218/issue-77218.fixed create mode 100644 src/test/ui/issues/issue-77218/issue-77218.rs create mode 100644 src/test/ui/issues/issue-77218/issue-77218.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a0a63620c08a9..9c579209fe51c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -915,14 +915,22 @@ impl<'hir> LoweringContext<'_, 'hir> { ); } if !self.sess.features_untracked().destructuring_assignment { - feature_err( + let mut err = feature_err( &self.sess.parse_sess, sym::destructuring_assignment, eq_sign_span, "destructuring assignments are unstable", - ) - .span_label(lhs.span, "cannot assign to this expression") - .emit(); + ); + err.span_label(lhs.span, "cannot assign to this expression"); + if self.is_in_loop_condition { + err.span_suggestion_verbose( + lhs.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + rustc_errors::Applicability::MachineApplicable, + ); + } + err.emit(); } let mut assignments = vec![]; diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 28712e0658269..77f7cccc04ba4 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1458,7 +1458,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause, expected, found, - coercion_error, + coercion_error.clone(), fcx, parent_id, expression.map(|expr| (expr, blk_id)), @@ -1472,7 +1472,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cause, expected, found, - coercion_error, + coercion_error.clone(), fcx, id, None, @@ -1483,7 +1483,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } _ => { - err = fcx.report_mismatched_types(cause, expected, found, coercion_error); + err = fcx.report_mismatched_types( + cause, + expected, + found, + coercion_error.clone(), + ); } } @@ -1492,7 +1497,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } if let Some(expr) = expression { - fcx.emit_coerce_suggestions(&mut err, expr, found, expected, None); + fcx.emit_coerce_suggestions( + &mut err, + expr, + found, + expected, + None, + coercion_error, + ); } err.emit_unless(unsized_return); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index ece2d7b4f3793..5d121913aac98 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::AllowTwoPhase; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::sym; @@ -27,8 +28,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, + error: TypeError<'tcx>, ) { - self.annotate_expected_due_to_let_ty(err, expr); + self.annotate_expected_due_to_let_ty(err, expr, error); self.suggest_box_deref(err, expr, expected, expr_ty); self.suggest_compatible_variants(err, expr, expected, expr_ty); self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); @@ -145,9 +147,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); let expr_ty = self.resolve_vars_with_obligations(checked_ty); - let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); + let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone()); - self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr); + self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, e); (expected, Some(err)) } @@ -156,15 +158,80 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr<'_>, + error: TypeError<'_>, ) { let parent = self.tcx.hir().get_parent_node(expr.hir_id); - if let Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })) = - self.tcx.hir().find(parent) - { - if init.hir_id == expr.hir_id { + match (self.tcx.hir().find(parent), error) { + (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _) + if init.hir_id == expr.hir_id => + { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); } + ( + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Assign(lhs, rhs, _), .. + })), + TypeError::Sorts(ExpectedFound { expected, .. }), + ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => { + // We ignore closures explicitly because we already point at them elsewhere. + // Point at the assigned-to binding. + let mut primary_span = lhs.span; + let mut secondary_span = lhs.span; + let mut post_message = ""; + if let hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: hir::def::Res::Local(hir_id), .. }, + )) = lhs.kind + { + if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { + let parent = self.tcx.hir().get_parent_node(pat.hir_id); + primary_span = pat.span; + secondary_span = pat.span; + match self.tcx.hir().find(parent) { + Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { + primary_span = ty.span; + post_message = " type"; + } + Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => { + primary_span = init.span; + post_message = " value"; + } + Some(hir::Node::Param(hir::Param { ty_span, .. })) => { + primary_span = *ty_span; + post_message = " parameter type"; + } + _ => {} + } + } + } + + if primary_span != secondary_span + && self + .tcx + .sess + .source_map() + .is_multiline(secondary_span.shrink_to_hi().until(primary_span)) + { + // We are pointing at the binding's type or initializer value, but it's pattern + // is in a different line, so we point at both. + err.span_label(secondary_span, "expected due to the type of this binding"); + err.span_label(primary_span, &format!("expected due to this{}", post_message)); + } else if post_message == "" { + // We are pointing at either the assignment lhs or the binding def pattern. + err.span_label(primary_span, "expected due to the type of this binding"); + } else { + // We are pointing at the binding's type or initializer value. + err.span_label(primary_span, &format!("expected due to this{}", post_message)); + } + + if !lhs.is_syntactic_place_expr() { + // We already emitted E0070 "invalid left-hand side of assignment", so we + // silence this. + err.delay_as_bug(); + } + } + _ => {} } } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index c9fa0fd72fc50..eb997b014c77b 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -833,7 +833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, lhs: &'tcx hir::Expr<'tcx>, err_code: &'static str, - expr_span: &Span, + op_span: Span, ) { if lhs.is_syntactic_place_expr() { return; @@ -841,11 +841,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set. let mut err = self.tcx.sess.struct_span_err_with_code( - *expr_span, + op_span, "invalid left-hand side of assignment", DiagnosticId::Error(err_code.into()), ); err.span_label(lhs.span, "cannot assign to this expression"); + + let mut parent = self.tcx.hir().get_parent_node(lhs.hir_id); + while let Some(node) = self.tcx.hir().find(parent) { + match node { + hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::Loop( + hir::Block { + expr: + Some(hir::Expr { + kind: + hir::ExprKind::Match(expr, ..) | hir::ExprKind::If(expr, ..), + .. + }), + .. + }, + _, + hir::LoopSource::While, + _, + ), + .. + }) => { + // We have a situation like `while Some(0) = value.get(0) {`, where `while let` + // was more likely intended. + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + Applicability::MachineApplicable, + ); + if !self.sess().features_untracked().destructuring_assignment { + // We already emit an E0658 with a suggestion for `while let`, this is + // redundant output. + err.delay_as_bug(); + } + break; + } + hir::Node::Item(_) + | hir::Node::ImplItem(_) + | hir::Node::TraitItem(_) + | hir::Node::Crate(_) => break, + _ => { + parent = self.tcx.hir().get_parent_node(parent); + } + } + } + err.emit(); } @@ -953,7 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (Applicability::MaybeIncorrect, false) }; - if !lhs.is_syntactic_place_expr() { + if !lhs.is_syntactic_place_expr() && !matches!(lhs.kind, hir::ExprKind::Lit(_)) { // Do not suggest `if let x = y` as `==` is way more likely to be the intention. let hir = self.tcx.hir(); if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) = @@ -965,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "let ".to_string(), applicability, ); - } + }; } if eq { err.span_suggestion_verbose( @@ -986,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return self.tcx.ty_error(); } - self.check_lhs_assignable(lhs, "E0070", span); + self.check_lhs_assignable(lhs, "E0070", *span); let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs)); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index a119a6838b8d2..74d7f0a80b6ca 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -737,6 +737,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut |err| { if let Some(expected_ty) = expected.only_has_type(self) { self.consider_hint_about_removing_semicolon(blk, expected_ty, err); + if expected_ty == self.tcx.types.bool { + // If this is caused by a missing `let` in a `while let`, + // silence this redundant error, as we already emit E0070. + let parent = self.tcx.hir().get_parent_node(blk.hir_id); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + let parent = self.tcx.hir().get_parent_node(parent); + match self.tcx.hir().find(parent) { + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _), + .. + })) => { + err.delay_as_bug(); + } + _ => {} + } + } } if let Some(fn_span) = fn_span { err.span_label( diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 9c53a1d4eb68d..f83209f57a897 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_ty }; - self.check_lhs_assignable(lhs, "E0067", &op.span); + self.check_lhs_assignable(lhs, "E0067", op.span); ty } diff --git a/src/test/ui/dst/dst-bad-assign-3.stderr b/src/test/ui/dst/dst-bad-assign-3.stderr index 04e46233532b2..b326dbbbc1405 100644 --- a/src/test/ui/dst/dst-bad-assign-3.stderr +++ b/src/test/ui/dst/dst-bad-assign-3.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/dst-bad-assign-3.rs:33:12 | LL | f5.2 = Bar1 {f: 36}; - | ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | ---- ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding | = note: expected trait object `dyn ToBar` found struct `Bar1` diff --git a/src/test/ui/dst/dst-bad-assign.stderr b/src/test/ui/dst/dst-bad-assign.stderr index f87a34c6d3783..614f213875129 100644 --- a/src/test/ui/dst/dst-bad-assign.stderr +++ b/src/test/ui/dst/dst-bad-assign.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/dst-bad-assign.rs:35:14 | LL | f5.ptr = Bar1 {f: 36}; - | ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | ------ ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding | = note: expected trait object `dyn ToBar` found struct `Bar1` diff --git a/src/test/ui/error-codes/E0070.rs b/src/test/ui/error-codes/E0070.rs index ab956d8109838..3aae0c9ff6e72 100644 --- a/src/test/ui/error-codes/E0070.rs +++ b/src/test/ui/error-codes/E0070.rs @@ -6,7 +6,6 @@ fn some_function() { SOME_CONST = 14; //~ ERROR E0070 1 = 3; //~ ERROR E0070 some_other_func() = 4; //~ ERROR E0070 - //~^ ERROR E0308 } fn main() { diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr index e24d498e3520c..8868bc257a703 100644 --- a/src/test/ui/error-codes/E0070.stderr +++ b/src/test/ui/error-codes/E0070.stderr @@ -22,13 +22,6 @@ LL | some_other_func() = 4; | | | cannot assign to this expression -error[E0308]: mismatched types - --> $DIR/E0070.rs:8:25 - | -LL | some_other_func() = 4; - | ^ expected `()`, found integer - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0070, E0308. -For more information about an error, try `rustc --explain E0070`. +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs index 1c6b9805b51b6..229c174daa864 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs @@ -1,10 +1,10 @@ // Test that we use fully-qualified type names in error messages. fn main() { - let x: Option; + let x: //~ NOTE expected due to the type of this binding + Option; //~ NOTE expected due to this type x = 5; //~^ ERROR mismatched types - //~| expected enum `Option` - //~| found type `{integer}` - //~| expected enum `Option`, found integer + //~| NOTE expected enum `Option` + //~| NOTE expected enum `Option`, found integer } diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr index 03fb299b39cd2..4750c5ccdf702 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -1,6 +1,10 @@ error[E0308]: mismatched types - --> $DIR/fully-qualified-type-name1.rs:5:9 + --> $DIR/fully-qualified-type-name1.rs:6:9 | +LL | let x: + | - expected due to the type of this binding +LL | Option; + | ------------- expected due to this type LL | x = 5; | ^ expected enum `Option`, found integer | diff --git a/src/test/ui/impl-trait/impl-trait-in-macro.stderr b/src/test/ui/impl-trait/impl-trait-in-macro.stderr index b5f9986ce4089..7cfbe3447b813 100644 --- a/src/test/ui/impl-trait/impl-trait-in-macro.stderr +++ b/src/test/ui/impl-trait/impl-trait-in-macro.stderr @@ -7,6 +7,8 @@ LL | ($($tr:tt)*) => { impl $($tr)* }; | expected type parameter | found type parameter ... +LL | let mut a = x; + | - expected due to this value LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr index 7c120235fd176..ab8a53d0db399 100644 --- a/src/test/ui/impl-trait/universal-two-impl-traits.stderr +++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr @@ -6,6 +6,7 @@ LL | fn foo(x: impl Debug, y: impl Debug) -> String { | | | expected type parameter LL | let mut a = x; + | - expected due to this value LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | diff --git a/src/test/ui/integral-variable-unification-error.rs b/src/test/ui/integral-variable-unification-error.rs index 5200b4a829db2..8d1621321e8e6 100644 --- a/src/test/ui/integral-variable-unification-error.rs +++ b/src/test/ui/integral-variable-unification-error.rs @@ -1,6 +1,8 @@ fn main() { - let mut x = 2; + let mut x //~ NOTE expected due to the type of this binding + = + 2; //~ NOTE expected due to this value x = 5.0; //~^ ERROR mismatched types - //~| expected integer, found floating-point number + //~| NOTE expected integer, found floating-point number } diff --git a/src/test/ui/integral-variable-unification-error.stderr b/src/test/ui/integral-variable-unification-error.stderr index b49bff1b0d84d..f77c265a2ada7 100644 --- a/src/test/ui/integral-variable-unification-error.stderr +++ b/src/test/ui/integral-variable-unification-error.stderr @@ -1,6 +1,11 @@ error[E0308]: mismatched types - --> $DIR/integral-variable-unification-error.rs:3:9 + --> $DIR/integral-variable-unification-error.rs:5:9 | +LL | let mut x + | ----- expected due to the type of this binding +LL | = +LL | 2; + | - expected due to this value LL | x = 5.0; | ^^^ expected integer, found floating-point number diff --git a/src/test/ui/issues/issue-13407.rs b/src/test/ui/issues/issue-13407.rs index fa53d55f5b3d7..7ea81ffb59e7e 100644 --- a/src/test/ui/issues/issue-13407.rs +++ b/src/test/ui/issues/issue-13407.rs @@ -5,6 +5,5 @@ mod A { fn main() { A::C = 1; //~^ ERROR: invalid left-hand side of assignment - //~| ERROR: mismatched types //~| ERROR: struct `C` is private } diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr index 4df1813a710ff..54b6c640d9d79 100644 --- a/src/test/ui/issues/issue-13407.stderr +++ b/src/test/ui/issues/issue-13407.stderr @@ -18,13 +18,7 @@ LL | A::C = 1; | | | cannot assign to this expression -error[E0308]: mismatched types - --> $DIR/issue-13407.rs:6:12 - | -LL | A::C = 1; - | ^ expected struct `C`, found integer - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0070, E0308, E0603. +Some errors have detailed explanations: E0070, E0603. For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-2951.stderr b/src/test/ui/issues/issue-2951.stderr index b966b33938917..538bbe2f50296 100644 --- a/src/test/ui/issues/issue-2951.stderr +++ b/src/test/ui/issues/issue-2951.stderr @@ -6,6 +6,7 @@ LL | fn foo(x: T, y: U) { | | | expected type parameter LL | let mut xx = x; + | - expected due to this value LL | xx = y; | ^ expected type parameter `T`, found type parameter `U` | diff --git a/src/test/ui/issues/issue-53348.rs b/src/test/ui/issues/issue-53348.rs index 65f4656b02266..d2f8c77c0ce11 100644 --- a/src/test/ui/issues/issue-53348.rs +++ b/src/test/ui/issues/issue-53348.rs @@ -5,7 +5,7 @@ fn main() { v.into_iter().map(|s|s.to_owned()).collect::>(); - let mut a = String::new(); + let mut a = String::new(); //~ NOTE expected due to this value for i in v { a = *i.to_string(); //~^ ERROR mismatched types diff --git a/src/test/ui/issues/issue-53348.stderr b/src/test/ui/issues/issue-53348.stderr index 8f500261243f1..71d9f5b3dbbff 100644 --- a/src/test/ui/issues/issue-53348.stderr +++ b/src/test/ui/issues/issue-53348.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-53348.rs:10:13 | +LL | let mut a = String::new(); + | ------------- expected due to this value +LL | for i in v { LL | a = *i.to_string(); | ^^^^^^^^^^^^^^ expected struct `String`, found `str` diff --git a/src/test/ui/issues/issue-77218.rs b/src/test/ui/issues/issue-77218.rs deleted file mode 100644 index a6a2401795ff4..0000000000000 --- a/src/test/ui/issues/issue-77218.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - let value = [7u8]; - while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable - //~| ERROR invalid left-hand side of assignment - //~| ERROR mismatched types - //~| ERROR mismatched types - - // FIXME The following diagnostic should also be emitted - // HELP you might have meant to use pattern matching - } -} diff --git a/src/test/ui/issues/issue-77218.stderr b/src/test/ui/issues/issue-77218.stderr deleted file mode 100644 index ce70c0111bee2..0000000000000 --- a/src/test/ui/issues/issue-77218.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0658]: destructuring assignments are unstable - --> $DIR/issue-77218.rs:3:19 - | -LL | while Some(0) = value.get(0) { - | ------- ^ - | | - | cannot assign to this expression - | - = note: see issue #71126 for more information - = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable - -error[E0070]: invalid left-hand side of assignment - --> $DIR/issue-77218.rs:3:19 - | -LL | while Some(0) = value.get(0) { - | - ^ - | | - | cannot assign to this expression - -error[E0308]: mismatched types - --> $DIR/issue-77218.rs:3:16 - | -LL | while Some(0) = value.get(0) { - | ^ expected integer, found `&u8` - | -help: consider dereferencing the borrow - | -LL | while Some(*0) = value.get(0) { - | + - -error[E0308]: mismatched types - --> $DIR/issue-77218.rs:3:11 - | -LL | while Some(0) = value.get(0) { - | ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0070, E0308, E0658. -For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.fixed b/src/test/ui/issues/issue-77218/issue-77218-2.fixed new file mode 100644 index 0000000000000..06487fe0886f9 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.fixed @@ -0,0 +1,7 @@ +// run-rustfix +#![feature(destructuring_assignment)] +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.rs b/src/test/ui/issues/issue-77218/issue-77218-2.rs new file mode 100644 index 0000000000000..e19cec08e4318 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.rs @@ -0,0 +1,7 @@ +// run-rustfix +#![feature(destructuring_assignment)] +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218-2.stderr b/src/test/ui/issues/issue-77218/issue-77218-2.stderr new file mode 100644 index 0000000000000..8d9eb2219d54c --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218-2.stderr @@ -0,0 +1,16 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-77218-2.rs:5:19 + | +LL | while Some(0) = value.get(0) { + | - ^ + | | + | cannot assign to this expression + | +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/issues/issue-77218/issue-77218.fixed b/src/test/ui/issues/issue-77218/issue-77218.fixed new file mode 100644 index 0000000000000..4ea5110902225 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.fixed @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218.rs b/src/test/ui/issues/issue-77218/issue-77218.rs new file mode 100644 index 0000000000000..0f3c12f56351d --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.rs @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable + } +} diff --git a/src/test/ui/issues/issue-77218/issue-77218.stderr b/src/test/ui/issues/issue-77218/issue-77218.stderr new file mode 100644 index 0000000000000..54f49609a4427 --- /dev/null +++ b/src/test/ui/issues/issue-77218/issue-77218.stderr @@ -0,0 +1,18 @@ +error[E0658]: destructuring assignments are unstable + --> $DIR/issue-77218.rs:4:19 + | +LL | while Some(0) = value.get(0) { + | ------- ^ + | | + | cannot assign to this expression + | + = note: see issue #71126 for more information + = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mismatched_types/issue-84976.stderr b/src/test/ui/mismatched_types/issue-84976.stderr index 0c27e17294131..f8f2b1f0f5720 100644 --- a/src/test/ui/mismatched_types/issue-84976.stderr +++ b/src/test/ui/mismatched_types/issue-84976.stderr @@ -7,6 +7,9 @@ LL | length = { foo(&length) }; error[E0308]: mismatched types --> $DIR/issue-84976.rs:17:14 | +LL | let mut length = 0; + | - expected due to this value +... LL | length = foo(&length); | ^^^^^^^^^^^^ expected `u32`, found `i32` @@ -19,6 +22,9 @@ LL | float_length = { bar(&float_length) }; error[E0308]: mismatched types --> $DIR/issue-84976.rs:23:20 | +LL | let mut float_length = 0.0; + | --- expected due to this value +... LL | float_length = bar(&float_length); | ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64` diff --git a/src/test/ui/output-type-mismatch.stderr b/src/test/ui/output-type-mismatch.stderr index 533bd87c9cccb..4507a4df621e1 100644 --- a/src/test/ui/output-type-mismatch.stderr +++ b/src/test/ui/output-type-mismatch.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/output-type-mismatch.rs:5:31 | LL | fn main() { let i: isize; i = f(); } - | ^^^ expected `isize`, found `()` + | ----- ^^^ expected `isize`, found `()` + | | + | expected due to this type error: aborting due to previous error diff --git a/src/test/ui/static/static-mut-bad-types.stderr b/src/test/ui/static/static-mut-bad-types.stderr index ddd98ff40798a..e5a59de6f1461 100644 --- a/src/test/ui/static/static-mut-bad-types.stderr +++ b/src/test/ui/static/static-mut-bad-types.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/static-mut-bad-types.rs:5:13 | LL | a = true; - | ^^^^ expected `isize`, found `bool` + | - ^^^^ expected `isize`, found `bool` + | | + | expected due to the type of this binding error: aborting due to previous error diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr index 7f71cb485815f..058f42f220064 100644 --- a/src/test/ui/suggestions/if-let-typo.stderr +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -70,11 +70,6 @@ error[E0308]: mismatched types | LL | if 3 = foo {} | ^^^^^^^ expected `bool`, found `()` - | -help: you might have meant to use pattern matching - | -LL | if let 3 = foo {} - | +++ error[E0070]: invalid left-hand side of assignment --> $DIR/if-let-typo.rs:10:16 diff --git a/src/test/ui/suggestions/mut-ref-reassignment.stderr b/src/test/ui/suggestions/mut-ref-reassignment.stderr index fd5677898e656..3bd98c7630780 100644 --- a/src/test/ui/suggestions/mut-ref-reassignment.stderr +++ b/src/test/ui/suggestions/mut-ref-reassignment.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:2:11 | +LL | fn suggestion(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = None; | ^^^^ expected mutable reference, found enum `Option` | @@ -14,6 +16,8 @@ LL | *opt = None; error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:6:11 | +LL | fn no_suggestion(opt: &mut Result) { + | ----------------------- expected due to this parameter type LL | opt = None | ^^^^ expected mutable reference, found enum `Option` | @@ -23,6 +27,8 @@ LL | opt = None error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:10:11 | +LL | fn suggestion2(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = Some(String::new()) | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option` | @@ -36,6 +42,8 @@ LL | *opt = Some(String::new()) error[E0308]: mismatched types --> $DIR/mut-ref-reassignment.rs:14:11 | +LL | fn no_suggestion2(opt: &mut Option) { + | ------------------- expected due to this parameter type LL | opt = Some(42) | ^^^^^^^^ expected mutable reference, found enum `Option` | diff --git a/src/test/ui/type-alias-impl-trait/argument-types.stderr b/src/test/ui/type-alias-impl-trait/argument-types.stderr index 1cbf9c95d3148..a87e44a048b25 100644 --- a/src/test/ui/type-alias-impl-trait/argument-types.stderr +++ b/src/test/ui/type-alias-impl-trait/argument-types.stderr @@ -4,6 +4,8 @@ error[E0308]: mismatched types LL | type Foo = impl Debug; | ---------- the expected opaque type ... +LL | fn foo1(mut x: Foo) { + | --- expected due to this parameter type LL | x = 22_u32; | ^^^^^^ expected opaque type, found `u32` | diff --git a/src/test/ui/type/type-check/assignment-expected-bool.stderr b/src/test/ui/type/type-check/assignment-expected-bool.stderr index 862ac65bc24e4..e2b821f7b05e9 100644 --- a/src/test/ui/type/type-check/assignment-expected-bool.stderr +++ b/src/test/ui/type/type-check/assignment-expected-bool.stderr @@ -48,10 +48,6 @@ error[E0308]: mismatched types LL | if 0 = 0 {} | ^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching - | -LL | if let 0 = 0 {} - | +++ help: you might have meant to compare for equality | LL | if 0 == 0 {} diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr index 710be9d6a0420..f4ef44e2444ee 100644 --- a/src/test/ui/type/type-check/assignment-in-if.stderr +++ b/src/test/ui/type/type-check/assignment-in-if.stderr @@ -37,10 +37,6 @@ error[E0308]: mismatched types LL | if 3 = x { | ^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching - | -LL | if let 3 = x { - | +++ help: you might have meant to compare for equality | LL | if 3 == x { diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index 1e6ff3b5f9ee7..c545a563b0d0a 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -7,6 +7,9 @@ LL | a = c + b * 5; error[E0308]: mismatched types --> $DIR/issue-81293.rs:6:9 | +LL | let a: u16; + | --- expected due to this type +... LL | a = c + b * 5; | ^^^^^^^^^ expected `u16`, found `usize` diff --git a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr index fe10fa733d238..56817ee2ca9f8 100644 --- a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr +++ b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-87771-ice-assign-assign-to-bool.rs:3:9 | +LL | let mut a; + | ----- expected due to the type of this binding LL | a = a = true; | ^^^^^^^^ expected `bool`, found `()` From 9cce7bb92181c4e27dbff1fc18d7496c172768ec Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sun, 21 Nov 2021 01:49:51 +0000 Subject: [PATCH 2/3] Account for type obligation coming from `const` and `static` --- compiler/rustc_typeck/src/check/demand.rs | 68 +++++++++++++------ .../ui/static/static-mut-bad-types.stderr | 7 +- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 5d121913aac98..12cd7ad184892 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -179,31 +179,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut primary_span = lhs.span; let mut secondary_span = lhs.span; let mut post_message = ""; - if let hir::ExprKind::Path(hir::QPath::Resolved( - None, - hir::Path { res: hir::def::Res::Local(hir_id), .. }, - )) = lhs.kind - { - if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { - let parent = self.tcx.hir().get_parent_node(pat.hir_id); - primary_span = pat.span; - secondary_span = pat.span; - match self.tcx.hir().find(parent) { - Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { - primary_span = ty.span; - post_message = " type"; - } - Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => { - primary_span = init.span; - post_message = " value"; - } - Some(hir::Node::Param(hir::Param { ty_span, .. })) => { - primary_span = *ty_span; - post_message = " parameter type"; + match lhs.kind { + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { + res: + hir::def::Res::Def( + hir::def::DefKind::Static | hir::def::DefKind::Const, + def_id, + ), + .. + }, + )) => { + if let Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..), + .. + })) = self.tcx.hir().get_if_local(*def_id) + { + primary_span = ty.span; + secondary_span = ident.span; + post_message = " type"; + } + } + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: hir::def::Res::Local(hir_id), .. }, + )) => { + if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) { + let parent = self.tcx.hir().get_parent_node(pat.hir_id); + primary_span = pat.span; + secondary_span = pat.span; + match self.tcx.hir().find(parent) { + Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { + primary_span = ty.span; + post_message = " type"; + } + Some(hir::Node::Local(hir::Local { init: Some(init), .. })) => { + primary_span = init.span; + post_message = " value"; + } + Some(hir::Node::Param(hir::Param { ty_span, .. })) => { + primary_span = *ty_span; + post_message = " parameter type"; + } + _ => {} } - _ => {} } } + _ => {} } if primary_span != secondary_span diff --git a/src/test/ui/static/static-mut-bad-types.stderr b/src/test/ui/static/static-mut-bad-types.stderr index e5a59de6f1461..983e1026f91e9 100644 --- a/src/test/ui/static/static-mut-bad-types.stderr +++ b/src/test/ui/static/static-mut-bad-types.stderr @@ -1,10 +1,11 @@ error[E0308]: mismatched types --> $DIR/static-mut-bad-types.rs:5:13 | +LL | static mut a: isize = 3; + | ----- expected due to this type +... LL | a = true; - | - ^^^^ expected `isize`, found `bool` - | | - | expected due to the type of this binding + | ^^^^ expected `isize`, found `bool` error: aborting due to previous error From 2e1792a764ad286cdd2b68ff6dff7f6efbdce45d Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 25 Nov 2021 18:39:32 +0000 Subject: [PATCH 3/3] Fix clippy test --- src/tools/clippy/tests/ui/crashes/ice-6250.stderr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 439884b7d274a..0d7713aa9a278 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -24,6 +24,9 @@ LL | | } error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:14 | +LL | for reference in vec![1, 2, 3] { + | --------- expected due to the type of this binding +... LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^ expected integer, found `&i32` |