Skip to content

Commit e87bf30

Browse files
committed
propagate user-ascribes types down onto resulting bindings
But only in very simple cases.
1 parent a871053 commit e87bf30

File tree

14 files changed

+171
-35
lines changed

14 files changed

+171
-35
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer });
2424
impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
2525
mutability,
2626
ty,
27+
user_ty,
2728
name,
2829
source_info,
2930
visibility_scope,

src/librustc/mir/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,12 @@ pub struct LocalDecl<'tcx> {
640640
/// Type of this local.
641641
pub ty: Ty<'tcx>,
642642

643+
/// If the user manually ascribed a type to this variable,
644+
/// e.g. via `let x: T`, then we carry that type here. The MIR
645+
/// borrow checker needs this information since it can affect
646+
/// region inference.
647+
pub user_ty: Option<CanonicalTy<'tcx>>,
648+
643649
/// Name of the local, used in debuginfo and pretty-printing.
644650
///
645651
/// Note that function arguments can also have this set to `Some(_)`
@@ -802,6 +808,7 @@ impl<'tcx> LocalDecl<'tcx> {
802808
LocalDecl {
803809
mutability,
804810
ty,
811+
user_ty: None,
805812
name: None,
806813
source_info: SourceInfo {
807814
span,
@@ -821,6 +828,7 @@ impl<'tcx> LocalDecl<'tcx> {
821828
LocalDecl {
822829
mutability: Mutability::Mut,
823830
ty: return_ty,
831+
user_ty: None,
824832
source_info: SourceInfo {
825833
span,
826834
scope: OUTERMOST_SOURCE_SCOPE,
@@ -2613,6 +2621,7 @@ BraceStructTypeFoldableImpl! {
26132621
is_user_variable,
26142622
internal,
26152623
ty,
2624+
user_ty,
26162625
name,
26172626
source_info,
26182627
visibility_scope,

src/librustc/mir/visit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ macro_rules! make_mir_visitor {
721721
let LocalDecl {
722722
mutability: _,
723723
ref $($mutability)* ty,
724+
ref $($mutability)* user_ty,
724725
name: _,
725726
ref $($mutability)* source_info,
726727
ref $($mutability)* visibility_scope,
@@ -732,6 +733,9 @@ macro_rules! make_mir_visitor {
732733
local,
733734
source_info: *source_info,
734735
});
736+
if let Some(user_ty) = user_ty {
737+
self.visit_canonical_ty(user_ty);
738+
}
735739
self.visit_source_info(source_info);
736740
self.visit_source_scope(visibility_scope);
737741
}

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,25 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
275275
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
276276
self.super_local_decl(local, local_decl);
277277
self.sanitize_type(local_decl, local_decl.ty);
278+
279+
if let Some(user_ty) = local_decl.user_ty {
280+
if let Err(terr) = self.cx.relate_type_and_user_type(
281+
local_decl.ty,
282+
ty::Variance::Invariant,
283+
user_ty,
284+
Locations::All,
285+
) {
286+
span_mirbug!(
287+
self,
288+
local,
289+
"bad user type on variable {:?}: {:?} != {:?} ({:?})",
290+
local,
291+
local_decl.ty,
292+
local_decl.user_ty,
293+
terr,
294+
);
295+
}
296+
}
278297
}
279298

280299
fn visit_mir(&mut self, mir: &Mir<'tcx>) {

src/librustc_mir/build/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
143143
None, remainder_span, lint_level, slice::from_ref(&pattern),
144144
ArmHasGuard(false), None);
145145

146-
this.visit_bindings(&pattern, &mut |this, _, _, _, node, span, _| {
146+
this.visit_bindings(&pattern, None, &mut |this, _, _, _, node, span, _, _| {
147147
this.storage_live_binding(block, node, span, OutsideGuard);
148148
this.schedule_drop_for_binding(node, span, OutsideGuard);
149149
})

src/librustc_mir/build/expr/into.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
296296
let ptr_temp = this.local_decls.push(LocalDecl {
297297
mutability: Mutability::Mut,
298298
ty: ptr_ty,
299+
user_ty: None,
299300
name: None,
300301
source_info,
301302
visibility_scope: source_info.scope,

src/librustc_mir/build/matches/mod.rs

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
399399
let num_patterns = patterns.len();
400400
self.visit_bindings(
401401
&patterns[0],
402-
&mut |this, mutability, name, mode, var, span, ty| {
402+
None,
403+
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
403404
if visibility_scope.is_none() {
404405
visibility_scope =
405406
Some(this.new_source_scope(scope_span, LintLevel::Inherited, None));
@@ -421,6 +422,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
421422
num_patterns,
422423
var,
423424
ty,
425+
user_ty,
424426
has_guard,
425427
opt_match_place.map(|(x, y)| (x.cloned(), y)),
426428
patterns[0].span,
@@ -470,10 +472,21 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
470472
);
471473
}
472474

473-
pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
474-
where
475-
F: FnMut(&mut Self, Mutability, Name, BindingMode, NodeId, Span, Ty<'tcx>),
476-
{
475+
pub fn visit_bindings(
476+
&mut self,
477+
pattern: &Pattern<'tcx>,
478+
pattern_user_ty: Option<CanonicalTy<'tcx>>,
479+
f: &mut impl FnMut(
480+
&mut Self,
481+
Mutability,
482+
Name,
483+
BindingMode,
484+
NodeId,
485+
Span,
486+
Ty<'tcx>,
487+
Option<CanonicalTy<'tcx>>,
488+
),
489+
) {
477490
match *pattern.kind {
478491
PatternKind::Binding {
479492
mutability,
@@ -484,9 +497,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
484497
ref subpattern,
485498
..
486499
} => {
487-
f(self, mutability, name, mode, var, pattern.span, ty);
500+
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty);
488501
if let Some(subpattern) = subpattern.as_ref() {
489-
self.visit_bindings(subpattern, f);
502+
self.visit_bindings(subpattern, pattern_user_ty, f);
490503
}
491504
}
492505
PatternKind::Array {
@@ -499,21 +512,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
499512
ref slice,
500513
ref suffix,
501514
} => {
515+
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
502516
for subpattern in prefix.iter().chain(slice).chain(suffix) {
503-
self.visit_bindings(subpattern, f);
517+
self.visit_bindings(subpattern, None, f);
504518
}
505519
}
506520
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
507-
PatternKind::AscribeUserType { ref subpattern, .. }
508-
| PatternKind::Deref { ref subpattern } => {
509-
self.visit_bindings(subpattern, f);
521+
PatternKind::Deref { ref subpattern } => {
522+
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
523+
self.visit_bindings(subpattern, None, f);
524+
}
525+
PatternKind::AscribeUserType { ref subpattern, user_ty } => {
526+
// This corresponds to something like
527+
//
528+
// ```
529+
// let (p1: T1): T2 = ...;
530+
// ```
531+
//
532+
// Not presently possible, though maybe someday.
533+
assert!(pattern_user_ty.is_none());
534+
self.visit_bindings(subpattern, Some(user_ty), f)
510535
}
511536
PatternKind::Leaf { ref subpatterns }
512537
| PatternKind::Variant {
513538
ref subpatterns, ..
514539
} => {
540+
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
515541
for subpattern in subpatterns {
516-
self.visit_bindings(&subpattern.pattern, f);
542+
self.visit_bindings(&subpattern.pattern, None, f);
517543
}
518544
}
519545
}
@@ -1375,6 +1401,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
13751401
num_patterns: usize,
13761402
var_id: NodeId,
13771403
var_ty: Ty<'tcx>,
1404+
user_var_ty: Option<CanonicalTy<'tcx>>,
13781405
has_guard: ArmHasGuard,
13791406
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
13801407
pat_span: Span,
@@ -1392,7 +1419,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
13921419
};
13931420
let local = LocalDecl::<'tcx> {
13941421
mutability,
1395-
ty: var_ty.clone(),
1422+
ty: var_ty,
1423+
user_ty: user_var_ty,
13961424
name: Some(name),
13971425
source_info,
13981426
visibility_scope,
@@ -1424,6 +1452,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14241452
// See previous comment.
14251453
mutability: Mutability::Not,
14261454
ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
1455+
user_ty: None,
14271456
name: Some(name),
14281457
source_info,
14291458
visibility_scope,

src/librustc_mir/build/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
730730
self.local_decls.push(LocalDecl {
731731
mutability: Mutability::Mut,
732732
ty,
733+
user_ty: None,
733734
source_info,
734735
visibility_scope: source_info.scope,
735736
name,

src/librustc_mir/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
3939
#![feature(if_while_or_patterns)]
4040
#![feature(try_from)]
4141
#![feature(reverse_bits)]
42+
#![feature(underscore_imports)]
4243

4344
#![recursion_limit="256"]
4445

src/librustc_mir/shim.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ enum CallKind {
140140
fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
141141
let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span };
142142
LocalDecl {
143-
mutability, ty, name: None,
143+
mutability, ty,
144+
user_ty: None,
145+
name: None,
144146
source_info,
145147
visibility_scope: source_info.scope,
146148
internal: false,

0 commit comments

Comments
 (0)