Skip to content

Commit 50fb848

Browse files
authored
Rollup merge of #67730 - Centril:typeck-pat-cleanup, r=estebank
Cleanup pattern type checking, fix diagnostics bugs (+ improvements) r? @estebank
2 parents bc5963d + 63dc0e4 commit 50fb848

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+418
-244
lines changed

src/librustc/infer/error_reporting/mod.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -581,10 +581,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
581581
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
582582
) {
583583
match cause.code {
584-
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
584+
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
585+
let ty = self.resolve_vars_if_possible(&root_ty);
585586
if ty.is_suggestable() {
586587
// don't show type `_`
587-
err.span_label(span, format!("this match expression has type `{}`", ty));
588+
err.span_label(span, format!("this expression has type `{}`", ty));
588589
}
589590
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
590591
if ty.is_box() && ty.boxed_ty() == found {
@@ -599,11 +600,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
599600
}
600601
}
601602
}
603+
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
604+
err.span_label(span, "expected due to this");
605+
}
602606
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
603607
source,
604608
ref prior_arms,
605609
last_ty,
606-
discrim_hir_id,
610+
scrut_hir_id,
607611
..
608612
}) => match source {
609613
hir::MatchSource::IfLetDesugar { .. } => {
@@ -612,16 +616,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
612616
}
613617
hir::MatchSource::TryDesugar => {
614618
if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
615-
let discrim_expr = self.tcx.hir().expect_expr(discrim_hir_id);
616-
let discrim_ty = if let hir::ExprKind::Call(_, args) = &discrim_expr.kind {
619+
let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
620+
let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
617621
let arg_expr = args.first().expect("try desugaring call w/out arg");
618622
self.in_progress_tables
619623
.and_then(|tables| tables.borrow().expr_ty_opt(arg_expr))
620624
} else {
621-
bug!("try desugaring w/out call expr as discriminant");
625+
bug!("try desugaring w/out call expr as scrutinee");
622626
};
623627

624-
match discrim_ty {
628+
match scrut_ty {
625629
Some(ty) if expected == ty => {
626630
let source_map = self.tcx.sess.source_map();
627631
err.span_suggestion(

src/librustc/traits/error_reporting.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2580,7 +2580,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
25802580
match *cause_code {
25812581
ObligationCauseCode::ExprAssignable
25822582
| ObligationCauseCode::MatchExpressionArm { .. }
2583-
| ObligationCauseCode::MatchExpressionArmPattern { .. }
2583+
| ObligationCauseCode::Pattern { .. }
25842584
| ObligationCauseCode::IfExpression { .. }
25852585
| ObligationCauseCode::IfExpressionWithNoElse
25862586
| ObligationCauseCode::MainFunctionType

src/librustc/traits/mod.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,14 @@ pub enum ObligationCauseCode<'tcx> {
249249
/// Computing common supertype in the arms of a match expression
250250
MatchExpressionArm(Box<MatchExpressionArmCause<'tcx>>),
251251

252-
/// Computing common supertype in the pattern guard for the arms of a match expression
253-
MatchExpressionArmPattern {
254-
span: Span,
255-
ty: Ty<'tcx>,
252+
/// Type error arising from type checking a pattern against an expected type.
253+
Pattern {
254+
/// The span of the scrutinee or type expression which caused the `root_ty` type.
255+
span: Option<Span>,
256+
/// The root expected type induced by a scrutinee or type expression.
257+
root_ty: Ty<'tcx>,
258+
/// Whether the `Span` came from an expression or a type expression.
259+
origin_expr: bool,
256260
},
257261

258262
/// Constants in patterns must have `Structural` type.
@@ -311,7 +315,7 @@ pub struct MatchExpressionArmCause<'tcx> {
311315
pub source: hir::MatchSource,
312316
pub prior_arms: Vec<Span>,
313317
pub last_ty: Ty<'tcx>,
314-
pub discrim_hir_id: hir::HirId,
318+
pub scrut_hir_id: hir::HirId,
315319
}
316320

317321
#[derive(Clone, Debug, PartialEq, Eq, Hash)]

src/librustc/traits/structural_impls.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -511,18 +511,18 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
511511
source,
512512
ref prior_arms,
513513
last_ty,
514-
discrim_hir_id,
514+
scrut_hir_id,
515515
}) => tcx.lift(&last_ty).map(|last_ty| {
516516
super::MatchExpressionArm(box super::MatchExpressionArmCause {
517517
arm_span,
518518
source,
519519
prior_arms: prior_arms.clone(),
520520
last_ty,
521-
discrim_hir_id,
521+
scrut_hir_id,
522522
})
523523
}),
524-
super::MatchExpressionArmPattern { span, ty } => {
525-
tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
524+
super::Pattern { span, root_ty, origin_expr } => {
525+
tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
526526
}
527527
super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
528528
Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))

src/librustc_typeck/check/_match.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1111
pub fn check_match(
1212
&self,
1313
expr: &'tcx hir::Expr<'tcx>,
14-
discrim: &'tcx hir::Expr<'tcx>,
14+
scrut: &'tcx hir::Expr<'tcx>,
1515
arms: &'tcx [hir::Arm<'tcx>],
1616
expected: Expectation<'tcx>,
1717
match_src: hir::MatchSource,
@@ -27,7 +27,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2727
};
2828

2929
// Type check the descriminant and get its type.
30-
let discrim_ty = if force_scrutinee_bool {
30+
let scrut_ty = if force_scrutinee_bool {
3131
// Here we want to ensure:
3232
//
3333
// 1. That default match bindings are *not* accepted in the condition of an
@@ -36,9 +36,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3636
// 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
3737
//
3838
// FIXME(60707): Consider removing hack with principled solution.
39-
self.check_expr_has_type_or_error(discrim, self.tcx.types.bool, |_| {})
39+
self.check_expr_has_type_or_error(scrut, self.tcx.types.bool, |_| {})
4040
} else {
41-
self.demand_discriminant_type(arms, discrim)
41+
self.demand_scrutinee_type(arms, scrut)
4242
};
4343

4444
// If there are no arms, that is a diverging match; a special case.
@@ -51,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5151

5252
// Otherwise, we have to union together the types that the
5353
// arms produce and so forth.
54-
let discrim_diverges = self.diverges.get();
54+
let scrut_diverges = self.diverges.get();
5555
self.diverges.set(Diverges::Maybe);
5656

5757
// rust-lang/rust#55810: Typecheck patterns first (via eager
@@ -61,7 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6161
.map(|arm| {
6262
let mut all_pats_diverge = Diverges::WarnedAlways;
6363
self.diverges.set(Diverges::Maybe);
64-
self.check_pat_top(&arm.pat, discrim_ty, Some(discrim.span));
64+
self.check_pat_top(&arm.pat, scrut_ty, Some(scrut.span), true);
6565
all_pats_diverge &= self.diverges.get();
6666

6767
// As discussed with @eddyb, this is for disabling unreachable_code
@@ -157,7 +157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
157157
source: match_src,
158158
prior_arms: other_arms.clone(),
159159
last_ty: prior_arm_ty.unwrap(),
160-
discrim_hir_id: discrim.hir_id,
160+
scrut_hir_id: scrut.hir_id,
161161
}),
162162
),
163163
};
@@ -186,8 +186,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
186186
};
187187
}
188188

189-
// We won't diverge unless the discriminant or all arms diverge.
190-
self.diverges.set(discrim_diverges | all_arms_diverge);
189+
// We won't diverge unless the scrutinee or all arms diverge.
190+
self.diverges.set(scrut_diverges | all_arms_diverge);
191191

192192
coercion.complete(self)
193193
}
@@ -388,14 +388,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
388388
)
389389
}
390390

