Skip to content

Clearer error diagnostic on type mismatch within a range #67214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 30 additions & 16 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
@@ -55,9 +55,8 @@ use crate::hir::Node;
use crate::infer::{self, SuppressRegionErrors};
use crate::infer::opaque_types;
use crate::middle::region;
use crate::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
};
use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::traits::{IfExpressionCause, PatternGuardCause, MatchExpressionArmCause};
use crate::ty::error::TypeError;
use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};

@@ -607,22 +606,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
) {
match cause.code {
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
if ty.is_suggestable() { // don't show type `_`
err.span_label(span, format!("this match expression has type `{}`", ty));
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
if ty.is_box() && ty.boxed_ty() == found {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
span,
"consider dereferencing the boxed value",
format!("*{}", snippet),
Applicability::MachineApplicable,
);
ObligationCauseCode::PatternGuard(box PatternGuardCause {
match_expr_discrim, other_range_expr
}) => {
if let Some((span, ty)) = match_expr_discrim {
if ty.is_suggestable() { // don't show type `_`
err.span_label(
span,
format!("this match expression requires type `{}`", ty)
);
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
if ty.is_box() && ty.boxed_ty() == found {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
span,
"consider dereferencing the boxed value",
format!("*{}", snippet),
Applicability::MachineApplicable,
);
}
}
}
}
if let Some((span, ty)) = other_range_expr {
err.span_label(span, format!("other endpoint has type `{}`", ty));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like "this endpoint has type will lend itself to less confusion in the output.

}
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
source,
@@ -1338,6 +1347,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
_ => (false, None),
};
debug!("note_type_err: values={:?}", values);
let vals = match self.values_str(&values) {
Some((expected, found)) => Some((expected, found)),
None => {
@@ -1365,6 +1375,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
};

if let Some((expected, found)) = expected_found {
debug!(
"note_type_err: exp_found={:?}, expected={:?} found={:?}",
exp_found, expected, found
);
let expected_label = exp_found.map_or("type".into(), |ef| ef.expected.prefix_string());
let found_label = exp_found.map_or("type".into(), |ef| ef.found.prefix_string());
match (&terr, expected == found) {
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
@@ -2273,7 +2273,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
match *cause_code {
ObligationCauseCode::ExprAssignable |
ObligationCauseCode::MatchExpressionArm { .. } |
ObligationCauseCode::MatchExpressionArmPattern { .. } |
ObligationCauseCode::PatternGuard { .. } |
ObligationCauseCode::IfExpression { .. } |
ObligationCauseCode::IfExpressionWithNoElse |
ObligationCauseCode::MainFunctionType |
10 changes: 8 additions & 2 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -237,8 +237,8 @@ pub enum ObligationCauseCode<'tcx> {
/// Computing common supertype in the arms of a match expression
MatchExpressionArm(Box<MatchExpressionArmCause<'tcx>>),

/// Computing common supertype in the pattern guard for the arms of a match expression
MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> },
/// Computing common supertype in a pattern guard
PatternGuard(Box<PatternGuardCause<'tcx>>),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PatternGuard feels misleading as the usage in demand_eqtype_pat_diag is about patterns. (There's also no such thing as a pattern guard. Only arms have guards.)


/// Constants in patterns must have `Structural` type.
ConstPatternStructural,
@@ -299,6 +299,12 @@ pub struct MatchExpressionArmCause<'tcx> {
pub discrim_hir_id: hir::HirId,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct PatternGuardCause<'tcx> {
pub match_expr_discrim: Option<(Span, Ty<'tcx>)>,
pub other_range_expr: Option<(Span, Ty<'tcx>)>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct IfExpressionCause {
pub then: Span,
9 changes: 6 additions & 3 deletions src/librustc/traits/structural_impls.rs
Original file line number Diff line number Diff line change
@@ -532,9 +532,12 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
})
})
}
super::MatchExpressionArmPattern { span, ty } => {
tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
}
super::PatternGuard(box super::PatternGuardCause {
match_expr_discrim, other_range_expr,
}) => Some(super::PatternGuard(box super::PatternGuardCause {
match_expr_discrim: tcx.lift(&match_expr_discrim)?,
other_range_expr: tcx.lift(&other_range_expr)?,
})),
super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
Some(super::IfExpression(box super::IfExpressionCause {
then,
11 changes: 2 additions & 9 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::check::FnCtxt;
use rustc::infer::InferOk;
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
use rustc::traits::{self, ObligationCause};

use syntax::symbol::sym;
use syntax::util::parser::PREC_POSTFIX;
@@ -88,14 +88,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
actual: Ty<'tcx>,
match_expr_span: Option<Span>,
) -> Option<DiagnosticBuilder<'tcx>> {
let cause = if let Some(span) = match_expr_span {
self.cause(
cause_span,
ObligationCauseCode::MatchExpressionArmPattern { span, ty: expected },
)
} else {
self.misc(cause_span)
};
let cause = self.pat_guard_cause(None, cause_span, expected, match_expr_span);
self.demand_eqtype_with_origin(&cause, expected, actual)
}

21 changes: 20 additions & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc::middle::region;
use rustc::mir::interpret::{ConstValue, GlobalId};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, PatternGuardCause, TraitEngine};
use rustc::ty::{
self, AdtKind, CanonicalUserType, Ty, TyCtxt, Const, GenericParamDefKind,
ToPolyTraitRef, ToPredicate, RegionKind, UserType
@@ -2738,6 +2738,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.cause(span, ObligationCauseCode::MiscObligation)
}

pub fn pat_guard_cause(
&self,
other_range_expr: Option<(Span, Ty<'tcx>)>,
cause_span: Span,
expected: Ty<'tcx>,
match_expr_discrim: Option<Span>
) -> ObligationCause<'tcx> {
match (other_range_expr, match_expr_discrim) {
(Some(_), _) | (_, Some(_)) => self.cause(
cause_span, // error primary span
ObligationCauseCode::PatternGuard(box PatternGuardCause {
match_expr_discrim: match_expr_discrim.map(|span| (span, expected)),
other_range_expr
})
),
_ => self.misc(cause_span)
}
}

/// Resolves type and const variables in `ty` if possible. Unlike the infcx
/// version (resolve_vars_if_possible), this version will
/// also select obligations if it seems useful, in an effort
79 changes: 70 additions & 9 deletions src/librustc_typeck/check/pat.rs
Original file line number Diff line number Diff line change
@@ -355,8 +355,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
discrim_span: Option<Span>,
) -> Option<Ty<'tcx>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that if you change the return type to Result<Ty<'tcx>, DiagnosticBuilder<'tcx>> it will let you clean up a few lines below. Just make sure that in the single check_pat_range caller you emit the error.

debug!("check_pat_range(begin={:?}, end={:?}, discrim_span={:?})",
begin, end, discrim_span
);

let lhs_ty = self.check_expr(begin);
let rhs_ty = self.check_expr(end);
debug!("check_pat_range: expected={:?}, expected.kind={:?}, lhs_ty={:?}, rhs_ty={:?}",
expected, expected.kind, lhs_ty, rhs_ty
);

// Check that both end-points are of numeric or char type.
let numeric_or_char = |ty: Ty<'_>| {
@@ -371,17 +378,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.emit_err_pat_range(
span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll have to change emit_err_pat_range to return the error instead of emitting it.

All of this then becomes

            return self.emit_err_pat_range(
                span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty
                span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty
            );

which lets you have the else clause implicit, removing one indentation level.

return None;
}

// Now that we know the types can be unified we find the unified type and use
// it to type the entire expression.
let common_type = self.resolve_vars_if_possible(&lhs_ty);
None
} else {
use rustc::traits::PredicateObligations;
use infer::InferOk;

let at_cause_eq = |
expect_ty: Ty<'tcx>, actual_type: Ty<'tcx>, cause_span: Span,
other_expr: Option<(Span, Ty<'tcx>)>
| {
if !actual_type.references_error() {
let other_expr = other_expr.filter(|(_, ty)| !ty.references_error());
let cause = self.pat_guard_cause(
other_expr, cause_span, expected, discrim_span
);

let result = self.at(&cause, self.param_env).eq(expect_ty, actual_type);
result.map_err(|terr| (cause, terr))
} else {
Ok(InferOk {obligations: PredicateObligations::new(), value: ()})
}
};

// test if sides both sides of range have the compatible types
let lhs_result = at_cause_eq(expected, lhs_ty, begin.span, Some((end.span, rhs_ty)));
let rhs_result = at_cause_eq(expected, rhs_ty, end.span, Some((begin.span, lhs_ty)));

let joined_result = match (lhs_result, rhs_result) {
// full success, move forwards
(
Ok(InferOk { obligations: lhs_obligation, value: () }),
Ok(InferOk { obligations: rhs_obligation, value: () })
) => {
self.register_predicates(lhs_obligation);
self.register_predicates(rhs_obligation);

// Now that we know the types can be unified we find the unified type and use
// it to type the entire expression.
Ok(self.resolve_vars_if_possible(&lhs_ty))
},
// only lhs is wrong
(Err((cause, terr)), Ok(_)) =>
Err(self.report_mismatched_types(&cause, expected, lhs_ty, terr)),
// only rhs is wrong
(Ok(_), Err((cause, terr))) =>
Err(self.report_mismatched_types(&cause, expected, rhs_ty, terr)),
// both sides are wrong
(Err(_), Err((rhs_cause, terr))) => {
if let Ok(_) = at_cause_eq(lhs_ty, rhs_ty, Span::default(), None) {
let cause = self.pat_guard_cause(None, span, expected, discrim_span);
Err(self.report_mismatched_types(&cause, expected, rhs_ty, terr))
} else {
Err(self.report_mismatched_types(&rhs_cause, expected, rhs_ty, terr))
}
}
};

// Subtyping doesn't matter here, as the value is some kind of scalar.
self.demand_eqtype_pat(span, expected, lhs_ty, discrim_span);
self.demand_eqtype_pat(span, expected, rhs_ty, discrim_span);
Some(common_type)
match joined_result {
Ok(common_type) => Some(common_type),
Err(mut err) => {
err.emit();
None
}
}
}
Comment on lines +384 to +445
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not happy about the amount of special casing, rawness, and the fragility of this type checking logic.
Looking right now to see if there's a less complicated way to get near the same results.

}

