Auto merge of #85102 - estebank:point-at-assignment, r=oli-obk
Diagnostic tweaks * On type mismatch caused by assignment, point at the source of the expectation * Hide redundant errors * Suggest `while let` when `let` is missing in some cases
This commit is contained in:
commit
9adfd9db78
40 changed files with 324 additions and 116 deletions
|
@ -915,14 +915,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if !self.sess.features_untracked().destructuring_assignment {
|
if !self.sess.features_untracked().destructuring_assignment {
|
||||||
feature_err(
|
let mut err = feature_err(
|
||||||
&self.sess.parse_sess,
|
&self.sess.parse_sess,
|
||||||
sym::destructuring_assignment,
|
sym::destructuring_assignment,
|
||||||
eq_sign_span,
|
eq_sign_span,
|
||||||
"destructuring assignments are unstable",
|
"destructuring assignments are unstable",
|
||||||
)
|
);
|
||||||
.span_label(lhs.span, "cannot assign to this expression")
|
err.span_label(lhs.span, "cannot assign to this expression");
|
||||||
.emit();
|
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![];
|
let mut assignments = vec![];
|
||||||
|
|
|
@ -1458,7 +1458,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||||
cause,
|
cause,
|
||||||
expected,
|
expected,
|
||||||
found,
|
found,
|
||||||
coercion_error,
|
coercion_error.clone(),
|
||||||
fcx,
|
fcx,
|
||||||
parent_id,
|
parent_id,
|
||||||
expression.map(|expr| (expr, blk_id)),
|
expression.map(|expr| (expr, blk_id)),
|
||||||
|
@ -1472,7 +1472,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||||
cause,
|
cause,
|
||||||
expected,
|
expected,
|
||||||
found,
|
found,
|
||||||
coercion_error,
|
coercion_error.clone(),
|
||||||
fcx,
|
fcx,
|
||||||
id,
|
id,
|
||||||
None,
|
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 {
|
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);
|
err.emit_unless(unsized_return);
|
||||||
|
|
|
@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{is_range_literal, Node};
|
use rustc_hir::{is_range_literal, Node};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
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::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
|
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
@ -27,8 +28,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
expr_ty: Ty<'tcx>,
|
expr_ty: Ty<'tcx>,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
expected_ty_expr: Option<&'tcx hir::Expr<'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_box_deref(err, expr, expected, expr_ty);
|
||||||
self.suggest_compatible_variants(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);
|
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 expr = expr.peel_drop_temps();
|
||||||
let cause = self.misc(expr.span);
|
let cause = self.misc(expr.span);
|
||||||
let expr_ty = self.resolve_vars_with_obligations(checked_ty);
|
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))
|
(expected, Some(err))
|
||||||
}
|
}
|
||||||
|
@ -156,15 +158,104 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
expr: &hir::Expr<'_>,
|
expr: &hir::Expr<'_>,
|
||||||
|
error: TypeError<'_>,
|
||||||
) {
|
) {
|
||||||
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
|
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), .. })) =
|
match (self.tcx.hir().find(parent), error) {
|
||||||
self.tcx.hir().find(parent)
|
(Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _)
|
||||||
{
|
if init.hir_id == expr.hir_id =>
|
||||||
if init.hir_id == expr.hir_id {
|
{
|
||||||
// Point at `let` assignment type.
|
// Point at `let` assignment type.
|
||||||
err.span_label(ty.span, "expected due to this");
|
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 = "";
|
||||||
|
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
|
||||||
|
&& 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -833,7 +833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
lhs: &'tcx hir::Expr<'tcx>,
|
lhs: &'tcx hir::Expr<'tcx>,
|
||||||
err_code: &'static str,
|
err_code: &'static str,
|
||||||
expr_span: &Span,
|
op_span: Span,
|
||||||
) {
|
) {
|
||||||
if lhs.is_syntactic_place_expr() {
|
if lhs.is_syntactic_place_expr() {
|
||||||
return;
|
return;
|
||||||
|
@ -841,11 +841,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// FIXME: Make this use SessionDiagnostic once error codes can be dynamically set.
|
// FIXME: Make this use SessionDiagnostic once error codes can be dynamically set.
|
||||||
let mut err = self.tcx.sess.struct_span_err_with_code(
|
let mut err = self.tcx.sess.struct_span_err_with_code(
|
||||||
*expr_span,
|
op_span,
|
||||||
"invalid left-hand side of assignment",
|
"invalid left-hand side of assignment",
|
||||||
DiagnosticId::Error(err_code.into()),
|
DiagnosticId::Error(err_code.into()),
|
||||||
);
|
);
|
||||||
err.span_label(lhs.span, "cannot assign to this expression");
|
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();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -953,7 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
(Applicability::MaybeIncorrect, false)
|
(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.
|
// Do not suggest `if let x = y` as `==` is way more likely to be the intention.
|
||||||
let hir = self.tcx.hir();
|
let hir = self.tcx.hir();
|
||||||
if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
|
if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
|
||||||
|
@ -965,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
"let ".to_string(),
|
"let ".to_string(),
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
if eq {
|
if eq {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
|
@ -986,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return self.tcx.ty_error();
|
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 lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
|
||||||
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
|
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
|
||||||
|
|
|
@ -737,6 +737,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&mut |err| {
|
&mut |err| {
|
||||||
if let Some(expected_ty) = expected.only_has_type(self) {
|
if let Some(expected_ty) = expected.only_has_type(self) {
|
||||||
self.consider_hint_about_removing_semicolon(blk, expected_ty, err);
|
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 {
|
if let Some(fn_span) = fn_span {
|
||||||
err.span_label(
|
err.span_label(
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return_ty
|
return_ty
|
||||||
};
|
};
|
||||||
|
|
||||||
self.check_lhs_assignable(lhs, "E0067", &op.span);
|
self.check_lhs_assignable(lhs, "E0067", op.span);
|
||||||
|
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/dst-bad-assign-3.rs:33:12
|
--> $DIR/dst-bad-assign-3.rs:33:12
|
||||||
|
|
|
|
||||||
LL | f5.2 = Bar1 {f: 36};
|
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`
|
= note: expected trait object `dyn ToBar`
|
||||||
found struct `Bar1`
|
found struct `Bar1`
|
||||||
|
|
|
@ -2,7 +2,9 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/dst-bad-assign.rs:35:14
|
--> $DIR/dst-bad-assign.rs:35:14
|
||||||
|
|
|
|
||||||
LL | f5.ptr = Bar1 {f: 36};
|
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`
|
= note: expected trait object `dyn ToBar`
|
||||||
found struct `Bar1`
|
found struct `Bar1`
|
||||||
|
|
|
@ -6,7 +6,6 @@ fn some_function() {
|
||||||
SOME_CONST = 14; //~ ERROR E0070
|
SOME_CONST = 14; //~ ERROR E0070
|
||||||
1 = 3; //~ ERROR E0070
|
1 = 3; //~ ERROR E0070
|
||||||
some_other_func() = 4; //~ ERROR E0070
|
some_other_func() = 4; //~ ERROR E0070
|
||||||
//~^ ERROR E0308
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -22,13 +22,6 @@ LL | some_other_func() = 4;
|
||||||
| |
|
| |
|
||||||
| cannot assign to this expression
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: aborting due to 3 previous errors
|
||||||
--> $DIR/E0070.rs:8:25
|
|
||||||
|
|
|
||||||
LL | some_other_func() = 4;
|
|
||||||
| ^ expected `()`, found integer
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
For more information about this error, try `rustc --explain E0070`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0070, E0308.
|
|
||||||
For more information about an error, try `rustc --explain E0070`.
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// Test that we use fully-qualified type names in error messages.
|
// Test that we use fully-qualified type names in error messages.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: Option<usize>;
|
let x: //~ NOTE expected due to the type of this binding
|
||||||
|
Option<usize>; //~ NOTE expected due to this type
|
||||||
x = 5;
|
x = 5;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected enum `Option<usize>`
|
//~| NOTE expected enum `Option<usize>`
|
||||||
//~| found type `{integer}`
|
//~| NOTE expected enum `Option`, found integer
|
||||||
//~| expected enum `Option`, found integer
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
error[E0308]: mismatched types
|
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<usize>;
|
||||||
|
| ------------- expected due to this type
|
||||||
LL | x = 5;
|
LL | x = 5;
|
||||||
| ^ expected enum `Option`, found integer
|
| ^ expected enum `Option`, found integer
|
||||||
|
|
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ LL | ($($tr:tt)*) => { impl $($tr)* };
|
||||||
| expected type parameter
|
| expected type parameter
|
||||||
| found type parameter
|
| found type parameter
|
||||||
...
|
...
|
||||||
|
LL | let mut a = x;
|
||||||
|
| - expected due to this value
|
||||||
LL | a = y;
|
LL | a = y;
|
||||||
| ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
|
| ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
|
||||||
|
|
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ LL | fn foo(x: impl Debug, y: impl Debug) -> String {
|
||||||
| |
|
| |
|
||||||
| expected type parameter
|
| expected type parameter
|
||||||
LL | let mut a = x;
|
LL | let mut a = x;
|
||||||
|
| - expected due to this value
|
||||||
LL | a = y;
|
LL | a = y;
|
||||||
| ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
|
| ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
fn main() {
|
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;
|
x = 5.0;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected integer, found floating-point number
|
//~| NOTE expected integer, found floating-point number
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
error[E0308]: mismatched types
|
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;
|
LL | x = 5.0;
|
||||||
| ^^^ expected integer, found floating-point number
|
| ^^^ expected integer, found floating-point number
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,5 @@ mod A {
|
||||||
fn main() {
|
fn main() {
|
||||||
A::C = 1;
|
A::C = 1;
|
||||||
//~^ ERROR: invalid left-hand side of assignment
|
//~^ ERROR: invalid left-hand side of assignment
|
||||||
//~| ERROR: mismatched types
|
|
||||||
//~| ERROR: struct `C` is private
|
//~| ERROR: struct `C` is private
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,7 @@ LL | A::C = 1;
|
||||||
| |
|
| |
|
||||||
| cannot assign to this expression
|
| cannot assign to this expression
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/issue-13407.rs:6:12
|
|
||||||
|
|
|
||||||
LL | A::C = 1;
|
|
||||||
| ^ expected struct `C`, found integer
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
Some errors have detailed explanations: E0070, E0603.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0070, E0308, E0603.
|
|
||||||
For more information about an error, try `rustc --explain E0070`.
|
For more information about an error, try `rustc --explain E0070`.
|
||||||
|
|
|
@ -6,6 +6,7 @@ LL | fn foo<T, U>(x: T, y: U) {
|
||||||
| |
|
| |
|
||||||
| expected type parameter
|
| expected type parameter
|
||||||
LL | let mut xx = x;
|
LL | let mut xx = x;
|
||||||
|
| - expected due to this value
|
||||||
LL | xx = y;
|
LL | xx = y;
|
||||||
| ^ expected type parameter `T`, found type parameter `U`
|
| ^ expected type parameter `T`, found type parameter `U`
|
||||||
|
|
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ fn main() {
|
||||||
|
|
||||||
v.into_iter().map(|s|s.to_owned()).collect::<Vec<_>>();
|
v.into_iter().map(|s|s.to_owned()).collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut a = String::new();
|
let mut a = String::new(); //~ NOTE expected due to this value
|
||||||
for i in v {
|
for i in v {
|
||||||
a = *i.to_string();
|
a = *i.to_string();
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-53348.rs:10:13
|
--> $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();
|
LL | a = *i.to_string();
|
||||||
| ^^^^^^^^^^^^^^ expected struct `String`, found `str`
|
| ^^^^^^^^^^^^^^ expected struct `String`, found `str`
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 <https://github.com/rust-lang/rust/issues/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`.
|
|
7
src/test/ui/issues/issue-77218/issue-77218-2.fixed
Normal file
7
src/test/ui/issues/issue-77218/issue-77218-2.fixed
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
7
src/test/ui/issues/issue-77218/issue-77218-2.rs
Normal file
7
src/test/ui/issues/issue-77218/issue-77218-2.rs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
16
src/test/ui/issues/issue-77218/issue-77218-2.stderr
Normal file
16
src/test/ui/issues/issue-77218/issue-77218-2.stderr
Normal file
|
@ -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`.
|
6
src/test/ui/issues/issue-77218/issue-77218.fixed
Normal file
6
src/test/ui/issues/issue-77218/issue-77218.fixed
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// run-rustfix
|
||||||
|
fn main() {
|
||||||
|
let value = [7u8];
|
||||||
|
while let Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable
|
||||||
|
}
|
||||||
|
}
|
6
src/test/ui/issues/issue-77218/issue-77218.rs
Normal file
6
src/test/ui/issues/issue-77218/issue-77218.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// run-rustfix
|
||||||
|
fn main() {
|
||||||
|
let value = [7u8];
|
||||||
|
while Some(0) = value.get(0) { //~ ERROR destructuring assignments are unstable
|
||||||
|
}
|
||||||
|
}
|
18
src/test/ui/issues/issue-77218/issue-77218.stderr
Normal file
18
src/test/ui/issues/issue-77218/issue-77218.stderr
Normal file
|
@ -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 <https://github.com/rust-lang/rust/issues/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`.
|
|
@ -7,6 +7,9 @@ LL | length = { foo(&length) };
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-84976.rs:17:14
|
--> $DIR/issue-84976.rs:17:14
|
||||||
|
|
|
|
||||||
|
LL | let mut length = 0;
|
||||||
|
| - expected due to this value
|
||||||
|
...
|
||||||
LL | length = foo(&length);
|
LL | length = foo(&length);
|
||||||
| ^^^^^^^^^^^^ expected `u32`, found `i32`
|
| ^^^^^^^^^^^^ expected `u32`, found `i32`
|
||||||
|
|
||||||
|
@ -19,6 +22,9 @@ LL | float_length = { bar(&float_length) };
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-84976.rs:23:20
|
--> $DIR/issue-84976.rs:23:20
|
||||||
|
|
|
|
||||||
|
LL | let mut float_length = 0.0;
|
||||||
|
| --- expected due to this value
|
||||||
|
...
|
||||||
LL | float_length = bar(&float_length);
|
LL | float_length = bar(&float_length);
|
||||||
| ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64`
|
| ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64`
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,9 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/output-type-mismatch.rs:5:31
|
--> $DIR/output-type-mismatch.rs:5:31
|
||||||
|
|
|
|
||||||
LL | fn main() { let i: isize; i = f(); }
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/static-mut-bad-types.rs:5:13
|
--> $DIR/static-mut-bad-types.rs:5:13
|
||||||
|
|
|
|
||||||
|
LL | static mut a: isize = 3;
|
||||||
|
| ----- expected due to this type
|
||||||
|
...
|
||||||
LL | a = true;
|
LL | a = true;
|
||||||
| ^^^^ expected `isize`, found `bool`
|
| ^^^^ expected `isize`, found `bool`
|
||||||
|
|
||||||
|
|
|
@ -70,11 +70,6 @@ error[E0308]: mismatched types
|
||||||
|
|
|
|
||||||
LL | if 3 = foo {}
|
LL | if 3 = foo {}
|
||||||
| ^^^^^^^ expected `bool`, found `()`
|
| ^^^^^^^ 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
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/if-let-typo.rs:10:16
|
--> $DIR/if-let-typo.rs:10:16
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mut-ref-reassignment.rs:2:11
|
--> $DIR/mut-ref-reassignment.rs:2:11
|
||||||
|
|
|
|
||||||
|
LL | fn suggestion(opt: &mut Option<String>) {
|
||||||
|
| ------------------- expected due to this parameter type
|
||||||
LL | opt = None;
|
LL | opt = None;
|
||||||
| ^^^^ expected mutable reference, found enum `Option`
|
| ^^^^ expected mutable reference, found enum `Option`
|
||||||
|
|
|
|
||||||
|
@ -14,6 +16,8 @@ LL | *opt = None;
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mut-ref-reassignment.rs:6:11
|
--> $DIR/mut-ref-reassignment.rs:6:11
|
||||||
|
|
|
|
||||||
|
LL | fn no_suggestion(opt: &mut Result<String, ()>) {
|
||||||
|
| ----------------------- expected due to this parameter type
|
||||||
LL | opt = None
|
LL | opt = None
|
||||||
| ^^^^ expected mutable reference, found enum `Option`
|
| ^^^^ expected mutable reference, found enum `Option`
|
||||||
|
|
|
|
||||||
|
@ -23,6 +27,8 @@ LL | opt = None
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mut-ref-reassignment.rs:10:11
|
--> $DIR/mut-ref-reassignment.rs:10:11
|
||||||
|
|
|
|
||||||
|
LL | fn suggestion2(opt: &mut Option<String>) {
|
||||||
|
| ------------------- expected due to this parameter type
|
||||||
LL | opt = Some(String::new())
|
LL | opt = Some(String::new())
|
||||||
| ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option`
|
| ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option`
|
||||||
|
|
|
|
||||||
|
@ -36,6 +42,8 @@ LL | *opt = Some(String::new())
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mut-ref-reassignment.rs:14:11
|
--> $DIR/mut-ref-reassignment.rs:14:11
|
||||||
|
|
|
|
||||||
|
LL | fn no_suggestion2(opt: &mut Option<String>) {
|
||||||
|
| ------------------- expected due to this parameter type
|
||||||
LL | opt = Some(42)
|
LL | opt = Some(42)
|
||||||
| ^^^^^^^^ expected mutable reference, found enum `Option`
|
| ^^^^^^^^ expected mutable reference, found enum `Option`
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ error[E0308]: mismatched types
|
||||||
LL | type Foo = impl Debug;
|
LL | type Foo = impl Debug;
|
||||||
| ---------- the expected opaque type
|
| ---------- the expected opaque type
|
||||||
...
|
...
|
||||||
|
LL | fn foo1(mut x: Foo) {
|
||||||
|
| --- expected due to this parameter type
|
||||||
LL | x = 22_u32;
|
LL | x = 22_u32;
|
||||||
| ^^^^^^ expected opaque type, found `u32`
|
| ^^^^^^ expected opaque type, found `u32`
|
||||||
|
|
|
|
||||||
|
|
|
@ -48,10 +48,6 @@ error[E0308]: mismatched types
|
||||||
LL | if 0 = 0 {}
|
LL | if 0 = 0 {}
|
||||||
| ^^^^^ expected `bool`, found `()`
|
| ^^^^^ 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
|
help: you might have meant to compare for equality
|
||||||
|
|
|
|
||||||
LL | if 0 == 0 {}
|
LL | if 0 == 0 {}
|
||||||
|
|
|
@ -37,10 +37,6 @@ error[E0308]: mismatched types
|
||||||
LL | if 3 = x {
|
LL | if 3 = x {
|
||||||
| ^^^^^ expected `bool`, found `()`
|
| ^^^^^ 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
|
help: you might have meant to compare for equality
|
||||||
|
|
|
|
||||||
LL | if 3 == x {
|
LL | if 3 == x {
|
||||||
|
|
|
@ -7,6 +7,9 @@ LL | a = c + b * 5;
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-81293.rs:6:9
|
--> $DIR/issue-81293.rs:6:9
|
||||||
|
|
|
|
||||||
|
LL | let a: u16;
|
||||||
|
| --- expected due to this type
|
||||||
|
...
|
||||||
LL | a = c + b * 5;
|
LL | a = c + b * 5;
|
||||||
| ^^^^^^^^^ expected `u16`, found `usize`
|
| ^^^^^^^^^ expected `u16`, found `usize`
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-87771-ice-assign-assign-to-bool.rs:3:9
|
--> $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;
|
LL | a = a = true;
|
||||||
| ^^^^^^^^ expected `bool`, found `()`
|
| ^^^^^^^^ expected `bool`, found `()`
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ LL | | }
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/ice-6250.rs:12:14
|
--> $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) {
|
LL | Some(reference) = cache.data.get(key) {
|
||||||
| ^^^^^^^^^ expected integer, found `&i32`
|
| ^^^^^^^^^ expected integer, found `&i32`
|
||||||
|
|
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue