Rollup merge of #67730 - Centril:typeck-pat-cleanup, r=estebank
Cleanup pattern type checking, fix diagnostics bugs (+ improvements) r? @estebank
This commit is contained in:
commit
50fb8480db
50 changed files with 418 additions and 244 deletions
|
@ -581,10 +581,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
||||
) {
|
||||
match cause.code {
|
||||
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
|
||||
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
|
||||
let ty = self.resolve_vars_if_possible(&root_ty);
|
||||
if ty.is_suggestable() {
|
||||
// don't show type `_`
|
||||
err.span_label(span, format!("this match expression has type `{}`", ty));
|
||||
err.span_label(span, format!("this expression has type `{}`", ty));
|
||||
}
|
||||
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
|
||||
if ty.is_box() && ty.boxed_ty() == found {
|
||||
|
@ -599,11 +600,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
|
||||
err.span_label(span, "expected due to this");
|
||||
}
|
||||
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
|
||||
source,
|
||||
ref prior_arms,
|
||||
last_ty,
|
||||
discrim_hir_id,
|
||||
scrut_hir_id,
|
||||
..
|
||||
}) => match source {
|
||||
hir::MatchSource::IfLetDesugar { .. } => {
|
||||
|
@ -612,16 +616,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
hir::MatchSource::TryDesugar => {
|
||||
if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
|
||||
let discrim_expr = self.tcx.hir().expect_expr(discrim_hir_id);
|
||||
let discrim_ty = if let hir::ExprKind::Call(_, args) = &discrim_expr.kind {
|
||||
let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
|
||||
let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
|
||||
let arg_expr = args.first().expect("try desugaring call w/out arg");
|
||||
self.in_progress_tables
|
||||
.and_then(|tables| tables.borrow().expr_ty_opt(arg_expr))
|
||||
} else {
|
||||
bug!("try desugaring w/out call expr as discriminant");
|
||||
bug!("try desugaring w/out call expr as scrutinee");
|
||||
};
|
||||
|
||||
match discrim_ty {
|
||||
match scrut_ty {
|
||||
Some(ty) if expected == ty => {
|
||||
let source_map = self.tcx.sess.source_map();
|
||||
err.span_suggestion(
|
||||
|
|
|
@ -2580,7 +2580,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
match *cause_code {
|
||||
ObligationCauseCode::ExprAssignable
|
||||
| ObligationCauseCode::MatchExpressionArm { .. }
|
||||
| ObligationCauseCode::MatchExpressionArmPattern { .. }
|
||||
| ObligationCauseCode::Pattern { .. }
|
||||
| ObligationCauseCode::IfExpression { .. }
|
||||
| ObligationCauseCode::IfExpressionWithNoElse
|
||||
| ObligationCauseCode::MainFunctionType
|
||||
|
|
|
@ -249,10 +249,14 @@ 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>,
|
||||
/// Type error arising from type checking a pattern against an expected type.
|
||||
Pattern {
|
||||
/// The span of the scrutinee or type expression which caused the `root_ty` type.
|
||||
span: Option<Span>,
|
||||
/// The root expected type induced by a scrutinee or type expression.
|
||||
root_ty: Ty<'tcx>,
|
||||
/// Whether the `Span` came from an expression or a type expression.
|
||||
origin_expr: bool,
|
||||
},
|
||||
|
||||
/// Constants in patterns must have `Structural` type.
|
||||
|
@ -311,7 +315,7 @@ pub struct MatchExpressionArmCause<'tcx> {
|
|||
pub source: hir::MatchSource,
|
||||
pub prior_arms: Vec<Span>,
|
||||
pub last_ty: Ty<'tcx>,
|
||||
pub discrim_hir_id: hir::HirId,
|
||||
pub scrut_hir_id: hir::HirId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -511,18 +511,18 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
|||
source,
|
||||
ref prior_arms,
|
||||
last_ty,
|
||||
discrim_hir_id,
|
||||
scrut_hir_id,
|
||||
}) => tcx.lift(&last_ty).map(|last_ty| {
|
||||
super::MatchExpressionArm(box super::MatchExpressionArmCause {
|
||||
arm_span,
|
||||
source,
|
||||
prior_arms: prior_arms.clone(),
|
||||
last_ty,
|
||||
discrim_hir_id,
|
||||
scrut_hir_id,
|
||||
})
|
||||
}),
|
||||
super::MatchExpressionArmPattern { span, ty } => {
|
||||
tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
|
||||
super::Pattern { span, root_ty, origin_expr } => {
|
||||
tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
|
||||
}
|
||||
super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
|
||||
Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))
|
||||
|
|
|
@ -11,7 +11,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pub fn check_match(
|
||||
&self,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
discrim: &'tcx hir::Expr<'tcx>,
|
||||
scrut: &'tcx hir::Expr<'tcx>,
|
||||
arms: &'tcx [hir::Arm<'tcx>],
|
||||
expected: Expectation<'tcx>,
|
||||
match_src: hir::MatchSource,
|
||||
|
@ -27,7 +27,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
// Type check the descriminant and get its type.
|
||||
let discrim_ty = if force_scrutinee_bool {
|
||||
let scrut_ty = if force_scrutinee_bool {
|
||||
// Here we want to ensure:
|
||||
//
|
||||
// 1. That default match bindings are *not* accepted in the condition of an
|
||||
|
@ -36,9 +36,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
|
||||
//
|
||||
// FIXME(60707): Consider removing hack with principled solution.
|
||||
self.check_expr_has_type_or_error(discrim, self.tcx.types.bool, |_| {})
|
||||
self.check_expr_has_type_or_error(scrut, self.tcx.types.bool, |_| {})
|
||||
} else {
|
||||
self.demand_discriminant_type(arms, discrim)
|
||||
self.demand_scrutinee_type(arms, scrut)
|
||||
};
|
||||
|
||||
// If there are no arms, that is a diverging match; a special case.
|
||||
|
@ -51,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Otherwise, we have to union together the types that the
|
||||
// arms produce and so forth.
|
||||
let discrim_diverges = self.diverges.get();
|
||||
let scrut_diverges = self.diverges.get();
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
|
||||
// rust-lang/rust#55810: Typecheck patterns first (via eager
|
||||
|
@ -61,7 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.map(|arm| {
|
||||
let mut all_pats_diverge = Diverges::WarnedAlways;
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
self.check_pat_top(&arm.pat, discrim_ty, Some(discrim.span));
|
||||
self.check_pat_top(&arm.pat, scrut_ty, Some(scrut.span), true);
|
||||
all_pats_diverge &= self.diverges.get();
|
||||
|
||||
// As discussed with @eddyb, this is for disabling unreachable_code
|
||||
|
@ -157,7 +157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
source: match_src,
|
||||
prior_arms: other_arms.clone(),
|
||||
last_ty: prior_arm_ty.unwrap(),
|
||||
discrim_hir_id: discrim.hir_id,
|
||||
scrut_hir_id: scrut.hir_id,
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
@ -186,8 +186,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
}
|
||||
|
||||
// We won't diverge unless the discriminant or all arms diverge.
|
||||
self.diverges.set(discrim_diverges | all_arms_diverge);
|
||||
// We won't diverge unless the scrutinee or all arms diverge.
|
||||
self.diverges.set(scrut_diverges | all_arms_diverge);
|
||||
|
||||
coercion.complete(self)
|
||||
}
|
||||
|
@ -388,14 +388,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
fn demand_discriminant_type(
|
||||
fn demand_scrutinee_type(
|
||||
&self,
|
||||
arms: &'tcx [hir::Arm<'tcx>],
|
||||
discrim: &'tcx hir::Expr<'tcx>,
|
||||
scrut: &'tcx hir::Expr<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
// Not entirely obvious: if matches may create ref bindings, we want to
|
||||
// use the *precise* type of the discriminant, *not* some supertype, as
|
||||
// the "discriminant type" (issue #23116).
|
||||
// use the *precise* type of the scrutinee, *not* some supertype, as
|
||||
// the "scrutinee type" (issue #23116).
|
||||
//
|
||||
// arielb1 [writes here in this comment thread][c] that there
|
||||
// is certainly *some* potential danger, e.g., for an example
|
||||
|
@ -454,17 +454,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
});
|
||||
|
||||
if let Some(m) = contains_ref_bindings {
|
||||
self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
|
||||
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
|
||||
} else {
|
||||
// ...but otherwise we want to use any supertype of the
|
||||
// discriminant. This is sort of a workaround, see note (*) in
|
||||
// scrutinee. This is sort of a workaround, see note (*) in
|
||||
// `check_pat` for some details.
|
||||
let discrim_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
let scrut_ty = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: discrim.span,
|
||||
span: scrut.span,
|
||||
});
|
||||
self.check_expr_has_type_or_error(discrim, discrim_ty, |_| {});
|
||||
discrim_ty
|
||||
self.check_expr_has_type_or_error(scrut, scrut_ty, |_| {});
|
||||
scrut_ty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::check::FnCtxt;
|
||||
use rustc::infer::InferOk;
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
||||
use rustc::traits::{self, ObligationCause};
|
||||
|
||||
use errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc::hir::{self, is_range_literal, print, Node};
|
||||
|
@ -79,35 +79,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn demand_eqtype_pat_diag(
|
||||
&self,
|
||||
cause_span: Span,
|
||||
expected: Ty<'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)
|
||||
};
|
||||
self.demand_eqtype_with_origin(&cause, expected, actual)
|
||||
}
|
||||
|
||||
pub fn demand_eqtype_pat(
|
||||
&self,
|
||||
cause_span: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
match_expr_span: Option<Span>,
|
||||
) {
|
||||
self.demand_eqtype_pat_diag(cause_span, expected, actual, match_expr_span)
|
||||
.map(|mut err| err.emit());
|
||||
}
|
||||
|
||||
pub fn demand_coerce(
|
||||
&self,
|
||||
expr: &hir::Expr<'_>,
|
||||
|
|
|
@ -1268,13 +1268,17 @@ fn check_fn<'a, 'tcx>(
|
|||
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
|
||||
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
|
||||
|
||||
let tcx = fcx.tcx;
|
||||
let sess = tcx.sess;
|
||||
let hir = tcx.hir();
|
||||
|
||||
let declared_ret_ty = fn_sig.output();
|
||||
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
|
||||
let revealed_ret_ty =
|
||||
fcx.instantiate_opaque_types_from_value(fn_id, &declared_ret_ty, decl.output.span());
|
||||
debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty);
|
||||
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
|
||||
fn_sig = fcx.tcx.mk_fn_sig(
|
||||
fn_sig = tcx.mk_fn_sig(
|
||||
fn_sig.inputs().iter().cloned(),
|
||||
revealed_ret_ty,
|
||||
fn_sig.c_variadic,
|
||||
|
@ -1284,7 +1288,7 @@ fn check_fn<'a, 'tcx>(
|
|||
|
||||
let span = body.value.span;
|
||||
|
||||
fn_maybe_err(fcx.tcx, span, fn_sig.abi);
|
||||
fn_maybe_err(tcx, span, fn_sig.abi);
|
||||
|
||||
if body.generator_kind.is_some() && can_be_generator.is_some() {
|
||||
let yield_ty = fcx
|
||||
|
@ -1293,37 +1297,39 @@ fn check_fn<'a, 'tcx>(
|
|||
fcx.yield_ty = Some(yield_ty);
|
||||
}
|
||||
|
||||
let outer_def_id = fcx.tcx.closure_base_def_id(fcx.tcx.hir().local_def_id(fn_id));
|
||||
let outer_hir_id = fcx.tcx.hir().as_local_hir_id(outer_def_id).unwrap();
|
||||
let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id));
|
||||
let outer_hir_id = hir.as_local_hir_id(outer_def_id).unwrap();
|
||||
GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id }.visit_body(body);
|
||||
|
||||
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
|
||||
// (as it's created inside the body itself, not passed in from outside).
|
||||
let maybe_va_list = if fn_sig.c_variadic {
|
||||
let va_list_did = fcx.tcx.require_lang_item(
|
||||
let va_list_did = tcx.require_lang_item(
|
||||
lang_items::VaListTypeLangItem,
|
||||
Some(body.params.last().unwrap().span),
|
||||
);
|
||||
let region = fcx.tcx.mk_region(ty::ReScope(region::Scope {
|
||||
let region = tcx.mk_region(ty::ReScope(region::Scope {
|
||||
id: body.value.hir_id.local_id,
|
||||
data: region::ScopeData::CallSite,
|
||||
}));
|
||||
|
||||
Some(fcx.tcx.type_of(va_list_did).subst(fcx.tcx, &[region.into()]))
|
||||
Some(tcx.type_of(va_list_did).subst(tcx, &[region.into()]))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Add formal parameters.
|
||||
for (param_ty, param) in fn_sig.inputs().iter().copied().chain(maybe_va_list).zip(body.params) {
|
||||
let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
|
||||
let inputs_fn = fn_sig.inputs().iter().copied();
|
||||
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
|
||||
// Check the pattern.
|
||||
fcx.check_pat_top(¶m.pat, param_ty, None);
|
||||
fcx.check_pat_top(¶m.pat, param_ty, try { inputs_hir?.get(idx)?.span }, false);
|
||||
|
||||
// Check that argument is Sized.
|
||||
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
|
||||
// for simple cases like `fn foo(x: Trait)`,
|
||||
// where we would error once on the parameter as a whole, and once on the binding `x`.
|
||||
if param.pat.simple_ident().is_none() && !fcx.tcx.features().unsized_locals {
|
||||
if param.pat.simple_ident().is_none() && !tcx.features().unsized_locals {
|
||||
fcx.require_type_is_sized(param_ty, decl.output.span(), traits::SizedArgumentType);
|
||||
}
|
||||
|
||||
|
@ -1384,11 +1390,11 @@ fn check_fn<'a, 'tcx>(
|
|||
fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
|
||||
|
||||
// Check that the main return type implements the termination trait.
|
||||
if let Some(term_id) = fcx.tcx.lang_items().termination() {
|
||||
if let Some((def_id, EntryFnType::Main)) = fcx.tcx.entry_fn(LOCAL_CRATE) {
|
||||
let main_id = fcx.tcx.hir().as_local_hir_id(def_id).unwrap();
|
||||
if let Some(term_id) = tcx.lang_items().termination() {
|
||||
if let Some((def_id, EntryFnType::Main)) = tcx.entry_fn(LOCAL_CRATE) {
|
||||
let main_id = hir.as_local_hir_id(def_id).unwrap();
|
||||
if main_id == fn_id {
|
||||
let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
|
||||
let substs = tcx.mk_substs_trait(declared_ret_ty, &[]);
|
||||
let trait_ref = ty::TraitRef::new(term_id, substs);
|
||||
let return_ty_span = decl.output.span();
|
||||
let cause = traits::ObligationCause::new(
|
||||
|
@ -1407,15 +1413,15 @@ fn check_fn<'a, 'tcx>(
|
|||
}
|
||||
|
||||
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
|
||||
if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() {
|
||||
if panic_impl_did == fcx.tcx.hir().local_def_id(fn_id) {
|
||||
if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() {
|
||||
if let Some(panic_impl_did) = tcx.lang_items().panic_impl() {
|
||||
if panic_impl_did == hir.local_def_id(fn_id) {
|
||||
if let Some(panic_info_did) = tcx.lang_items().panic_info() {
|
||||
if declared_ret_ty.kind != ty::Never {
|
||||
fcx.tcx.sess.span_err(decl.output.span(), "return type should be `!`");
|
||||
sess.span_err(decl.output.span(), "return type should be `!`");
|
||||
}
|
||||
|
||||
let inputs = fn_sig.inputs();
|
||||
let span = fcx.tcx.hir().span(fn_id);
|
||||
let span = hir.span(fn_id);
|
||||
if inputs.len() == 1 {
|
||||
let arg_is_panic_info = match inputs[0].kind {
|
||||
ty::Ref(region, ty, mutbl) => match ty.kind {
|
||||
|
@ -1430,38 +1436,36 @@ fn check_fn<'a, 'tcx>(
|
|||
};
|
||||
|
||||
if !arg_is_panic_info {
|
||||
fcx.tcx
|
||||
.sess
|
||||
.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
|
||||
sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
|
||||
}
|
||||
|
||||
if let Node::Item(item) = fcx.tcx.hir().get(fn_id) {
|
||||
if let Node::Item(item) = hir.get(fn_id) {
|
||||
if let ItemKind::Fn(_, ref generics, _) = item.kind {
|
||||
if !generics.params.is_empty() {
|
||||
fcx.tcx.sess.span_err(span, "should have no type parameters");
|
||||
sess.span_err(span, "should have no type parameters");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let span = fcx.tcx.sess.source_map().def_span(span);
|
||||
fcx.tcx.sess.span_err(span, "function should have one argument");
|
||||
let span = sess.source_map().def_span(span);
|
||||
sess.span_err(span, "function should have one argument");
|
||||
}
|
||||
} else {
|
||||
fcx.tcx.sess.err("language item required, but not found: `panic_info`");
|
||||
sess.err("language item required, but not found: `panic_info`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
|
||||
if let Some(alloc_error_handler_did) = fcx.tcx.lang_items().oom() {
|
||||
if alloc_error_handler_did == fcx.tcx.hir().local_def_id(fn_id) {
|
||||
if let Some(alloc_layout_did) = fcx.tcx.lang_items().alloc_layout() {
|
||||
if let Some(alloc_error_handler_did) = tcx.lang_items().oom() {
|
||||
if alloc_error_handler_did == hir.local_def_id(fn_id) {
|
||||
if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() {
|
||||
if declared_ret_ty.kind != ty::Never {
|
||||
fcx.tcx.sess.span_err(decl.output.span(), "return type should be `!`");
|
||||
sess.span_err(decl.output.span(), "return type should be `!`");
|
||||
}
|
||||
|
||||
let inputs = fn_sig.inputs();
|
||||
let span = fcx.tcx.hir().span(fn_id);
|
||||
let span = hir.span(fn_id);
|
||||
if inputs.len() == 1 {
|
||||
let arg_is_alloc_layout = match inputs[0].kind {
|
||||
ty::Adt(ref adt, _) => adt.did == alloc_layout_did,
|
||||
|
@ -1469,13 +1473,13 @@ fn check_fn<'a, 'tcx>(
|
|||
};
|
||||
|
||||
if !arg_is_alloc_layout {
|
||||
fcx.tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
|
||||
sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
|
||||
}
|
||||
|
||||
if let Node::Item(item) = fcx.tcx.hir().get(fn_id) {
|
||||
if let Node::Item(item) = hir.get(fn_id) {
|
||||
if let ItemKind::Fn(_, ref generics, _) = item.kind {
|
||||
if !generics.params.is_empty() {
|
||||
fcx.tcx.sess.span_err(
|
||||
sess.span_err(
|
||||
span,
|
||||
"`#[alloc_error_handler]` function should have no type \
|
||||
parameters",
|
||||
|
@ -1484,11 +1488,11 @@ fn check_fn<'a, 'tcx>(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let span = fcx.tcx.sess.source_map().def_span(span);
|
||||
fcx.tcx.sess.span_err(span, "function should have one argument");
|
||||
let span = sess.source_map().def_span(span);
|
||||
sess.span_err(span, "function should have one argument");
|
||||
}
|
||||
} else {
|
||||
fcx.tcx.sess.err("language item required, but not found: `alloc_layout`");
|
||||
sess.err("language item required, but not found: `alloc_layout`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4304,18 +4308,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Type check a `let` statement.
|
||||
pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
|
||||
let t = self.local_ty(local.span, local.hir_id).decl_ty;
|
||||
self.write_ty(local.hir_id, t);
|
||||
// Determine and write the type which we'll check the pattern against.
|
||||
let ty = self.local_ty(local.span, local.hir_id).decl_ty;
|
||||
self.write_ty(local.hir_id, ty);
|
||||
|
||||
// Type check the initializer.
|
||||
if let Some(ref init) = local.init {
|
||||
let init_ty = self.check_decl_initializer(local, &init);
|
||||
self.overwrite_local_ty_if_err(local, t, init_ty);
|
||||
self.overwrite_local_ty_if_err(local, ty, init_ty);
|
||||
}
|
||||
|
||||
self.check_pat_top(&local.pat, t, None);
|
||||
// Does the expected pattern type originate from an expression and what is the span?
|
||||
let (origin_expr, ty_span) = match (local.ty, local.init) {
|
||||
(Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
|
||||
(_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee.
|
||||
_ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
|
||||
};
|
||||
|
||||
// Type check the pattern. Override if necessary to avoid knock-on errors.
|
||||
self.check_pat_top(&local.pat, ty, ty_span, origin_expr);
|
||||
let pat_ty = self.node_ty(local.pat.hir_id);
|
||||
self.overwrite_local_ty_if_err(local, t, pat_ty);
|
||||
self.overwrite_local_ty_if_err(local, ty, pat_ty);
|
||||
}
|
||||
|
||||
fn overwrite_local_ty_if_err(
|
||||
|
@ -4325,7 +4340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ty: Ty<'tcx>,
|
||||
) {
|
||||
if ty.references_error() {
|
||||
// Override the types everywhere with `types.err` to avoid knock down errors.
|
||||
// Override the types everywhere with `types.err` to avoid knock on errors.
|
||||
self.write_ty(local.hir_id, ty);
|
||||
self.write_ty(local.pat.hir_id, ty);
|
||||
let local_ty = LocalTy { decl_ty, revealed_ty: ty };
|
||||
|
|
|
@ -6,6 +6,7 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
|||
use rustc::hir::{self, HirId, Pat, PatKind};
|
||||
use rustc::infer;
|
||||
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc::traits::Pattern;
|
||||
use rustc::ty::subst::GenericArg;
|
||||
use rustc::ty::{self, BindingMode, Ty, TypeFoldable};
|
||||
use syntax::ast;
|
||||
|
@ -29,39 +30,97 @@ pointers. If you encounter this error you should try to avoid dereferencing the
|
|||
You can read more about trait objects in the Trait Objects section of the Reference: \
|
||||
https://doc.rust-lang.org/reference/types.html#trait-objects";
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn check_pat_top(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
/// Information about the expected type at the top level of type checking a pattern.
|
||||
///
|
||||
/// **NOTE:** This is only for use by diagnostics. Do NOT use for type checking logic!
|
||||
#[derive(Copy, Clone)]
|
||||
struct TopInfo<'tcx> {
|
||||
/// The `expected` type at the top level of type checking a pattern.
|
||||
expected: Ty<'tcx>,
|
||||
discrim_span: Option<Span>,
|
||||
) {
|
||||
let def_bm = BindingMode::BindByValue(hir::Mutability::Not);
|
||||
self.check_pat(pat, expected, def_bm, discrim_span);
|
||||
}
|
||||
|
||||
/// `discrim_span` argument having a `Span` indicates that this pattern is part of a match
|
||||
/// expression arm guard, and it points to the match discriminant to add context in type errors.
|
||||
/// In the following example, `discrim_span` corresponds to the `a + b` expression:
|
||||
/// Was the origin of the `span` from a scrutinee expression?
|
||||
///
|
||||
/// Otherwise there is no scrutinee and it could be e.g. from the type of a formal parameter.
|
||||
origin_expr: bool,
|
||||
/// The span giving rise to the `expected` type, if one could be provided.
|
||||
///
|
||||
/// If `origin_expr` is `true`, then this is the span of the scrutinee as in:
|
||||
///
|
||||
/// - `match scrutinee { ... }`
|
||||
/// - `let _ = scrutinee;`
|
||||
///
|
||||
/// This is used to point to add context in type errors.
|
||||
/// In the following example, `span` corresponds to the `a + b` expression:
|
||||
///
|
||||
/// ```text
|
||||
/// error[E0308]: mismatched types
|
||||
/// --> src/main.rs:5:9
|
||||
/// --> src/main.rs:L:C
|
||||
/// |
|
||||
/// 4 | let temp: usize = match a + b {
|
||||
/// L | let temp: usize = match a + b {
|
||||
/// | ----- this expression has type `usize`
|
||||
/// 5 | Ok(num) => num,
|
||||
/// L | Ok(num) => num,
|
||||
/// | ^^^^^^^ expected `usize`, found enum `std::result::Result`
|
||||
/// |
|
||||
/// = note: expected type `usize`
|
||||
/// found type `std::result::Result<_, _>`
|
||||
/// ```
|
||||
span: Option<Span>,
|
||||
}
|
||||
|
||||
impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
fn demand_eqtype_pat_diag(
|
||||
&self,
|
||||
cause_span: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
let code = Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr };
|
||||
let cause = self.cause(cause_span, code);
|
||||
self.demand_eqtype_with_origin(&cause, expected, actual)
|
||||
}
|
||||
|
||||
fn demand_eqtype_pat(
|
||||
&self,
|
||||
cause_span: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) {
|
||||
self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map(|mut err| err.emit());
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Type check the given top level pattern against the `expected` type.
|
||||
///
|
||||
/// If a `Some(span)` is provided and `origin_expr` holds,
|
||||
/// then the `span` represents the scrutinee's span.
|
||||
/// The scrutinee is found in e.g. `match scrutinee { ... }` and `let pat = scrutinee;`.
|
||||
///
|
||||
/// Otherwise, `Some(span)` represents the span of a type expression
|
||||
/// which originated the `expected` type.
|
||||
pub fn check_pat_top(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
span: Option<Span>,
|
||||
origin_expr: bool,
|
||||
) {
|
||||
let def_bm = BindingMode::BindByValue(hir::Mutability::Not);
|
||||
self.check_pat(pat, expected, def_bm, TopInfo { expected, origin_expr, span });
|
||||
}
|
||||
|
||||
/// Type check the given `pat` against the `expected` type
|
||||
/// with the provided `def_bm` (default binding mode).
|
||||
///
|
||||
/// Outside of this module, `check_pat_top` should always be used.
|
||||
/// Conversely, inside this module, `check_pat_top` should never be used.
|
||||
fn check_pat(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) {
|
||||
debug!("check_pat(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
|
||||
|
||||
|
@ -72,60 +131,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let is_nrp = self.is_non_ref_pat(pat, path_resolution.map(|(res, ..)| res));
|
||||
let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, is_nrp);
|
||||
|
||||
let ty = match &pat.kind {
|
||||
let ty = match pat.kind {
|
||||
PatKind::Wild => expected,
|
||||
PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, discrim_span),
|
||||
PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
|
||||
PatKind::Range(begin, end, _) => {
|
||||
match self.check_pat_range(pat.span, begin, end, expected, discrim_span) {
|
||||
match self.check_pat_range(pat.span, begin, end, expected, ti) {
|
||||
None => return,
|
||||
Some(ty) => ty,
|
||||
}
|
||||
}
|
||||
PatKind::Binding(ba, var_id, _, sub) => {
|
||||
let sub = sub.as_deref();
|
||||
self.check_pat_ident(pat, *ba, *var_id, sub, expected, def_bm, discrim_span)
|
||||
self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, ti)
|
||||
}
|
||||
PatKind::TupleStruct(qpath, subpats, ddpos) => self.check_pat_tuple_struct(
|
||||
pat,
|
||||
qpath,
|
||||
subpats,
|
||||
*ddpos,
|
||||
expected,
|
||||
def_bm,
|
||||
discrim_span,
|
||||
),
|
||||
PatKind::Path(qpath) => {
|
||||
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
|
||||
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti)
|
||||
}
|
||||
PatKind::Path(ref qpath) => {
|
||||
self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected)
|
||||
}
|
||||
PatKind::Struct(qpath, fields, etc) => {
|
||||
self.check_pat_struct(pat, qpath, fields, *etc, expected, def_bm, discrim_span)
|
||||
PatKind::Struct(ref qpath, fields, etc) => {
|
||||
self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti)
|
||||
}
|
||||
PatKind::Or(pats) => {
|
||||
for pat in *pats {
|
||||
self.check_pat(pat, expected, def_bm, discrim_span);
|
||||
for pat in pats {
|
||||
self.check_pat(pat, expected, def_bm, ti);
|
||||
}
|
||||
expected
|
||||
}
|
||||
PatKind::Tuple(elements, ddpos) => {
|
||||
self.check_pat_tuple(pat.span, *elements, *ddpos, expected, def_bm, discrim_span)
|
||||
}
|
||||
PatKind::Box(inner) => {
|
||||
self.check_pat_box(pat.span, inner, expected, def_bm, discrim_span)
|
||||
self.check_pat_tuple(pat.span, elements, ddpos, expected, def_bm, ti)
|
||||
}
|
||||
PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, def_bm, ti),
|
||||
PatKind::Ref(inner, mutbl) => {
|
||||
self.check_pat_ref(pat, inner, *mutbl, expected, def_bm, discrim_span)
|
||||
self.check_pat_ref(pat, inner, mutbl, expected, def_bm, ti)
|
||||
}
|
||||
PatKind::Slice(before, slice, after) => {
|
||||
let slice = slice.as_deref();
|
||||
self.check_pat_slice(
|
||||
pat.span,
|
||||
*before,
|
||||
slice,
|
||||
*after,
|
||||
expected,
|
||||
def_bm,
|
||||
discrim_span,
|
||||
)
|
||||
self.check_pat_slice(pat.span, before, slice, after, expected, def_bm, ti)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -302,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span: Span,
|
||||
lt: &hir::Expr<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
// We've already computed the type above (when checking for a non-ref pat),
|
||||
// so avoid computing it again.
|
||||
|
@ -336,7 +377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// then that's equivalent to there existing a LUB.
|
||||
if let Some(mut err) = self.demand_suptype_diag(span, expected, pat_ty) {
|
||||
err.emit_unless(
|
||||
discrim_span
|
||||
ti.span
|
||||
.filter(|&s| {
|
||||
// In the case of `if`- and `while`-expressions we've already checked
|
||||
// that `scrutinee: bool`. We know that the pattern is `true`,
|
||||
|
@ -356,7 +397,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
lhs: &'tcx hir::Expr<'tcx>,
|
||||
rhs: &'tcx hir::Expr<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
let lhs_ty = self.check_expr(lhs);
|
||||
let rhs_ty = self.check_expr(rhs);
|
||||
|
@ -377,7 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Subtyping doesn't matter here, as the value is some kind of scalar.
|
||||
let demand_eqtype = |x_span, y_span, x_ty, y_ty| {
|
||||
self.demand_eqtype_pat_diag(x_span, expected, x_ty, discrim_span).map(|mut err| {
|
||||
self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
|
||||
self.endpoint_has_type(&mut err, y_span, y_ty);
|
||||
err.emit();
|
||||
});
|
||||
|
@ -451,7 +492,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
sub: Option<&'tcx Pat<'tcx>>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
// Determine the binding mode...
|
||||
let bm = match ba {
|
||||
|
@ -481,17 +522,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expected
|
||||
}
|
||||
};
|
||||
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, discrim_span);
|
||||
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
|
||||
|
||||
// If there are multiple arms, make sure they all agree on
|
||||
// what the type of the binding `x` ought to be.
|
||||
if var_id != pat.hir_id {
|
||||
let vt = self.local_ty(pat.span, var_id).decl_ty;
|
||||
self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
|
||||
self.demand_eqtype_pat(pat.span, vt, local_ty, ti);
|
||||
}
|
||||
|
||||
if let Some(p) = sub {
|
||||
self.check_pat(&p, expected, def_bm, discrim_span);
|
||||
self.check_pat(&p, expected, def_bm, ti);
|
||||
}
|
||||
|
||||
local_ty
|
||||
|
@ -570,7 +611,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
etc: bool,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
// Resolve the path and check the definition for errors.
|
||||
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
|
||||
|
@ -578,16 +619,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
variant_ty
|
||||
} else {
|
||||
for field in fields {
|
||||
self.check_pat(&field.pat, self.tcx.types.err, def_bm, discrim_span);
|
||||
self.check_pat(&field.pat, self.tcx.types.err, def_bm, ti);
|
||||
}
|
||||
return self.tcx.types.err;
|
||||
};
|
||||
|
||||
// Type-check the path.
|
||||
self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span);
|
||||
self.demand_eqtype_pat(pat.span, expected, pat_ty, ti);
|
||||
|
||||
// Type-check subpatterns.
|
||||
if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
|
||||
if self
|
||||
.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm, ti)
|
||||
{
|
||||
pat_ty
|
||||
} else {
|
||||
|
@ -638,12 +680,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ddpos: Option<usize>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
match_arm_pat_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let on_error = || {
|
||||
for pat in subpats {
|
||||
self.check_pat(&pat, tcx.types.err, def_bm, match_arm_pat_span);
|
||||
self.check_pat(&pat, tcx.types.err, def_bm, ti);
|
||||
}
|
||||
};
|
||||
let report_unexpected_res = |res: Res| {
|
||||
|
@ -704,7 +746,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
|
||||
|
||||
// Type-check the tuple struct pattern against the expected type.
|
||||
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, match_arm_pat_span);
|
||||
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti);
|
||||
let had_err = diag.is_some();
|
||||
diag.map(|mut err| err.emit());
|
||||
|
||||
|
@ -718,7 +760,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
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);
|
||||
self.check_pat(&subpat, field_ty, def_bm, match_arm_pat_span);
|
||||
self.check_pat(&subpat, field_ty, def_bm, ti);
|
||||
|
||||
self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
|
||||
}
|
||||
|
@ -822,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ddpos: Option<usize>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let mut expected_len = elements.len();
|
||||
|
@ -849,12 +891,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// further errors being emitted when using the bindings. #50333
|
||||
let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
|
||||
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat(elem, &tcx.types.err, def_bm, discrim_span);
|
||||
self.check_pat(elem, &tcx.types.err, def_bm, ti);
|
||||
}
|
||||
tcx.mk_tup(element_tys_iter)
|
||||
} else {
|
||||
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat(elem, &element_tys[i].expect_ty(), def_bm, discrim_span);
|
||||
self.check_pat(elem, &element_tys[i].expect_ty(), def_bm, ti);
|
||||
}
|
||||
pat_ty
|
||||
}
|
||||
|
@ -869,6 +911,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
fields: &'tcx [hir::FieldPat<'tcx>],
|
||||
etc: bool,
|
||||
def_bm: BindingMode,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> bool {
|
||||
let tcx = self.tcx;
|
||||
|
||||
|
@ -918,7 +961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
self.check_pat(&field.pat, field_ty, def_bm, None);
|
||||
self.check_pat(&field.pat, field_ty, def_bm, ti);
|
||||
}
|
||||
|
||||
let mut unmentioned_fields = variant
|
||||
|
@ -1095,7 +1138,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
inner: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let (box_ty, inner_ty) = if self.check_dereferenceable(span, expected, &inner) {
|
||||
|
@ -1106,12 +1149,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span: inner.span,
|
||||
});
|
||||
let box_ty = tcx.mk_box(inner_ty);
|
||||
self.demand_eqtype_pat(span, expected, box_ty, discrim_span);
|
||||
self.demand_eqtype_pat(span, expected, box_ty, ti);
|
||||
(box_ty, inner_ty)
|
||||
} else {
|
||||
(tcx.types.err, tcx.types.err)
|
||||
};
|
||||
self.check_pat(&inner, inner_ty, def_bm, discrim_span);
|
||||
self.check_pat(&inner, inner_ty, def_bm, ti);
|
||||
box_ty
|
||||
}
|
||||
|
||||
|
@ -1122,7 +1165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
mutbl: hir::Mutability,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let expected = self.shallow_resolve(expected);
|
||||
|
@ -1157,7 +1200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
(tcx.types.err, tcx.types.err)
|
||||
};
|
||||
self.check_pat(&inner, inner_ty, def_bm, discrim_span);
|
||||
self.check_pat(&inner, inner_ty, def_bm, ti);
|
||||
rptr_ty
|
||||
}
|
||||
|
||||
|
@ -1186,7 +1229,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
after: &'tcx [&'tcx Pat<'tcx>],
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
discrim_span: Option<Span>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let err = self.tcx.types.err;
|
||||
let expected = self.structurally_resolved_type(span, expected);
|
||||
|
@ -1211,15 +1254,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Type check all the patterns before `slice`.
|
||||
for elt in before {
|
||||
self.check_pat(&elt, inner_ty, def_bm, discrim_span);
|
||||
self.check_pat(&elt, inner_ty, def_bm, ti);
|
||||
}
|
||||
// Type check the `slice`, if present, against its expected type.
|
||||
if let Some(slice) = slice {
|
||||
self.check_pat(&slice, slice_ty, def_bm, discrim_span);
|
||||
self.check_pat(&slice, slice_ty, def_bm, ti);
|
||||
}
|
||||
// Type check the elements after `slice`, if present.
|
||||
for elt in after {
|
||||
self.check_pat(&elt, inner_ty, def_bm, discrim_span);
|
||||
self.check_pat(&elt, inner_ty, def_bm, ti);
|
||||
}
|
||||
expected
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ This API is completely unstable and subject to change.
|
|||
#![feature(in_band_lifetimes)]
|
||||
#![feature(nll)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(never_type)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
|
|
|
@ -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 expression has type `()`
|
||||
LL | a::Enum::EnumStructVariant { x, y, z } => {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `a::Enum`
|
||||
|
||||
|
|
|
@ -44,7 +44,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/destructure-trait-ref.rs:42:13
|
||||
|
|
||||
LL | let box box x = box 1isize as Box<dyn T>;
|
||||
| ^^^^^ expected trait `T`, found struct `std::boxed::Box`
|
||||
| ^^^^^ ------------------------ this expression has type `std::boxed::Box<dyn T>`
|
||||
| |
|
||||
| expected trait `T`, found struct `std::boxed::Box`
|
||||
|
|
||||
= note: expected trait object `dyn T`
|
||||
found struct `std::boxed::Box<_>`
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/E0308-4.rs:4:15
|
||||
|
|
||||
LL | match x {
|
||||
| - this match expression has type `u8`
|
||||
| - this expression has type `u8`
|
||||
LL | 0u8..=3i8 => (),
|
||||
| --- ^^^ expected `u8`, found `i8`
|
||||
| |
|
||||
|
|
|
@ -8,7 +8,7 @@ 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 expression has type `[std::ops::Range<{integer}>; 3]`
|
||||
LL | [_, 99.., _] => {},
|
||||
| ^^ expected struct `std::ops::Range`, found integer
|
||||
|
|
||||
|
|
|
@ -14,7 +14,7 @@ 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 expression has type `[std::ops::Range<{integer}>; 3]`
|
||||
LL | [_, 99..] => {},
|
||||
| ^^ expected struct `std::ops::Range`, found integer
|
||||
|
|
||||
|
|
|
@ -8,7 +8,7 @@ error[E0308]: mismatched types
|
|||
--> $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 expression has type `[std::ops::Range<{integer}>; 3]`
|
||||
LL | [..9, 99..100, _] => {},
|
||||
| ^ expected struct `std::ops::Range`, found 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 expression has type `[std::ops::Range<{integer}>; 3]`
|
||||
LL | [..9, 99..100, _] => {},
|
||||
| ^^ --- this is of type `{integer}`
|
||||
| |
|
||||
|
@ -32,7 +32,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
|
||||
|
|
||||
LL | match [5..4, 99..105, 43..44] {
|
||||
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
|
||||
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
|
||||
LL | [..9, 99..100, _] => {},
|
||||
| -- ^^^ expected struct `std::ops::Range`, found integer
|
||||
| |
|
||||
|
|
|
@ -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 expression has type `std::option::Option<std::boxed::Box<{integer}>>`
|
||||
LL | Ok(a) =>
|
||||
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
||||
|
|
|
@ -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 expression has type `std::result::Result<_, {integer}>`
|
||||
LL | Some(k) => match k {
|
||||
| ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
|
||||
|
|
||||
|
|
|
@ -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 expression has 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 expression has type `std::option::Option<{integer}>`
|
||||
...
|
||||
LL | Err(e) => panic!(e)
|
||||
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
|
@ -2,7 +2,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-14541.rs:5:9
|
||||
|
|
||||
LL | let Vec3 { y: _, z: _ } = v;
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found struct `Vec3`
|
||||
| ^^^^^^^^^^^^^^^^^^^ - this expression has type `Vec2`
|
||||
| |
|
||||
| expected struct `Vec2`, found struct `Vec3`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -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 expression has type `main::E`
|
||||
LL | E::B(
|
||||
LL | Tau{t: x},
|
||||
| ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau`
|
||||
|
|
|
@ -2,7 +2,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-16338.rs:7:9
|
||||
|
|
||||
LL | let Slice { data: data, len: len } = "foo";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `str`, found struct `Slice`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----- this expression has type `&str`
|
||||
| |
|
||||
| expected `str`, found struct `Slice`
|
||||
|
|
||||
= note: expected type `str`
|
||||
found struct `Slice<_>`
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-16401.rs:8:9
|
||||
|
|
||||
LL | match () {
|
||||
| -- this match expression has type `()`
|
||||
| -- this expression has type `()`
|
||||
LL | Slice { data: data, len: len } => (),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Slice`
|
||||
|
|
||||
|
|
|
@ -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 expression has type `std::option::Option<_>`
|
||||
LL | Err(_) => ()
|
||||
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
||||
|
|
|
@ -8,7 +8,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-37026.rs:7:9
|
||||
|
|
||||
LL | let empty_struct::XEmpty6(..) = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `empty_struct::XEmpty6`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ -- this expression has type `()`
|
||||
| |
|
||||
| expected `()`, found struct `empty_struct::XEmpty6`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -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 expression has type `(bool, bool)`
|
||||
LL | box (true, false) => ()
|
||||
| ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box`
|
||||
|
|
||||
|
|
|
@ -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 expression has type `S`
|
||||
LL | Either::Right(_) => {}
|
||||
| ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
|
||||
|
|
||||
|
|
|
@ -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 expression has 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 expression has type `std::boxed::Box<u32>`
|
||||
LL | S::A { a } | S::B { b: a } => a,
|
||||
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|
||||
|
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0308]: mismatched types
|
|||
LL | let y = match x {
|
||||
| -
|
||||
| |
|
||||
| this match expression has type `std::boxed::Box<T>`
|
||||
| this expression has 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 expression has 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 expression has 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 expression has 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,7 +2,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9
|
||||
|
|
||||
LL | let P() = U {};
|
||||
| ^^^ expected struct `U`, found struct `P`
|
||||
| ^^^ ---- this expression has type `U`
|
||||
| |
|
||||
| expected struct `U`, found struct `P`
|
||||
|
|
||||
= note: expected struct `U`
|
||||
found struct `P<_>`
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-7092.rs:6:9
|
||||
|
|
||||
LL | match x {
|
||||
| - this match expression has type `Whatever`
|
||||
| - this expression has type `Whatever`
|
||||
LL | Some(field) =>
|
||||
| ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option`
|
||||
|
|
||||
|
|
|
@ -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 expression has type `S`
|
||||
LL | E::C(_) => (),
|
||||
| ^^^^^^^ expected struct `S`, found enum `E`
|
||||
|
||||
|
|
|
@ -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 expression has type `A`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ LL | (0, ref y) | (y, 0) => {}
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/E0409.rs:5:23
|
||||
|
|
||||
LL | match x {
|
||||
| - this expression has type `({integer}, {integer})`
|
||||
LL | (0, ref y) | (y, 0) => {}
|
||||
| ^ expected `&{integer}`, found integer
|
||||
|
||||
|
|
|
@ -94,7 +94,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/already-bound-name.rs:33:31
|
||||
|
|
||||
LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
|
||||
| ^ expected integer, found enum `E`
|
||||
| ^ ------- this expression has type `E<E<{integer}>>`
|
||||
| |
|
||||
| expected integer, found enum `E`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found type `E<{integer}>`
|
||||
|
|
|
@ -60,7 +60,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/inconsistent-modes.rs:13:25
|
||||
|
|
||||
LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
|
||||
| ^^^^^^^^^ types differ in mutability
|
||||
| ^^^^^^^^^ -------------------- expected due to this
|
||||
| |
|
||||
| types differ in mutability
|
||||
|
|
||||
= note: expected type `&&u8`
|
||||
found type `&mut &mut u8`
|
||||
|
@ -69,7 +71,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/inconsistent-modes.rs:16:31
|
||||
|
|
||||
LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
|
||||
| ^^^^^^^^^ types differ in mutability
|
||||
| ^^^^^^^^^ ----------- this expression has type `std::result::Result<({integer}, &{integer}), (_, _)>`
|
||||
| |
|
||||
| types differ in mutability
|
||||
|
|
||||
= note: expected type `&{integer}`
|
||||
found type `&mut _`
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/or-pattern-mismatch.rs:3:68
|
||||
|
|
||||
LL | fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } }
|
||||
| ^ expected `usize`, found `isize`
|
||||
| ---------------- this expression has type `Blah` ^ expected `usize`, found `isize`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/pat-tuple-5.rs:5:10
|
||||
|
|
||||
LL | match (0, 1) {
|
||||
| ------ this match expression has type `({integer}, {integer})`
|
||||
| ------ this expression has type `({integer}, {integer})`
|
||||
LL | (PAT ..) => {}
|
||||
| ^^^ expected tuple, found `u8`
|
||||
|
|
||||
|
|
|
@ -425,8 +425,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/recover-range-pats.rs:23:16
|
||||
|
|
||||
LL | if let X.. .0 = 0 {}
|
||||
| - ^^ expected integer, found floating-point number
|
||||
| |
|
||||
| - ^^ - this expression has type `u8`
|
||||
| | |
|
||||
| | expected integer, found floating-point number
|
||||
| this is of type `u8`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
|
@ -457,8 +458,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/recover-range-pats.rs:36:16
|
||||
|
|
||||
LL | if let X..=.0 = 0 {}
|
||||
| - ^^ expected integer, found floating-point number
|
||||
| |
|
||||
| - ^^ - this expression has type `u8`
|
||||
| | |
|
||||
| | expected integer, found floating-point number
|
||||
| this is of type `u8`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
|
@ -489,8 +491,9 @@ error[E0308]: mismatched types
|
|||
--> $DIR/recover-range-pats.rs:52:17
|
||||
|
|
||||
LL | if let X... .0 = 0 {}
|
||||
| - ^^ expected integer, found floating-point number
|
||||
| |
|
||||
| - ^^ - this expression has type `u8`
|
||||
| | |
|
||||
| | expected integer, found floating-point number
|
||||
| this is of type `u8`
|
||||
|
||||
error[E0029]: only char and numeric types are allowed in range patterns
|
||||
|
|
9
src/test/ui/pattern/pat-struct-field-expr-has-type.rs
Normal file
9
src/test/ui/pattern/pat-struct-field-expr-has-type.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
struct S {
|
||||
f: u8,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match (S { f: 42 }) {
|
||||
S { f: Ok(_) } => {} //~ ERROR mismatched types
|
||||
}
|
||||
}
|
14
src/test/ui/pattern/pat-struct-field-expr-has-type.stderr
Normal file
14
src/test/ui/pattern/pat-struct-field-expr-has-type.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-struct-field-expr-has-type.rs:7:16
|
||||
|
|
||||
LL | match (S { f: 42 }) {
|
||||
| ------------- this expression has type `S`
|
||||
LL | S { f: Ok(_) } => {}
|
||||
| ^^^^^ expected `u8`, found enum `std::result::Result`
|
||||
|
|
||||
= note: expected type `u8`
|
||||
found enum `std::result::Result<_, _>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
8
src/test/ui/pattern/pat-type-err-formal-param.rs
Normal file
8
src/test/ui/pattern/pat-type-err-formal-param.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Test the `.span_label(..)` to the type when there's a
|
||||
// type error in a pattern due to a the formal parameter.
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct Tuple(u8);
|
||||
|
||||
fn foo(Tuple(_): String) {} //~ ERROR mismatched types
|
11
src/test/ui/pattern/pat-type-err-formal-param.stderr
Normal file
11
src/test/ui/pattern/pat-type-err-formal-param.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-type-err-formal-param.rs:8:8
|
||||
|
|
||||
LL | fn foo(Tuple(_): String) {}
|
||||
| ^^^^^^^^ ------ expected due to this
|
||||
| |
|
||||
| expected struct `std::string::String`, found struct `Tuple`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
16
src/test/ui/pattern/pat-type-err-let-stmt.rs
Normal file
16
src/test/ui/pattern/pat-type-err-let-stmt.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Test the `.span_label` to the type / scrutinee
|
||||
// when there's a type error in checking a pattern.
|
||||
|
||||
fn main() {
|
||||
// We want to point at the `Option<u8>`.
|
||||
let Ok(0): Option<u8> = 42u8;
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
|
||||
// We want to point at the `Option<u8>`.
|
||||
let Ok(0): Option<u8>;
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
// We want to point at the scrutinee.
|
||||
let Ok(0) = 42u8; //~ ERROR mismatched types
|
||||
}
|
49
src/test/ui/pattern/pat-type-err-let-stmt.stderr
Normal file
49
src/test/ui/pattern/pat-type-err-let-stmt.stderr
Normal file
|
@ -0,0 +1,49 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-type-err-let-stmt.rs:6:29
|
||||
|
|
||||
LL | let Ok(0): Option<u8> = 42u8;
|
||||
| ---------- ^^^^
|
||||
| | |
|
||||
| | expected enum `std::option::Option`, found `u8`
|
||||
| | help: try using a variant of the expected enum: `Some(42u8)`
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected enum `std::option::Option<u8>`
|
||||
found type `u8`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-type-err-let-stmt.rs:6:9
|
||||
|
|
||||
LL | let Ok(0): Option<u8> = 42u8;
|
||||
| ^^^^^ ---------- expected due to this
|
||||
| |
|
||||
| expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
||||
= note: expected enum `std::option::Option<u8>`
|
||||
found enum `std::result::Result<_, _>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-type-err-let-stmt.rs:11:9
|
||||
|
|
||||
LL | let Ok(0): Option<u8>;
|
||||
| ^^^^^ ---------- expected due to this
|
||||
| |
|
||||
| expected enum `std::option::Option`, found enum `std::result::Result`
|
||||
|
|
||||
= note: expected enum `std::option::Option<u8>`
|
||||
found enum `std::result::Result<_, _>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-type-err-let-stmt.rs:15:9
|
||||
|
|
||||
LL | let Ok(0) = 42u8;
|
||||
| ^^^^^ ---- this expression has type `u8`
|
||||
| |
|
||||
| expected `u8`, found enum `std::result::Result`
|
||||
|
|
||||
= note: expected type `u8`
|
||||
found enum `std::result::Result<_, _>`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -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 expression has type `char`
|
||||
LL | S { .. } => (),
|
||||
| ^^^^^^^^ expected `char`, found struct `S`
|
||||
|
||||
|
|
|
@ -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 expression has type `Bar`
|
||||
LL | Bar::T1(_, Some::<isize>(x)) => {
|
||||
| ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found `isize`
|
||||
|
|
||||
|
|
|
@ -23,18 +23,24 @@ LL | Opts::A(ref mut i) | Opts::B(ref i) => {}
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/resolve-inconsistent-binding-mode.rs:7:32
|
||||
|
|
||||
LL | match x {
|
||||
| - this expression has type `Opts`
|
||||
LL | Opts::A(ref i) | Opts::B(i) => {}
|
||||
| ^ expected `&isize`, found `isize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/resolve-inconsistent-binding-mode.rs:16:32
|
||||
|
|
||||
LL | match x {
|
||||
| - this expression has type `Opts`
|
||||
LL | Opts::A(ref i) | Opts::B(i) => {}
|
||||
| ^ expected `&isize`, found `isize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/resolve-inconsistent-binding-mode.rs:25:36
|
||||
|
|
||||
LL | match x {
|
||||
| - this expression has type `Opts`
|
||||
LL | Opts::A(ref mut i) | Opts::B(ref i) => {}
|
||||
| ^^^^^ types differ in mutability
|
||||
|
|
||||
|
|
|
@ -86,6 +86,8 @@ LL | (CONST1, _) | (_, Const2) => ()
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/resolve-inconsistent-names.rs:19:19
|
||||
|
|
||||
LL | match x {
|
||||
| - this expression has type `(E, E)`
|
||||
LL | (A, B) | (ref B, c) | (c, A) => ()
|
||||
| ^^^^^ expected enum `E`, found `&E`
|
||||
|
||||
|
|
|
@ -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 expression has 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 expression has 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 expression has 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 expression has 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 expression has 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 expression has 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 expression has type `bool`
|
||||
| |
|
||||
| expected `bool`, found struct `std::ops::Range`
|
||||
|
|
||||
|
|
|
@ -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 expression has 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 expression has 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 expression has type `Pair<{integer}, {integer}>`
|
||||
LL | PairF::<u32> { .. } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
|
||||
|
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue