Point at the match discriminant when arm pattern has a type mismatch

This commit is contained in:
Esteban Küber 2019-01-05 17:08:15 -08:00
parent c2d381d39d
commit a873337f21
27 changed files with 183 additions and 77 deletions

View file

@ -487,6 +487,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) { fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) {
match cause.code { match cause.code {
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
err.span_label(span, format!("this match expression evaluates to `{}`", ty));
}
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source { ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
hir::MatchSource::IfLetDesugar { .. } => { hir::MatchSource::IfLetDesugar { .. } => {
let msg = "`if let` arm with an incompatible type"; let msg = "`if let` arm with an incompatible type";

View file

@ -1444,6 +1444,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
match *cause_code { match *cause_code {
ObligationCauseCode::ExprAssignable | ObligationCauseCode::ExprAssignable |
ObligationCauseCode::MatchExpressionArm { .. } | ObligationCauseCode::MatchExpressionArm { .. } |
ObligationCauseCode::MatchExpressionArmPattern { .. } |
ObligationCauseCode::IfExpression | ObligationCauseCode::IfExpression |
ObligationCauseCode::IfExpressionWithNoElse | ObligationCauseCode::IfExpressionWithNoElse |
ObligationCauseCode::MainFunctionType | ObligationCauseCode::MainFunctionType |
@ -1451,8 +1452,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ObligationCauseCode::IntrinsicType | ObligationCauseCode::IntrinsicType |
ObligationCauseCode::MethodReceiver | ObligationCauseCode::MethodReceiver |
ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::ReturnNoExpression |
ObligationCauseCode::MiscObligation => { ObligationCauseCode::MiscObligation => {}
}
ObligationCauseCode::SliceOrArrayElem => { ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type"); err.note("slice and array elements must have `Sized` type");
} }

View file

@ -220,8 +220,13 @@ pub enum ObligationCauseCode<'tcx> {
ExprAssignable, ExprAssignable,
/// Computing common supertype in the arms of a match expression /// Computing common supertype in the arms of a match expression
MatchExpressionArm { arm_span: Span, MatchExpressionArm {
source: hir::MatchSource }, arm_span: Span,
source: hir::MatchSource,
},
/// Computing common supertype in the pattern guard for the arms of a match expression
MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> },
/// Computing common supertype in an if expression /// Computing common supertype in an if expression
IfExpression, IfExpression,

View file

@ -517,6 +517,9 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
arm_span, arm_span,
source: source, source: source,
}), }),
super::MatchExpressionArmPattern { span, ty } => {
tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
}
super::IfExpression => Some(super::IfExpression), super::IfExpression => Some(super::IfExpression),
super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse), super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
super::MainFunctionType => Some(super::MainFunctionType), super::MainFunctionType => Some(super::MainFunctionType),

View file

