Skip to content

Commit 6588018

Browse files
committed
Return a type from check_pat_inner
1 parent 38adb99 commit 6588018

File tree

1 file changed

+49
-55
lines changed
  • compiler/rustc_hir_typeck/src

1 file changed

+49
-55
lines changed

compiler/rustc_hir_typeck/src/pat.rs

+49-55
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
325325
_ => None,
326326
};
327327
let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res));
328-
self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info);
328+
let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info);
329+
self.write_ty(pat.hir_id, ty);
330+
331+
// (note_1): In most of the cases where (note_1) is referenced
332+
// (literals and constants being the exception), we relate types
333+
// using strict equality, even though subtyping would be sufficient.
334+
// There are a few reasons for this, some of which are fairly subtle
335+
// and which cost me (nmatsakis) an hour or two debugging to remember,
336+
// so I thought I'd write them down this time.
337+
//
338+
// 1. There is no loss of expressiveness here, though it does
339+
// cause some inconvenience. What we are saying is that the type
340+
// of `x` becomes *exactly* what is expected. This can cause unnecessary
341+
// errors in some cases, such as this one:
342+
//
343+
// ```
344+
// fn foo<'x>(x: &'x i32) {
345+
// let a = 1;
346+
// let mut z = x;
347+
// z = &a;
348+
// }
349+
// ```
350+
//
351+
// The reason we might get an error is that `z` might be
352+
// assigned a type like `&'x i32`, and then we would have
353+
// a problem when we try to assign `&a` to `z`, because
354+
// the lifetime of `&a` (i.e., the enclosing block) is
355+
// shorter than `'x`.
356+
//
357+
// HOWEVER, this code works fine. The reason is that the
358+
// expected type here is whatever type the user wrote, not
359+
// the initializer's type. In this case the user wrote
360+
// nothing, so we are going to create a type variable `Z`.
361+
// Then we will assign the type of the initializer (`&'x i32`)
362+
// as a subtype of `Z`: `&'x i32 <: Z`. And hence we
363+
// will instantiate `Z` as a type `&'0 i32` where `'0` is
364+
// a fresh region variable, with the constraint that `'x : '0`.
365+
// So basically we're all set.
366+
//
367+
// Note that there are two tests to check that this remains true
368+
// (`regions-reassign-{match,let}-bound-pointer.rs`).
369+
//
370+
// 2. An outdated issue related to the old HIR borrowck. See the test
371+
// `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
329372
}
330373

331374
// Helper to avoid resolving the same path pattern several times.
@@ -336,7 +379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
336379
adjust_mode: AdjustMode,
337380
expected: Ty<'tcx>,
338381
pat_info: PatInfo<'tcx>,
339-
) {
382+
) -> Ty<'tcx> {
340383
let PatInfo { mut binding_mode, mut max_ref_mutbl, current_depth, .. } = pat_info;
341384
#[cfg(debug_assertions)]
342385
if binding_mode == ByRef::Yes(Mutability::Mut)
@@ -369,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
369412
decl_origin: old_pat_info.decl_origin,
370413
};
371414

372-
let ty = match pat.kind {
415+
match pat.kind {
373416
// Peel off a `&` or `&mut` from the scrutinee type. See the examples in
374417
// `tests/ui/rfcs/rfc-2005-default-binding-mode`.
375418
_ if let AdjustMode::Peel = adjust_mode
@@ -408,13 +451,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
408451

409452
// Use the old pat info to keep `current_depth` to its old value.
410453
let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info };
411-
return self.check_pat_inner(
412-
pat,
413-
opt_path_res,
414-
adjust_mode,
415-
inner_ty,
416-
new_pat_info,
417-
);
454+
// Recurse with the new expected type.
455+
self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, new_pat_info)
418456
}
419457
PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
420458
// We allow any type here; we ensure that the type is uninhabited during match checking.
@@ -465,51 +503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
465503
PatKind::Slice(before, slice, after) => {
466504
self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
467505
}
468-
};
469-
470-
self.write_ty(pat.hir_id, ty);
471-
472-
// (note_1): In most of the cases where (note_1) is referenced
473-
// (literals and constants being the exception), we relate types
474-
// using strict equality, even though subtyping would be sufficient.
475-
// There are a few reasons for this, some of which are fairly subtle
476-
// and which cost me (nmatsakis) an hour or two debugging to remember,
477-
// so I thought I'd write them down this time.
478-
//
479-
// 1. There is no loss of expressiveness here, though it does
480-
// cause some inconvenience. What we are saying is that the type
481-
// of `x` becomes *exactly* what is expected. This can cause unnecessary
482-
// errors in some cases, such as this one:
483-
//
484-
// ```
485-
// fn foo<'x>(x: &'x i32) {
486-
// let a = 1;
487-
// let mut z = x;
488-
// z = &a;
489-
// }
490-
// ```
491-
//
492-
// The reason we might get an error is that `z` might be
493-
// assigned a type like `&'x i32`, and then we would have
494-
// a problem when we try to assign `&a` to `z`, because
495-
// the lifetime of `&a` (i.e., the enclosing block) is
496-
// shorter than `'x`.
497-
//
498-
// HOWEVER, this code works fine. The reason is that the
499-
// expected type here is whatever type the user wrote, not
500-
// the initializer's type. In this case the user wrote
501-
// nothing, so we are going to create a type variable `Z`.
502-
// Then we will assign the type of the initializer (`&'x i32`)
503-
// as a subtype of `Z`: `&'x i32 <: Z`. And hence we
504-
// will instantiate `Z` as a type `&'0 i32` where `'0` is
505-
// a fresh region variable, with the constraint that `'x : '0`.
506-
// So basically we're all set.
507-
//
508-
// Note that there are two tests to check that this remains true
509-
// (`regions-reassign-{match,let}-bound-pointer.rs`).
510-
//
511-
// 2. An outdated issue related to the old HIR borrowck. See the test
512-
// `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
506+
}
513507
}
514508

515509
/// How should the binding mode and expected type be adjusted?

0 commit comments

Comments
 (0)