Avoid using same code

This commit is contained in:
Yuki Okushi 2019-11-13 23:22:48 +09:00
parent 302cf6db74
commit 030fa9a337

View File

@ -362,66 +362,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| ty.is_char()
|| ty.references_error()
};
let lhs_compat = numeric_or_char(lhs_ty);
let rhs_compat = numeric_or_char(rhs_ty);
let lhs_fail = !numeric_or_char(lhs_ty);
let rhs_fail = !numeric_or_char(rhs_ty);
if !lhs_compat || !rhs_compat {
let span = if !lhs_compat && !rhs_compat {
span
} else if !lhs_compat {
begin.span
} else {
end.span
};
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0029,
"only char and numeric types are allowed in range patterns"
if lhs_fail || rhs_fail {
self.emit_err_pat_range(
span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty
);
if !lhs_compat && !rhs_compat {
err.span_label(
begin.span,
&format!("this is of type `{}` but it should be `char` or numeric", lhs_ty)
);
err.span_label(
end.span,
&format!("this is of type `{}` but it should be `char` or numeric", rhs_ty)
);
} else if !lhs_compat {
err.span_label(
begin.span,
&format!("this is of type `{}` but it should be `char` or numeric", lhs_ty)
);
if !rhs_ty.references_error() {
err.span_label(
end.span,
&format!("this is of type `{}`", rhs_ty)
);
}
} else {
err.span_label(
end.span,
&format!("this is of type `{}` but it should be `char` or numeric", rhs_ty)
);
if !lhs_ty.references_error() {
err.span_label(
begin.span,
&format!("this is of type `{}`", lhs_ty)
);
}
}
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"In a match expression, only numbers and characters can be matched \
against a range. This is because the compiler checks that the range \
is non-empty at compile-time, and is unable to evaluate arbitrary \
comparison functions. If you want to capture values of an orderable \
type between two end-points, you can use a guard."
);
}
err.emit();
return None;
}
@ -435,6 +382,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(common_type)
}
fn emit_err_pat_range(
&self,
span: Span,
begin_span: Span,
end_span: Span,
lhs_fail: bool,
rhs_fail: bool,
lhs_ty: Ty<'tcx>,
rhs_ty: Ty<'tcx>,
) {
let span = if lhs_fail && rhs_fail {
span
} else if lhs_fail {
begin_span
} else {
end_span
};
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0029,
"only char and numeric types are allowed in range patterns"
);
let msg = |ty| {
format!("this is of type `{}` but it should be `char` or numeric", ty)
};
let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
err.span_label(first_span, &msg(first_ty));
if !second_ty.references_error() {
err.span_label(
second_span,
&format!("this is of type `{}`", second_ty)
);
}
};
if lhs_fail && rhs_fail {
err.span_label(begin_span, &msg(lhs_ty));
err.span_label(end_span, &msg(rhs_ty));
} else if lhs_fail {
one_side_err(begin_span, lhs_ty, end_span, rhs_ty);
} else {
one_side_err(end_span, rhs_ty, begin_span, lhs_ty);
}
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"In a match expression, only numbers and characters can be matched \
against a range. This is because the compiler checks that the range \
is non-empty at compile-time, and is unable to evaluate arbitrary \
comparison functions. If you want to capture values of an orderable \
type between two end-points, you can use a guard."
);
}
err.emit();
}
fn check_pat_ident(
&self,
pat: &Pat,