391-
fn demand_discriminant_type(
391+
fn demand_scrutinee_type(
392392
&self,
393393
arms: &'tcx [hir::Arm<'tcx>],
394-
discrim: &'tcx hir::Expr<'tcx>,
394+
scrut: &'tcx hir::Expr<'tcx>,
395395
) -> Ty<'tcx> {
396396
// Not entirely obvious: if matches may create ref bindings, we want to
397-
// use the *precise* type of the discriminant, *not* some supertype, as
398-
// the "discriminant type" (issue #23116).
397+
// use the *precise* type of the scrutinee, *not* some supertype, as
398+
// the "scrutinee type" (issue #23116).
399399
//
400400
// arielb1 [writes here in this comment thread][c] that there
401401
// is certainly *some* potential danger, e.g., for an example
@@ -454,17 +454,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
454454
});
455455

456456
if let Some(m) = contains_ref_bindings {
457-
self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
457+
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
458458
} else {
459459
// ...but otherwise we want to use any supertype of the
460-
// discriminant. This is sort of a workaround, see note (*) in
460+
// scrutinee. This is sort of a workaround, see note (*) in
461461
// `check_pat` for some details.
462-
let discrim_ty = self.next_ty_var(TypeVariableOrigin {
462+
let scrut_ty = self.next_ty_var(TypeVariableOrigin {
463463
kind: TypeVariableOriginKind::TypeInference,
464-
span: discrim.span,
464+
span: scrut.span,
465465
});
466-
self.check_expr_has_type_or_error(discrim, discrim_ty, |_| {});
467-
discrim_ty
466+
self.check_expr_has_type_or_error(scrut, scrut_ty, |_| {});
467+
scrut_ty
468468
}
469469
}
470470
}

src/librustc_typeck/check/demand.rs

+1-30
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::check::FnCtxt;
22
use rustc::infer::InferOk;
3-
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
3+
use rustc::traits::{self, ObligationCause};
44

55
use errors::{Applicability, DiagnosticBuilder};
66
use rustc::hir::{self, is_range_literal, print, Node};
@@ -79,35 +79,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7979
}
8080
}
8181

82-
pub fn demand_eqtype_pat_diag(
83-
&self,
84-
cause_span: Span,
85-
expected: Ty<'tcx>,
86-
actual: Ty<'tcx>,
87-
match_expr_span: Option<Span>,
88-
) -> Option<DiagnosticBuilder<'tcx>> {
89-
let cause = if let Some(span) = match_expr_span {
90-
self.cause(
91-
cause_span,
92-
ObligationCauseCode::MatchExpressionArmPattern { span, ty: expected },
93-
)
94-
} else {
95-
self.misc(cause_span)
96-
};
97-
self.demand_eqtype_with_origin(&cause, expected, actual)
98-
}
99-
100-
pub fn demand_eqtype_pat(
101-
&self,
102-
cause_span: Span,
103-
expected: Ty<'tcx>,
104-
actual: Ty<'tcx>,
105-
match_expr_span: Option<Span>,
106-
) {
107-
self.demand_eqtype_pat_diag(cause_span, expected, actual, match_expr_span)
108-
.map(|mut err| err.emit());
109-
}
110-
11182
pub fn demand_coerce(
11283
&self,
11384
expr: &hir::Expr<'_>,

0 commit comments

Comments
 (0)