Skip to content

Commit 58dc448

Browse files
authored
Auto merge of #35787 - canndrew:bang_type_refactor_check, r=eddyb
Typecheck refactor for `!` Ping @nikomatsakis @eddyb. This is the PR for the typeck refactor for `!`. Is this what you guys had in mind? Is there anything else that needs doing on it?
2 parents 2dbf600 + c9a340e commit 58dc448

File tree

9 files changed

+272
-327
lines changed

9 files changed

+272
-327
lines changed

src/librustc_typeck/check/_match.rs

+44-52
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3232

3333
debug!("check_pat(pat={:?},expected={:?})", pat, expected);
3434

35-
match pat.node {
35+
let ty = match pat.node {
3636
PatKind::Wild => {
37-
self.write_ty(pat.id, expected);
37+
expected
3838
}
3939
PatKind::Lit(ref lt) => {
40-
self.check_expr(&lt);
41-
let expr_ty = self.expr_ty(&lt);
40+
let ty = self.check_expr(&lt);
4241

4342
// Byte string patterns behave the same way as array patterns
4443
// They can denote both statically and dynamically sized byte arrays
45-
let mut pat_ty = expr_ty;
44+
let mut pat_ty = ty;
4645
if let hir::ExprLit(ref lt) = lt.node {
4746
if let ast::LitKind::ByteStr(_) = lt.node {
4847
let expected_ty = self.structurally_resolved_type(pat.span, expected);
@@ -55,28 +54,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5554
}
5655
}
5756

58-
self.write_ty(pat.id, pat_ty);
59-
6057
// somewhat surprising: in this case, the subtyping
6158
// relation goes the opposite way as the other
6259
// cases. Actually what we really want is not a subtyping
6360
// relation at all but rather that there exists a LUB (so
6461
// that they can be compared). However, in practice,
6562
// constants are always scalars or strings. For scalars
66-
// subtyping is irrelevant, and for strings `expr_ty` is
63+
// subtyping is irrelevant, and for strings `ty` is
6764
// type is `&'static str`, so if we say that
6865
//
6966
// &'static str <: expected
7067
//
7168
// that's equivalent to there existing a LUB.
7269
self.demand_suptype(pat.span, expected, pat_ty);
70+
pat_ty
7371
}
7472
PatKind::Range(ref begin, ref end) => {
75-
self.check_expr(begin);
76-
self.check_expr(end);
77-
78-
let lhs_ty = self.expr_ty(begin);
79-
let rhs_ty = self.expr_ty(end);
73+
let lhs_ty = self.check_expr(begin);
74+
let rhs_ty = self.check_expr(end);
8075

8176
// Check that both end-points are of numeric or char type.
8277
let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
@@ -105,11 +100,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
105100
// it to type the entire expression.
106101
let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
107102

108-
self.write_ty(pat.id, common_type);
109-
110103
// subtyping doesn't matter here, as the value is some kind of scalar
111104
self.demand_eqtype(pat.span, expected, lhs_ty);
112105
self.demand_eqtype(pat.span, expected, rhs_ty);
106+
common_type
113107
}
114108
PatKind::Binding(bm, _, ref sub) => {
115109
let typ = self.local_ty(pat.span, pat.id);
@@ -136,8 +130,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
136130
}
137131
}
138132

139-
self.write_ty(pat.id, typ);
140-
141133
// if there are multiple arms, make sure they all agree on
142134
// what the type of the binding `x` ought to be
143135
match tcx.expect_def(pat.id) {
@@ -154,16 +146,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
154146
if let Some(ref p) = *sub {
155147
self.check_pat(&p, expected);
156148
}
149+
150+
typ
157151
}
158152
PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
159-
self.check_pat_tuple_struct(pat, path, &subpats, ddpos, expected);
153+
self.check_pat_tuple_struct(pat, path, &subpats, ddpos, expected)
160154
}
161155
PatKind::Path(ref opt_qself, ref path) => {
162156
let opt_qself_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
163-
self.check_pat_path(pat, opt_qself_ty, path, expected);
157+
self.check_pat_path(pat, opt_qself_ty, path, expected)
164158
}
165159
PatKind::Struct(ref path, ref fields, etc) => {
166-
self.check_pat_struct(pat, path, fields, etc, expected);
160+
self.check_pat_struct(pat, path, fields, etc, expected)
167161
}
168162
PatKind::Tuple(ref elements, ddpos) => {
169163
let mut expected_len = elements.len();
@@ -178,11 +172,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
178172

179173
let element_tys: Vec<_> = (0 .. max_len).map(|_| self.next_ty_var()).collect();
180174
let pat_ty = tcx.mk_tup(element_tys.clone());
181-
self.write_ty(pat.id, pat_ty);
182175
self.demand_eqtype(pat.span, expected, pat_ty);
183176
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
184177
self.check_pat(elem, &element_tys[i]);
185178
}
179+
pat_ty
186180
}
187181
PatKind::Box(ref inner) => {
188182
let inner_ty = self.next_ty_var();
@@ -193,11 +187,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
193187
// think any errors can be introduced by using
194188
// `demand::eqtype`.
195189
self.demand_eqtype(pat.span, expected, uniq_ty);
196-
self.write_ty(pat.id, uniq_ty);
197190
self.check_pat(&inner, inner_ty);
191+
uniq_ty
198192
} else {
199-
self.write_error(pat.id);
200193
self.check_pat(&inner, tcx.types.err);
194+
tcx.types.err
201195
}
202196
}
203197
PatKind::Ref(ref inner, mutbl) => {
@@ -225,11 +219,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
225219
}
226220
};
227221

228-
self.write_ty(pat.id, rptr_ty);
229222
self.check_pat(&inner, inner_ty);
223+
rptr_ty
230224
} else {
231-
self.write_error(pat.id);
232225
self.check_pat(&inner, tcx.types.err);
226+
tcx.types.err
233227
}
234228
}
235229
PatKind::Vec(ref before, ref slice, ref after) => {
@@ -281,8 +275,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
281275
}
282276
};
283277

284-
self.write_ty(pat.id, expected_ty);
285-
286278
for elt in before {
287279
self.check_pat(&elt, inner_ty);
288280
}
@@ -292,8 +284,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
292284
for elt in after {
293285
self.check_pat(&elt, inner_ty);
294286
}
287+
expected_ty
295288
}
296-
}
289+
};
290+
291+
self.write_ty(pat.id, ty);
297292

298293
// (*) In most of the cases above (literals and constants being
299294
// the exception), we relate types using strict equality, evewn
@@ -371,7 +366,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
371366
discrim: &'gcx hir::Expr,
372367
arms: &'gcx [hir::Arm],
373368
expected: Expectation<'tcx>,
374-
match_src: hir::MatchSource) {
369+
match_src: hir::MatchSource) -> Ty<'tcx> {
375370
let tcx = self.tcx;
376371

377372
// Not entirely obvious: if matches may create ref bindings, we
@@ -385,8 +380,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
385380
});
386381
let discrim_ty;
387382
if let Some(m) = contains_ref_bindings {
388-
self.check_expr_with_lvalue_pref(discrim, LvaluePreference::from_mutbl(m));
389-
discrim_ty = self.expr_ty(discrim);
383+
discrim_ty = self.check_expr_with_lvalue_pref(discrim, LvaluePreference::from_mutbl(m));
390384
} else {
391385
// ...but otherwise we want to use any supertype of the
392386
// discriminant. This is sort of a workaround, see note (*) in
@@ -425,12 +419,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
425419
}
426420
_ => result_ty
427421
};
422+
428423
for (i, arm) in arms.iter().enumerate() {
429424
if let Some(ref e) = arm.guard {
430425
self.check_expr_has_type(e, tcx.types.bool);
431426
}
432-
self.check_expr_with_expectation(&arm.body, expected);
433-
let arm_ty = self.expr_ty(&arm.body);
427+
let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
434428

435429
if result_ty.references_error() || arm_ty.references_error() {
436430
result_ty = tcx.types.err;
@@ -460,10 +454,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
460454
})
461455
} else if i == 0 {
462456
// Special-case the first arm, as it has no "previous expressions".
463-
self.try_coerce(&arm.body, coerce_first)
457+
self.try_coerce(&arm.body, arm_ty, coerce_first)
464458
} else {
465459
let prev_arms = || arms[..i].iter().map(|arm| &*arm.body);
466-
self.try_find_coercion_lub(origin, prev_arms, result_ty, &arm.body)
460+
self.try_find_coercion_lub(origin, prev_arms, result_ty, &arm.body, arm_ty)
467461
};
468462

469463
result_ty = match result {
@@ -480,7 +474,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
480474
};
481475
}
482476

483-
self.write_ty(expr.id, result_ty);
477+
result_ty
484478
}
485479
}
486480