fn emit_err_pat_range(
2 changes: 1 addition & 1 deletion src/test/ui/block-result/issue-13624.stderr
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13624.rs:20:9
|
LL | match enum_struct_variant {
| ------------------- this match expression has type `()`
| ------------------- this match expression requires type `()`
LL | a::Enum::EnumStructVariant { x, y, z } => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `a::Enum`

8 changes: 5 additions & 3 deletions src/test/ui/error-codes/E0308-4.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
error[E0308]: mismatched types
--> $DIR/E0308-4.rs:4:9
--> $DIR/E0308-4.rs:4:15
|
LL | match x {
| - this match expression has type `u8`
| - this match expression requires type `u8`
LL | 0u8..=3i8 => (),
| ^^^^^^^^^ expected `u8`, found `i8`
| --- ^^^ expected `u8`, found `i8`
| |
| other endpoint has type `u8`

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -8,9 +8,9 @@ error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this match expression requires type `std::ops::Range<{integer}>`
LL | [_, 99.., _] => {},
| ^^^^ expected struct `std::ops::Range`, found integer
| ^^ expected struct `std::ops::Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
Original file line number Diff line number Diff line change
@@ -14,9 +14,9 @@ error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this match expression requires type `std::ops::Range<{integer}>`
LL | [_, 99..] => {},
| ^^^^ expected struct `std::ops::Range`, found integer
| ^^ expected struct `std::ops::Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
Original file line number Diff line number Diff line change
@@ -5,12 +5,12 @@ LL | [..9, 99..100, _] => {},
| ^^^ help: try using the minimum value for the type: `MIN..9`

error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this match expression requires type `std::ops::Range<{integer}>`
LL | [..9, 99..100, _] => {},
| ^^^ expected struct `std::ops::Range`, found integer
| ^ expected struct `std::ops::Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
@@ -19,7 +19,7 @@ error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
| ----------------------- this match expression requires type `std::ops::Range<{integer}>`
LL | [..9, 99..100, _] => {},
| ^^^^^^^ expected struct `std::ops::Range`, found integer
|
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-11844.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-11844.rs:6:9
|
LL | match a {
| - this match expression has type `std::option::Option<std::boxed::Box<{integer}>>`
| - this match expression requires type `std::option::Option<std::boxed::Box<{integer}>>`
LL | Ok(a) =>
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-12552.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-12552.rs:6:5
|
LL | match t {
| - this match expression has type `std::result::Result<_, {integer}>`
| - this match expression requires type `std::result::Result<_, {integer}>`
LL | Some(k) => match k {
| ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
|
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-13466.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13466.rs:8:9
|
LL | let _x: usize = match Some(1) {
| ------- this match expression has type `std::option::Option<{integer}>`
| ------- this match expression requires type `std::option::Option<{integer}>`
LL | Ok(u) => u,
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13466.rs:14:9
|
LL | let _x: usize = match Some(1) {
| ------- this match expression has type `std::option::Option<{integer}>`
| ------- this match expression requires type `std::option::Option<{integer}>`
...
LL | Err(e) => panic!(e)
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-15896.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-15896.rs:11:11
|
LL | let u = match e {
| - this match expression has type `main::R`
| - this match expression requires type `main::R`
LL | E::B(
LL | Tau{t: x},
| ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau`
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-16401.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-16401.rs:8:9
|
LL | match () {
| -- this match expression has type `()`
| -- this match expression requires type `()`
LL | Slice { data: data, len: len } => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Slice`
|
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-3680.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-3680.rs:3:9
|
LL | match None {
| ---- this match expression has type `std::option::Option<_>`
| ---- this match expression requires type `std::option::Option<_>`
LL | Err(_) => ()
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-5100.stderr
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ error[E0308]: mismatched types
--> $DIR/issue-5100.rs:33:9
|
LL | match (true, false) {
| ------------- this match expression has type `(bool, bool)`
| ------------- this match expression requires type `(bool, bool)`
LL | box (true, false) => ()
| ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box`
|
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-5358-1.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-5358-1.rs:6:9
|
LL | match S(Either::Left(5)) {
| ------------------ this match expression has type `S`
| ------------------ this match expression requires type `S`
LL | Either::Right(_) => {}
| ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
|
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-57741-1.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-57741-1.rs:14:9
|
LL | let y = match x {
| - this match expression has type `std::boxed::Box<u32>`
| - this match expression requires type `std::boxed::Box<u32>`
LL | S::A { a } | S::B { b: a } => a,
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/issue-57741-1.rs:14:22
|
LL | let y = match x {
| - this match expression has type `std::boxed::Box<u32>`
| - this match expression requires type `std::boxed::Box<u32>`
LL | S::A { a } | S::B { b: a } => a,
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|
8 changes: 4 additions & 4 deletions src/test/ui/issues/issue-57741.stderr
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| -
| |
| this match expression has type `std::boxed::Box<T>`
| this match expression requires type `std::boxed::Box<T>`
| help: consider dereferencing the boxed value: `*x`
LL | T::A(a) | T::B(a) => a,
| ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| -
| |
| this match expression has type `std::boxed::Box<T>`
| this match expression requires type `std::boxed::Box<T>`
| help: consider dereferencing the boxed value: `*x`
LL | T::A(a) | T::B(a) => a,
| ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| -
| |
| this match expression has type `std::boxed::Box<S>`
| this match expression requires type `std::boxed::Box<S>`
| help: consider dereferencing the boxed value: `*x`
LL | S::A { a } | S::B { b: a } => a,
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
@@ -46,7 +46,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| -
| |
| this match expression has type `std::boxed::Box<S>`
| this match expression requires type `std::boxed::Box<S>`
| help: consider dereferencing the boxed value: `*x`
LL | S::A { a } | S::B { b: a } => a,
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-7092.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-7092.rs:6:9
|
LL | match x {
| - this match expression has type `Whatever`
| - this match expression requires type `Whatever`
LL | Some(field) =>
| ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option`
|
4 changes: 3 additions & 1 deletion src/test/ui/match/match-range-fail.stderr
Original file line number Diff line number Diff line change
@@ -28,7 +28,9 @@ error[E0308]: mismatched types
--> $DIR/match-range-fail.rs:18:9
|
LL | 'c' ..= 100 => { }
| ^^^^^^^^^^^ expected integer, found `char`
| ^^^ --- other endpoint has type `{integer}`
| |
| expected integer, found `char`

error: aborting due to 4 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/match/match-struct.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/match-struct.rs:6:9
|
LL | match (S { a: 1 }) {
| ------------ this match expression has type `S`
| ------------ this match expression requires type `S`
LL | E::C(_) => (),
| ^^^^^^^ expected struct `S`, found enum `E`

2 changes: 1 addition & 1 deletion src/test/ui/match/match-tag-unary.stderr
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } }
| - ^^^^^^^ expected enum `A`, found enum `B`
| |
| this match expression has type `A`
| this match expression requires type `A`

error: aborting due to previous error

4 changes: 2 additions & 2 deletions src/test/ui/parser/pat-tuple-5.stderr
Original file line number Diff line number Diff line change
@@ -17,9 +17,9 @@ error[E0308]: mismatched types
--> $DIR/pat-tuple-5.rs:5:10
|
LL | match (0, 1) {
| ------ this match expression has type `({integer}, {integer})`
| ------ this match expression requires type `({integer}, {integer})`
LL | (PAT ..) => {}
| ^^^^^^ expected tuple, found `u8`
| ^^^ expected tuple, found `u8`
|
= note: expected tuple `({integer}, {integer})`
found type `u8`
48 changes: 30 additions & 18 deletions src/test/ui/parser/recover-range-pats.stderr
Original file line number Diff line number Diff line change
@@ -417,13 +417,17 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:21:12
|
LL | if let .0..Y = 0 {}
| ^^^^^ expected integer, found floating-point number
| ^^ - other endpoint has type `u8`
| |
| expected integer, found floating-point number

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:23:12
--> $DIR/recover-range-pats.rs:23:16
|
LL | if let X.. .0 = 0 {}
| ^^^^^^ expected integer, found floating-point number
| - ^^ expected integer, found floating-point number
| |
| other endpoint has type `u8`

error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/recover-range-pats.rs:32:12
@@ -445,13 +449,17 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:34:12
|
LL | if let .0..=Y = 0 {}
| ^^^^^^ expected integer, found floating-point number
| ^^ - other endpoint has type `u8`
| |
| expected integer, found floating-point number

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:36:12
--> $DIR/recover-range-pats.rs:36:16
|
LL | if let X..=.0 = 0 {}
| ^^^^^^ expected integer, found floating-point number
| - ^^ expected integer, found floating-point number
| |
| other endpoint has type `u8`

error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/recover-range-pats.rs:45:12
@@ -473,13 +481,17 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:49:12
|
LL | if let .0...Y = 0 {}
| ^^^^^^ expected integer, found floating-point number
| ^^ - other endpoint has type `u8`
| |
| expected integer, found floating-point number

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:52:12
--> $DIR/recover-range-pats.rs:52:17
|
LL | if let X... .0 = 0 {}
| ^^^^^^^ expected integer, found floating-point number
| - ^^ expected integer, found floating-point number
| |
| other endpoint has type `u8`

error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/recover-range-pats.rs:60:12
@@ -491,7 +503,7 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:62:12
|
LL | if let .0.. = 0 {}
| ^^^^ expected integer, found floating-point number
| ^^ expected integer, found floating-point number

error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/recover-range-pats.rs:70:12
@@ -503,7 +515,7 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:72:12
|
LL | if let .0..= = 0 {}
| ^^^^^ expected integer, found floating-point number
| ^^ expected integer, found floating-point number

error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/recover-range-pats.rs:82:12
@@ -515,7 +527,7 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:85:12
|
LL | if let .0... = 0 {}
| ^^^^^ expected integer, found floating-point number
| ^^ expected integer, found floating-point number

error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/recover-range-pats.rs:94:14
@@ -524,10 +536,10 @@ LL | if let ..true = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:96:12
--> $DIR/recover-range-pats.rs:96:15
|
LL | if let .. .0 = 0 {}
| ^^^^^ expected integer, found floating-point number
| ^^ expected integer, found floating-point number

error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/recover-range-pats.rs:104:15
@@ -536,10 +548,10 @@ LL | if let ..=true = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:106:12
--> $DIR/recover-range-pats.rs:106:15
|
LL | if let ..=.0 = 0 {}
| ^^^^^ expected integer, found floating-point number
| ^^ expected integer, found floating-point number

error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/recover-range-pats.rs:116:15
@@ -548,10 +560,10 @@ LL | if let ...true = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:119:12
--> $DIR/recover-range-pats.rs:119:15
|
LL | if let ....3 = 0 {}
| ^^^^^ expected integer, found floating-point number
| ^^ expected integer, found floating-point number

error: aborting due to 85 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/pattern/pattern-error-continue.stderr
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ error[E0308]: mismatched types
--> $DIR/pattern-error-continue.rs:22:9
|
LL | match 'c' {
| --- this match expression has type `char`
| --- this match expression requires type `char`
LL | S { .. } => (),
| ^^^^^^^^ expected `char`, found struct `S`

2 changes: 1 addition & 1 deletion src/test/ui/pattern/pattern-tyvar.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/pattern-tyvar.rs:5:18
|
LL | match t {
| - this match expression has type `std::option::Option<std::vec::Vec<isize>>`
| - this match expression requires type `std::option::Option<std::vec::Vec<isize>>`
LL | Bar::T1(_, Some::<isize>(x)) => {
| ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found `isize`
|
14 changes: 7 additions & 7 deletions src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
Original file line number Diff line number Diff line change
@@ -630,7 +630,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:67:12
|
LL | if let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression requires type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@@ -650,7 +650,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:71:12
|
LL | if let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression requires type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@@ -697,7 +697,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:86:12
|
LL | if let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this match expression requires type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@@ -818,7 +818,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:131:15
|
LL | while let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression requires type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@@ -838,7 +838,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:135:15
|
LL | while let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression requires type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@@ -885,7 +885,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:150:15
|
LL | while let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this match expression requires type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
@@ -961,7 +961,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:198:10
|
LL | (let Range { start: _, end: _ } = true..true || false);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression has type `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this match expression requires type `bool`
| |
| expected `bool`, found struct `std::ops::Range`
|
Original file line number Diff line number Diff line change
@@ -86,7 +86,7 @@ error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:54:9
|
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this match expression has type `Point<{integer}>`
| ---------------------- this match expression requires type `Point<{integer}>`
LL | PointF::<u32> { .. } => {}
| ^^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
|
@@ -97,7 +97,7 @@ error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:59:9
|
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this match expression has type `Point<{integer}>`
| ---------------------- this match expression requires type `Point<{integer}>`
LL | PointF { .. } => {}
| ^^^^^^^^^^^^^ expected integer, found `f32`
|
@@ -108,7 +108,7 @@ error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:67:9
|
LL | match (Pair { x: 1, y: 2 }) {
| --------------------- this match expression has type `Pair<{integer}, {integer}>`
| --------------------- this match expression requires type `Pair<{integer}, {integer}>`
LL | PairF::<u32> { .. } => {}
| ^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
|