@ -29,12 +29,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pat: &'gcx hir::Pat, pat: &'gcx hir::Pat,
mut expected: Ty<'tcx>, mut expected: Ty<'tcx>,
mut def_bm: ty::BindingMode, mut def_bm: ty::BindingMode,
is_arg: bool) match_discrim_span: Option<Span>,
{ ) {
let tcx = self.tcx; let tcx = self.tcx;
debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?},is_arg={})", debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
pat, expected, def_bm, is_arg);
let is_non_ref_pat = match pat.node { let is_non_ref_pat = match pat.node {
PatKind::Struct(..) | PatKind::Struct(..) |
@ -210,8 +209,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let common_type = self.resolve_type_vars_if_possible(&lhs_ty); let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
// subtyping doesn't matter here, as the value is some kind of scalar // subtyping doesn't matter here, as the value is some kind of scalar
self.demand_eqtype(pat.span, expected, lhs_ty); self.demand_eqtype_pat(pat.span, expected, lhs_ty, match_discrim_span);
self.demand_eqtype(pat.span, expected, rhs_ty); self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span);
common_type common_type
} }
PatKind::Binding(ba, var_id, _, ref sub) => { PatKind::Binding(ba, var_id, _, ref sub) => {
@ -240,13 +239,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
// required. However, we use equality, which is stronger. See (*) for // required. However, we use equality, which is stronger. See (*) for
// an explanation. // an explanation.
self.demand_eqtype(pat.span, region_ty, local_ty); self.demand_eqtype_pat(pat.span, region_ty, local_ty, match_discrim_span);
} }
// otherwise the type of x is the expected type T // otherwise the type of x is the expected type T
ty::BindByValue(_) => { ty::BindByValue(_) => {
// As above, `T <: typeof(x)` is required but we // As above, `T <: typeof(x)` is required but we
// use equality, see (*) below. // use equality, see (*) below.
self.demand_eqtype(pat.span, expected, local_ty); self.demand_eqtype_pat(pat.span, expected, local_ty, match_discrim_span);
} }
} }
@ -254,23 +253,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// what the type of the binding `x` ought to be // what the type of the binding `x` ought to be
if var_id != pat.id { if var_id != pat.id {
let vt = self.local_ty(pat.span, var_id).decl_ty; let vt = self.local_ty(pat.span, var_id).decl_ty;
self.demand_eqtype(pat.span, vt, local_ty); self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span);
} }
if let Some(ref p) = *sub { if let Some(ref p) = *sub {
self.check_pat_walk(&p, expected, def_bm, true); self.check_pat_walk(&p, expected, def_bm, match_discrim_span);
} }
local_ty local_ty
} }
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected, def_bm) self.check_pat_tuple_struct(
pat,
qpath,
&subpats,
ddpos,
expected,
def_bm,
match_discrim_span,
)
} }
PatKind::Path(ref qpath) => { PatKind::Path(ref qpath) => {
self.check_pat_path(pat, qpath, expected) self.check_pat_path(pat, qpath, expected)
} }
PatKind::Struct(ref qpath, ref fields, etc) => { PatKind::Struct(ref qpath, ref fields, etc) => {
self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm) self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, match_discrim_span)
} }
PatKind::Tuple(ref elements, ddpos) => { PatKind::Tuple(ref elements, ddpos) => {
let mut expected_len = elements.len(); let mut expected_len = elements.len();
@ -295,12 +302,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// further errors being emitted when using the bindings. #50333 // further errors being emitted when using the bindings. #50333
let element_tys_iter = (0..max_len).map(|_| tcx.types.err); let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
self.check_pat_walk(elem, &tcx.types.err, def_bm, true); self.check_pat_walk(elem, &tcx.types.err, def_bm, match_discrim_span);
} }
tcx.mk_tup(element_tys_iter) tcx.mk_tup(element_tys_iter)
} else { } else {
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
self.check_pat_walk(elem, &element_tys[i], def_bm, true); self.check_pat_walk(elem, &element_tys[i], def_bm, match_discrim_span);
} }
pat_ty pat_ty
} }
@ -313,11 +320,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Here, `demand::subtype` is good enough, but I don't // Here, `demand::subtype` is good enough, but I don't
// think any errors can be introduced by using // think any errors can be introduced by using
// `demand::eqtype`. // `demand::eqtype`.
self.demand_eqtype(pat.span, expected, uniq_ty); self.demand_eqtype_pat(pat.span, expected, uniq_ty, match_discrim_span);
self.check_pat_walk(&inner, inner_ty, def_bm, true); self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
uniq_ty uniq_ty
} else { } else {
self.check_pat_walk(&inner, tcx.types.err, def_bm, true); self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
tcx.types.err tcx.types.err
} }
} }
@ -349,15 +356,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Look for a case like `fn foo(&foo: u32)` and suggest // Look for a case like `fn foo(&foo: u32)` and suggest
// `fn foo(foo: &u32)` // `fn foo(foo: &u32)`
if let Some(mut err) = err { if let Some(mut err) = err {
if is_arg { if let PatKind::Binding(..) = inner.node {
if let PatKind::Binding(..) = inner.node { if let Ok(snippet) = tcx.sess.source_map()
if let Ok(snippet) = tcx.sess.source_map() .span_to_snippet(pat.span)
.span_to_snippet(pat.span) {
{ err.help(&format!("did you mean `{}: &{}`?",
err.help(&format!("did you mean `{}: &{}`?", &snippet[1..],
&snippet[1..], expected));
expected));
}
} }
} }
err.emit(); err.emit();
@ -366,10 +371,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
}; };
self.check_pat_walk(&inner, inner_ty, def_bm, true); self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
rptr_ty rptr_ty
} else { } else {
self.check_pat_walk(&inner, tcx.types.err, def_bm, true); self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
tcx.types.err tcx.types.err
} }
} }
@ -427,13 +432,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}; };
for elt in before { for elt in before {
self.check_pat_walk(&elt, inner_ty, def_bm, true); self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
} }
if let Some(ref slice) = *slice { if let Some(ref slice) = *slice {
self.check_pat_walk(&slice, slice_ty, def_bm, true); self.check_pat_walk(&slice, slice_ty, def_bm, match_discrim_span);
} }
for elt in after { for elt in after {
self.check_pat_walk(&elt, inner_ty, def_bm, true); self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
} }
expected_ty expected_ty
} }
@ -524,12 +529,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
true true
} }
pub fn check_match(&self, pub fn check_match(
expr: &'gcx hir::Expr, &self,
discrim: &'gcx hir::Expr, expr: &'gcx hir::Expr,
arms: &'gcx [hir::Arm], discrim: &'gcx hir::Expr,
expected: Expectation<'tcx>, arms: &'gcx [hir::Arm],
match_src: hir::MatchSource) -> Ty<'tcx> { expected: Expectation<'tcx>,
match_src: hir::MatchSource,
) -> Ty<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
// Not entirely obvious: if matches may create ref bindings, we want to // Not entirely obvious: if matches may create ref bindings, we want to
@ -624,8 +631,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
let mut all_pats_diverge = Diverges::WarnedAlways; let mut all_pats_diverge = Diverges::WarnedAlways;
for p in &arm.pats { for p in &arm.pats {
self.diverges.set(Diverges::Maybe); self.diverges.set(Diverges::Maybe);
self.check_pat_walk(&p, discrim_ty, self.check_pat_walk(
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true); &p,
discrim_ty,
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
Some(discrim.span),
);
all_pats_diverge &= self.diverges.get(); all_pats_diverge &= self.diverges.get();
} }
@ -703,26 +714,29 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
coercion.complete(self) coercion.complete(self)
} }
fn check_pat_struct(&self, fn check_pat_struct(
pat: &'gcx hir::Pat, &self,
qpath: &hir::QPath, pat: &'gcx hir::Pat,
fields: &'gcx [Spanned<hir::FieldPat>], qpath: &hir::QPath,
etc: bool, fields: &'gcx [Spanned<hir::FieldPat>],
expected: Ty<'tcx>, etc: bool,
def_bm: ty::BindingMode) -> Ty<'tcx> expected: Ty<'tcx>,
def_bm: ty::BindingMode,
match_discrim_span: Option<Span>,
) -> Ty<'tcx>
{ {
// Resolve the path and check the definition for errors. // Resolve the path and check the definition for errors.
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) { let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
variant_ty variant_ty
} else { } else {
for field in fields { for field in fields {
self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, true); self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, match_discrim_span);
} }
return self.tcx.types.err; return self.tcx.types.err;
}; };
// Type-check the path. // Type-check the path.
self.demand_eqtype(pat.span, expected, pat_ty); self.demand_eqtype_pat(pat.span, expected, pat_ty, match_discrim_span);
// Type-check subpatterns. // Type-check subpatterns.
if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) { if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) {
@ -732,11 +746,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
} }
} }
fn check_pat_path(&self, fn check_pat_path(
pat: &hir::Pat, &self,
qpath: &hir::QPath, pat: &hir::Pat,
expected: Ty<'tcx>) -> Ty<'tcx> qpath: &hir::QPath,
{ expected: Ty<'tcx>,
) -> Ty<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
// Resolve the path and check the definition for errors. // Resolve the path and check the definition for errors.
@ -767,18 +782,20 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
pat_ty pat_ty
} }
fn check_pat_tuple_struct(&self, fn check_pat_tuple_struct(
pat: &hir::Pat, &self,
qpath: &hir::QPath, pat: &hir::Pat,
subpats: &'gcx [P<hir::Pat>], qpath: &hir::QPath,
ddpos: Option<usize>, subpats: &'gcx [P<hir::Pat>],
expected: Ty<'tcx>, ddpos: Option<usize>,
def_bm: ty::BindingMode) -> Ty<'tcx> expected: Ty<'tcx>,
{ def_bm: ty::BindingMode,
match_arm_pat_span: Option<Span>,
) -> Ty<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let on_error = || { let on_error = || {
for pat in subpats { for pat in subpats {
self.check_pat_walk(&pat, tcx.types.err, def_bm, true); self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
} }
}; };
let report_unexpected_def = |def: Def| { let report_unexpected_def = |def: Def| {
@ -826,7 +843,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
let pat_ty = pat_ty.fn_sig(tcx).output(); let pat_ty = pat_ty.fn_sig(tcx).output();
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
self.demand_eqtype(pat.span, expected, pat_ty); self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
// Type-check subpatterns. // Type-check subpatterns.
if subpats.len() == variant.fields.len() || if subpats.len() == variant.fields.len() ||
@ -837,7 +854,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
}; };
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
self.check_pat_walk(&subpat, field_ty, def_bm, true); self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span); self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span);
} }
@ -917,7 +934,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
} }
}; };
self.check_pat_walk(&field.pat, field_ty, def_bm, true); self.check_pat_walk(&field.pat, field_ty, def_bm, None);
} }
let mut unmentioned_fields = variant.fields let mut unmentioned_fields = variant.fields
.iter() .iter()