@@ -490,39 +484,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
490484
path: &hir::Path,
491485
fields: &'gcx [Spanned<hir::FieldPat>],
492486
etc: bool,
493-
expected: Ty<'tcx>)
487+
expected: Ty<'tcx>) -> Ty<'tcx>
494488
{
495489
// Resolve the path and check the definition for errors.
496490
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id,
497491
pat.span) {
498492
variant_ty
499493
} else {
500-
self.write_error(pat.id);
501494
for field in fields {
502495
self.check_pat(&field.node.pat, self.tcx.types.err);
503496
}
504-
return;
497+
return self.tcx.types.err;
505498
};
506499

507500
// Type check the path.
508501
self.demand_eqtype(pat.span, expected, pat_ty);
509502

510503
// Type check subpatterns.
511504
self.check_struct_pat_fields(pat_ty, pat.span, variant, fields, etc);
505+
pat_ty
512506
}
513507

514508
fn check_pat_path(&self,
515509
pat: &hir::Pat,
516510
opt_self_ty: Option<Ty<'tcx>>,
517511
path: &hir::Path,
518-
expected: Ty<'tcx>)
512+
expected: Ty<'tcx>) -> Ty<'tcx>
519513
{
520514
let tcx = self.tcx;
521515
let report_unexpected_def = || {
522516
span_err!(tcx.sess, pat.span, E0533,
523517
"`{}` does not name a unit variant, unit struct or a constant",
524518
pprust::path_to_string(path));
525-
self.write_error(pat.id);
526519
};
527520

528521
// Resolve the path and check the definition for errors.
@@ -531,18 +524,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
531524
match def {
532525
Def::Err => {
533526
self.set_tainted_by_errors();
534-
self.write_error(pat.id);
535-
return;
527+
return tcx.types.err;
536528
}
537529
Def::Method(..) => {
538530
report_unexpected_def();
539-
return;
531+
return tcx.types.err;
540532
}
541533
Def::Variant(..) | Def::Struct(..) => {
542534
let variant = tcx.expect_variant_def(def);
543535
if variant.kind != VariantKind::Unit {
544536
report_unexpected_def();
545-
return;
537+
return tcx.types.err;
546538
}
547539
}
548540
Def::Const(..) | Def::AssociatedConst(..) => {} // OK
@@ -552,18 +544,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
552544
// Type check the path.
553545
let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
554546
self.demand_suptype(pat.span, expected, pat_ty);
547+
pat_ty
555548
}
556549

557550
fn check_pat_tuple_struct(&self,
558551
pat: &hir::Pat,
559552
path: &hir::Path,
560553
subpats: &'gcx [P<hir::Pat>],
561554
ddpos: Option<usize>,
562-
expected: Ty<'tcx>)
555+
expected: Ty<'tcx>) -> Ty<'tcx>
563556
{
564557
let tcx = self.tcx;
565558
let on_error = || {
566-
self.write_error(pat.id);
567559
for pat in subpats {
568560
self.check_pat(&pat, tcx.types.err);
569561
}
@@ -587,11 +579,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
587579
Def::Err => {
588580
self.set_tainted_by_errors();
589581
on_error();
590-
return;
582+
return tcx.types.err;
591583
}
592584
Def::Const(..) | Def::AssociatedConst(..) | Def::Method(..) => {
593585
report_unexpected_def(false);
594-
return;
586+
return tcx.types.err;
595587
}
596588
Def::Variant(..) | Def::Struct(..) => {
597589
tcx.expect_variant_def(def)
@@ -604,20 +596,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
604596
report_unexpected_def(true);
605597
} else if variant.kind != VariantKind::Tuple {
606598
report_unexpected_def(false);
607-
return;
599+
return tcx.types.err;
608600
}
609601

610602
// Type check the path.
611603
let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
612-
613604
let pat_ty = if pat_ty.is_fn() {
614605
// Replace constructor type with constructed type for tuple struct patterns.
615606
tcx.no_late_bound_regions(&pat_ty.fn_ret()).unwrap()
616607
} else {
617608
// Leave the type as is for unit structs (backward compatibility).
618609
pat_ty
619610
};
620-
self.write_ty(pat.id, pat_ty);
621611
self.demand_eqtype(pat.span, expected, pat_ty);
622612

623613
// Type check subpatterns.
@@ -650,7 +640,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
650640
variant.fields.len(), fields_ending, subpats.len()))
651641
.emit();
652642
on_error();
643+
return tcx.types.err;
653644
}
645+
pat_ty
654646
}
655647

656648
fn check_struct_pat_fields(&self,

0 commit comments

Comments
 (0)