View file

@ -1,6 +1,6 @@
use check::FnCtxt; use check::FnCtxt;
use rustc::infer::InferOk; use rustc::infer::InferOk;
use rustc::traits::ObligationCause; use rustc::traits::{ObligationCause, ObligationCauseCode};
use syntax::ast; use syntax::ast;
use syntax::util::parser::PREC_POSTFIX; use syntax::util::parser::PREC_POSTFIX;
@ -66,6 +66,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub fn demand_eqtype_pat(
&self,
cause_span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
match_expr_span: Option<Span>,
) {
let cause = if let Some(span) = match_expr_span {
self.cause(
cause_span,
ObligationCauseCode::MatchExpressionArmPattern { span, ty: expected },
)
} else {
self.misc(cause_span)
};
self.demand_eqtype_with_origin(&cause, expected, actual).map(|mut err| err.emit());
}
pub fn demand_coerce(&self, pub fn demand_coerce(&self,
expr: &hir::Expr, expr: &hir::Expr,
checked_ty: Ty<'tcx>, checked_ty: Ty<'tcx>,

View file

@ -1084,8 +1084,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
// Add formal parameters. // Add formal parameters.
for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) {
// Check the pattern. // Check the pattern.
fcx.check_pat_walk(&arg.pat, arg_ty, fcx.check_pat_walk(
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true); &arg.pat,
arg_ty,
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
None,
);
// Check that argument is Sized. // Check that argument is Sized.
// The check for a non-trivial pattern is a hack to avoid duplicate warnings // The check for a non-trivial pattern is a hack to avoid duplicate warnings
@ -4723,9 +4727,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
self.check_pat_walk(&local.pat, t, self.check_pat_walk(
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), &local.pat,
true); t,
ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
None,
);
let pat_ty = self.node_ty(local.pat.hir_id); let pat_ty = self.node_ty(local.pat.hir_id);
if pat_ty.references_error() { if pat_ty.references_error() {
self.write_ty(local.hir_id, pat_ty); self.write_ty(local.hir_id, pat_ty);

View file

@ -12,6 +12,8 @@ LL | Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-13624.rs:22:9 --> $DIR/issue-13624.rs:22:9
| |
LL | match enum_struct_variant {
| ------------------- this match expression evaluates to `()`
LL | a::Enum::EnumStructVariant { x, y, z } => { LL | a::Enum::EnumStructVariant { x, y, z } => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/E0308-4.rs:4:9 --> $DIR/E0308-4.rs:4:9
| |
LL | match x {
| - this match expression evaluates to `u8`
LL | 0u8..=3i8 => (), //~ ERROR E0308 LL | 0u8..=3i8 => (), //~ ERROR E0308
| ^^^^^^^^^ expected u8, found i8 | ^^^^^^^^^ expected u8, found i8

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-11844.rs:6:9 --> $DIR/issue-11844.rs:6:9
| |
LL | match a {
| - this match expression evaluates to `std::option::Option<std::boxed::Box<{integer}>>`
LL | Ok(a) => //~ ERROR: mismatched types LL | Ok(a) => //~ ERROR: mismatched types
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-12552.rs:6:5 --> $DIR/issue-12552.rs:6:5
| |
LL | match t {
| - this match expression evaluates to `std::result::Result<_, {integer}>`
LL | Some(k) => match k { //~ ERROR mismatched types LL | Some(k) => match k { //~ ERROR mismatched types
| ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option` | ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-13466.rs:8:9 --> $DIR/issue-13466.rs:8:9
| |
LL | let _x: usize = match Some(1) {
| ------- this match expression evaluates to `std::option::Option<{integer}>`
LL | Ok(u) => u, LL | Ok(u) => u,
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
| |
@ -10,6 +12,9 @@ LL | Ok(u) => u,
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-13466.rs:14:9 --> $DIR/issue-13466.rs:14:9
| |
LL | let _x: usize = match Some(1) {
| ------- this match expression evaluates to `std::option::Option<{integer}>`
...
LL | Err(e) => panic!(e) LL | Err(e) => panic!(e)
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
| |

View file

@ -1,6 +1,9 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-15896.rs:11:11 --> $DIR/issue-15896.rs:11:11
| |
LL | let u = match e {
| - this match expression evaluates to `main::R`
LL | E::B(
LL | Tau{t: x}, LL | Tau{t: x},
| ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau` | ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau`
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-16401.rs:8:9 --> $DIR/issue-16401.rs:8:9
| |
LL | match () {
| -- this match expression evaluates to `()`
LL | Slice { data: data, len: len } => (), LL | Slice { data: data, len: len } => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `Slice` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `Slice`
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-3680.rs:3:9 --> $DIR/issue-3680.rs:3:9
| |
LL | match None {
| ---- this match expression evaluates to `std::option::Option<_>`
LL | Err(_) => () LL | Err(_) => ()
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
| |

View file

@ -28,6 +28,8 @@ LL | (true, false, false) => ()
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-5100.rs:33:9 --> $DIR/issue-5100.rs:33:9
| |
LL | match (true, false) {
| ------------- this match expression evaluates to `(bool, bool)`
LL | box (true, false) => () LL | box (true, false) => ()
| ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box` | ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box`
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-5358-1.rs:6:9 --> $DIR/issue-5358-1.rs:6:9
| |
LL | match S(Either::Left(5)) {
| ------------------ this match expression evaluates to `S`
LL | Either::Right(_) => {} LL | Either::Right(_) => {}
| ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either` | ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-7092.rs:6:9 --> $DIR/issue-7092.rs:6:9
| |
LL | match x {
| - this match expression evaluates to `Whatever`
LL | Some(field) => LL | Some(field) =>
| ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option` | ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option`
| |

View file

@ -19,6 +19,8 @@ LL | 10 ..= "what" => ()
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/match-range-fail.rs:17:9 --> $DIR/match-range-fail.rs:17:9
| |
LL | match 5 {
| - this match expression evaluates to `{integer}`
LL | 'c' ..= 100 => { } LL | 'c' ..= 100 => { }
| ^^^^^^^^^^^ expected integer, found char | ^^^^^^^^^^^ expected integer, found char
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/match-struct.rs:6:9 --> $DIR/match-struct.rs:6:9
| |
LL | match (S { a: 1 }) {
| ------------ this match expression evaluates to `S`
LL | E::C(_) => (), LL | E::C(_) => (),
| ^^^^^^^ expected struct `S`, found enum `E` | ^^^^^^^ expected struct `S`, found enum `E`
| |

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/match-tag-unary.rs:4:43 --> $DIR/match-tag-unary.rs:4:43
| |
LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types
| ^^^^^^^ expected enum `A`, found enum `B` | - ^^^^^^^ expected enum `A`, found enum `B`
| |
| this match expression evaluates to `A`
| |
= note: expected type `A` = note: expected type `A`
found type `B` found type `B`

View file

@ -9,6 +9,8 @@ LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/E0409.rs:5:23 --> $DIR/E0409.rs:5:23
| |
LL | match x {
| - this match expression evaluates to `_`
LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409 LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409
| ^ expected &{integer}, found integer | ^ expected &{integer}, found integer
| |

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/or-pattern-mismatch.rs:3:68 --> $DIR/or-pattern-mismatch.rs:3:68
| |
LL | fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } } LL | fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } }
| ^ expected usize, found isize | ---------------- ^ expected usize, found isize
| |
| this match expression evaluates to `_`
| |
= note: expected type `usize` = note: expected type `usize`
found type `isize` found type `isize`

View file

@ -21,6 +21,8 @@ LL | A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/pattern-error-continue.rs:22:9 --> $DIR/pattern-error-continue.rs:22:9
| |
LL | match 'c' {
| --- this match expression evaluates to `char`
LL | S { .. } => (), LL | S { .. } => (),
| ^^^^^^^^ expected char, found struct `S` | ^^^^^^^^ expected char, found struct `S`
| |

View file

@ -1,6 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/pattern-tyvar.rs:5:18 --> $DIR/pattern-tyvar.rs:5:18
| |
LL | match t {
| - this match expression evaluates to `std::option::Option<std::vec::Vec<isize>>`
LL | Bar::T1(_, Some::<isize>(x)) => { //~ ERROR mismatched types LL | Bar::T1(_, Some::<isize>(x)) => { //~ ERROR mismatched types
| ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found isize | ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found isize
| |

View file

@ -23,6 +23,8 @@ LL | Opts::A(ref mut i) | Opts::B(ref i) => {}
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/resolve-inconsistent-binding-mode.rs:7:32 --> $DIR/resolve-inconsistent-binding-mode.rs:7:32
| |
LL | match x {
| - this match expression evaluates to `_`
LL | Opts::A(ref i) | Opts::B(i) => {} LL | Opts::A(ref i) | Opts::B(i) => {}
| ^ expected &isize, found isize | ^ expected &isize, found isize
| |
@ -32,6 +34,8 @@ LL | Opts::A(ref i) | Opts::B(i) => {}
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/resolve-inconsistent-binding-mode.rs:16:32 --> $DIR/resolve-inconsistent-binding-mode.rs:16:32
| |
LL | match x {
| - this match expression evaluates to `_`
LL | Opts::A(ref i) | Opts::B(i) => {} LL | Opts::A(ref i) | Opts::B(i) => {}
| ^ expected &isize, found isize | ^ expected &isize, found isize
| |
@ -41,6 +45,8 @@ LL | Opts::A(ref i) | Opts::B(i) => {}
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/resolve-inconsistent-binding-mode.rs:25:36 --> $DIR/resolve-inconsistent-binding-mode.rs:25:36
| |
LL | match x {
| - this match expression evaluates to `_`
LL | Opts::A(ref mut i) | Opts::B(ref i) => {} LL | Opts::A(ref mut i) | Opts::B(ref i) => {}
| ^^^^^ types differ in mutability | ^^^^^ types differ in mutability
| |

View file

@ -109,6 +109,8 @@ LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:54:9 --> $DIR/structure-constructor-type-mismatch.rs:54:9
| |
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this match expression evaluates to `Point<{integer}>`
LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
| ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32
| |
@ -118,6 +120,8 @@ LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:59:9 --> $DIR/structure-constructor-type-mismatch.rs:59:9
| |
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this match expression evaluates to `Point<{integer}>`
LL | PointF { .. } => {} //~ ERROR mismatched types LL | PointF { .. } => {} //~ ERROR mismatched types
| ^^^^^^^^^^^^^ expected integer, found f32 | ^^^^^^^^^^^^^ expected integer, found f32
| |
@ -127,6 +131,8 @@ LL | PointF { .. } => {} //~ ERROR mismatched types
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:67:9 --> $DIR/structure-constructor-type-mismatch.rs:67:9
| |
LL | match (Pair { x: 1, y: 2 }) {
| --------------------- this match expression evaluates to `Pair<{integer}, {integer}>`
LL | PairF::<u32> { .. } => {} //~ ERROR mismatched types LL | PairF::<u32> { .. } => {} //~ ERROR mismatched types
| ^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | ^^^^^^^^^^^^^^^^^^^ expected integer, found f32
| |