Skip to content

Commit b569caf

Browse files
committed
Checkpoint: Added abstraction over collection of projections into user type.
I did not think I would need this in the MIR, but in general local decls are going to need to support this. (That, or we need to be able define a least-upper-bound for a collection of types encountered via the pattern compilation.)
1 parent 28ce99d commit b569caf

File tree

13 files changed

+148
-53
lines changed

13 files changed

+148
-53
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,3 +608,4 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::UserTypeAnnotation<
608608
}
609609

610610
impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base });
611+
impl_stable_hash_for!(struct mir::UserTypeProjections<'tcx> { contents });

src/librustc/mir/mod.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ pub struct LocalDecl<'tcx> {
710710
/// e.g. via `let x: T`, then we carry that type here. The MIR
711711
/// borrow checker needs this information since it can affect
712712
/// region inference.
713-
pub user_ty: Option<(UserTypeProjection<'tcx>, Span)>,
713+
pub user_ty: UserTypeProjections<'tcx>,
714714

715715
/// Name of the local, used in debuginfo and pretty-printing.
716716
///
@@ -882,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> {
882882
LocalDecl {
883883
mutability,
884884
ty,
885-
user_ty: None,
885+
user_ty: UserTypeProjections::none(),
886886
name: None,
887887
source_info: SourceInfo {
888888
span,
@@ -903,7 +903,7 @@ impl<'tcx> LocalDecl<'tcx> {
903903
LocalDecl {
904904
mutability: Mutability::Mut,
905905
ty: return_ty,
906-
user_ty: None,
906+
user_ty: UserTypeProjections::none(),
907907
source_info: SourceInfo {
908908
span,
909909
scope: OUTERMOST_SOURCE_SCOPE,
@@ -2449,6 +2449,42 @@ EnumLiftImpl! {
24492449
}
24502450
}
24512451

2452+
/// A collection of projections into user types.
2453+
///
2454+
/// They are projections because a binding can occur a part of a
2455+
/// parent pattern that has been ascribed a type.
2456+
///
2457+
/// Its a collection because there can be multiple type ascriptions on
2458+
/// the path from the root of the pattern down to the binding itself.
2459+
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
2460+
pub struct UserTypeProjections<'tcx> {
2461+
pub(crate) contents: Vec<(UserTypeProjection<'tcx>, Span)>,
2462+
}
2463+
2464+
BraceStructTypeFoldableImpl! {
2465+
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections<'tcx> {
2466+
contents
2467+
}
2468+
}
2469+
2470+
impl<'tcx> UserTypeProjections<'tcx> {
2471+
pub fn none() -> Self {
2472+
UserTypeProjections { contents: vec![] }
2473+
}
2474+
2475+
pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection<'tcx>, Span)>) -> Self {
2476+
UserTypeProjections { contents: projs.collect() }
2477+
}
2478+
2479+
pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection<'tcx>, Span)> {
2480+
self.contents.iter()
2481+
}
2482+
2483+
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
2484+
self.contents.iter().map(|&(ref user_type, _span)| user_type)
2485+
}
2486+
}
2487+
24522488
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
24532489
pub struct UserTypeProjection<'tcx> {
24542490
pub base: UserTypeAnnotation<'tcx>,

src/librustc/mir/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ macro_rules! make_mir_visitor {
743743
local,
744744
source_info: *source_info,
745745
});
746-
if let Some((user_ty, _)) = user_ty {
746+
for (user_ty, _) in & $($mutability)* user_ty.contents {
747747
self.visit_user_type_projection(user_ty);
748748
}
749749
self.visit_source_info(source_info);

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
284284
if let Err(terr) = self.cx.relate_type_and_user_type(
285285
constant.ty,
286286
ty::Variance::Invariant,
287-
UserTypeProjection { base: user_ty },
287+
&UserTypeProjection { base: user_ty },
288288
location.to_locations(),
289289
ConstraintCategory::Boring,
290290
) {
@@ -310,12 +310,12 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
310310
self.super_local_decl(local, local_decl);
311311
self.sanitize_type(local_decl, local_decl.ty);
312312

313-
if let Some((user_ty, span)) = local_decl.user_ty {
313+
for (user_ty, span) in local_decl.user_ty.projections_and_spans() {
314314
if let Err(terr) = self.cx.relate_type_and_user_type(
315315
local_decl.ty,
316316
ty::Variance::Invariant,
317317
user_ty,
318-
Locations::All(span),
318+
Locations::All(*span),
319319
ConstraintCategory::TypeAnnotation,
320320
) {
321321
span_mirbug!(
@@ -971,7 +971,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
971971
&mut self,
972972
a: Ty<'tcx>,
973973
v: ty::Variance,
974-
user_ty: UserTypeProjection<'tcx>,
974+
user_ty: &UserTypeProjection<'tcx>,
975975
locations: Locations,
976976
category: ConstraintCategory,
977977
) -> Fallible<()> {
@@ -1173,7 +1173,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
11731173
if let Err(terr) = self.relate_type_and_user_type(
11741174
rv_ty,
11751175
ty::Variance::Invariant,
1176-
UserTypeProjection { base: user_ty },
1176+
&UserTypeProjection { base: user_ty },
11771177
location.to_locations(),
11781178
ConstraintCategory::Boring,
11791179
) {
@@ -1226,7 +1226,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
12261226
);
12271227
};
12281228
}
1229-
StatementKind::AscribeUserType(ref place, variance, box c_ty) => {
1229+
StatementKind::AscribeUserType(ref place, variance, box ref c_ty) => {
12301230
let place_ty = place.ty(mir, tcx).to_ty(tcx);
12311231
if let Err(terr) = self.relate_type_and_user_type(
12321232
place_ty,

src/librustc_mir/build/block.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
151151
None, remainder_span, lint_level, slice::from_ref(&pattern),
152152
ArmHasGuard(false), None);
153153

154-
this.visit_bindings(&pattern, None, &mut |this, _, _, _, node, span, _, _| {
155-
this.storage_live_binding(block, node, span, OutsideGuard);
156-
this.schedule_drop_for_binding(node, span, OutsideGuard);
157-
})
154+
this.visit_bindings(
155+
&pattern,
156+
&PatternTypeProjections::none(),
157+
&mut |this, _, _, _, node, span, _, _| {
158+
this.storage_live_binding(block, node, span, OutsideGuard);
159+
this.schedule_drop_for_binding(node, span, OutsideGuard);
160+
})
158161
}
159162

160163
// Enter the source scope, after evaluating the initializer.

src/librustc_mir/build/expr/into.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
306306
let ptr_temp = this.local_decls.push(LocalDecl {
307307
mutability: Mutability::Mut,
308308
ty: ptr_ty,
309-
user_ty: None,
309+
user_ty: UserTypeProjections::none(),
310310
name: None,
311311
source_info,
312312
visibility_scope: source_info.scope,

src/librustc_mir/build/matches/mod.rs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
1818
use build::{BlockAnd, BlockAndExtension, Builder};
1919
use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
2020
use hair::*;
21+
use hair::pattern::PatternTypeProjections;
2122
use rustc::hir;
2223
use rustc::mir::*;
2324
use rustc::ty::{self, Ty};
@@ -415,7 +416,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
415416
let num_patterns = patterns.len();
416417
self.visit_bindings(
417418
&patterns[0],
418-
None,
419+
&PatternTypeProjections::none(),
419420
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
420421
if visibility_scope.is_none() {
421422
visibility_scope =
@@ -491,7 +492,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
491492
pub(super) fn visit_bindings(
492493
&mut self,
493494
pattern: &Pattern<'tcx>,
494-
mut pattern_user_ty: Option<(PatternTypeProjection<'tcx>, Span)>,
495+
pattern_user_ty: &PatternTypeProjections<'tcx>,
495496
f: &mut impl FnMut(
496497
&mut Self,
497498
Mutability,
@@ -500,7 +501,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
500501
NodeId,
501502
Span,
502503
Ty<'tcx>,
503-
Option<(PatternTypeProjection<'tcx>, Span)>,
504+
&PatternTypeProjections<'tcx>,
504505
),
505506
) {
506507
match *pattern.kind {
@@ -513,20 +514,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
513514
ref subpattern,
514515
..
515516
} => {
516-
match mode {
517-
BindingMode::ByValue => { }
517+
let pattern_ref_binding; // sidestep temp lifetime limitations.
518+
let binding_user_ty = match mode {
519+
BindingMode::ByValue => { pattern_user_ty }
518520
BindingMode::ByRef(..) => {
519521
// If this is a `ref` binding (e.g., `let ref
520522
// x: T = ..`), then the type of `x` is not
521-
// `T` but rather `&T`, so ignore
522-
// `pattern_user_ty` for now.
523-
//
524-
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
525-
pattern_user_ty = None;
523+
// `T` but rather `&T`.
524+
pattern_ref_binding = pattern_user_ty.ref_binding();
525+
&pattern_ref_binding
526526
}
527-
}
527+
};
528528

529-
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty);
529+
f(self, mutability, name, mode, var, pattern.span, ty, binding_user_ty);
530530
if let Some(subpattern) = subpattern.as_ref() {
531531
self.visit_bindings(subpattern, pattern_user_ty, f);
532532
}
@@ -541,33 +541,39 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
541541
ref slice,
542542
ref suffix,
543543
} => {
544-
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
545-
for subpattern in prefix.iter().chain(slice).chain(suffix) {
546-
self.visit_bindings(subpattern, None, f);
544+
for subpattern in prefix {
545+
self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
546+
}
547+
for subpattern in slice {
548+
self.visit_bindings(subpattern, &pattern_user_ty.subslice(), f);
549+
}
550+
for subpattern in suffix {
551+
self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
547552
}
548553
}
549554
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
550555
PatternKind::Deref { ref subpattern } => {
551-
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
552-
self.visit_bindings(subpattern, None, f);
556+
self.visit_bindings(subpattern, &pattern_user_ty.deref(), f);
553557
}
554558
PatternKind::AscribeUserType { ref subpattern, user_ty, user_ty_span } => {
555559
// This corresponds to something like
556560
//
557561
// ```
558562
// let A::<'a>(_): A<'static> = ...;
559563
// ```
560-
//
561-
// FIXME(#47184): handle `pattern_user_ty` somehow
562-
self.visit_bindings(subpattern, Some((user_ty, user_ty_span)), f)
564+
let pattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span);
565+
self.visit_bindings(subpattern, &pattern_user_ty, f)
563566
}
564-
PatternKind::Leaf { ref subpatterns }
565-
| PatternKind::Variant {
566-
ref subpatterns, ..
567-
} => {
568-
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
569-
for subpattern in subpatterns {
570-
self.visit_bindings(&subpattern.pattern, None, f);
567+
568+
PatternKind::Leaf { ref subpatterns } => {
569+
for (j, subpattern) in subpatterns.iter().enumerate() {
570+
self.visit_bindings(&subpattern.pattern, &pattern_user_ty.leaf(j), f);
571+
}
572+
}
573+
574+
PatternKind::Variant { ref subpatterns, .. } => {
575+
for (j, subpattern) in subpatterns.iter().enumerate() {
576+
self.visit_bindings(&subpattern.pattern, &pattern_user_ty.variant(j), f);
571577
}
572578
}
573579
}
@@ -1470,7 +1476,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14701476
num_patterns: usize,
14711477
var_id: NodeId,
14721478
var_ty: Ty<'tcx>,
1473-
user_var_ty: Option<(PatternTypeProjection<'tcx>, Span)>,
1479+
user_var_ty: &PatternTypeProjections<'tcx>,
14741480
has_guard: ArmHasGuard,
14751481
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
14761482
pat_span: Span,
@@ -1489,7 +1495,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14891495
let local = LocalDecl::<'tcx> {
14901496
mutability,
14911497
ty: var_ty,
1492-
user_ty: user_var_ty.map(|(ut, sp)| (ut.user_ty(), sp)),
1498+
user_ty: user_var_ty.clone().user_ty(),
14931499
name: Some(name),
14941500
source_info,
14951501
visibility_scope,
@@ -1522,7 +1528,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
15221528
// See previous comment.
15231529
mutability: Mutability::Not,
15241530
ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
1525-
user_ty: None,
1531+
user_ty: UserTypeProjections::none(),
15261532
name: Some(name),
15271533
source_info,
15281534
visibility_scope,

src/librustc_mir/build/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
845845
self.local_decls.push(LocalDecl {
846846
mutability: Mutability::Mut,
847847
ty,
848-
user_ty: None,
848+
user_ty: UserTypeProjections::none(),
849849
source_info,
850850
visibility_scope: source_info.scope,
851851
name,

src/librustc_mir/hair/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ use self::cx::Cx;
2727
pub mod cx;
2828

2929
pub mod pattern;
30-
pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternTypeProjection, FieldPattern};
30+
pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
31+
pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
3132

3233
mod util;
3334

src/librustc_mir/hair/pattern/mod.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use const_eval::{const_field, const_variant_index};
2121
use hair::util::UserAnnotatedTyHelpers;
2222

2323
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
24-
use rustc::mir::{UserTypeAnnotation, UserTypeProjection};
24+
use rustc::mir::{UserTypeAnnotation, UserTypeProjection, UserTypeProjections};
2525
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
2626
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
2727
use rustc::ty::subst::{Substs, Kind};
@@ -65,6 +65,54 @@ pub struct Pattern<'tcx> {
6565
pub kind: Box<PatternKind<'tcx>>,
6666
}
6767

68+
69+
#[derive(Clone, Debug)]
70+
pub(crate) struct PatternTypeProjections<'tcx> {
71+
contents: Vec<(PatternTypeProjection<'tcx>, Span)>,
72+
}
73+
74+
impl<'tcx> PatternTypeProjections<'tcx> {
75+
pub(crate) fn user_ty(self) -> UserTypeProjections<'tcx> {
76+
UserTypeProjections::from_projections(
77+
self.contents.into_iter().map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(), span)))
78+
}
79+
80+
pub(crate) fn none() -> Self {
81+
PatternTypeProjections { contents: vec![] }
82+
}
83+
84+
pub(crate) fn ref_binding(&self) -> Self {
85+
// FIXME(#47184): ignore for now
86+
PatternTypeProjections { contents: vec![] }
87+
}
88+
89+
pub(crate) fn index(&self) -> Self {
90+
unimplemented!()
91+
}
92+
93+
pub(crate) fn subslice(&self) -> Self {
94+
unimplemented!()
95+
}
96+
97+
pub(crate) fn deref(&self) -> Self {
98+
unimplemented!()
99+
}
100+
101+
pub(crate) fn add_user_type(&self, user_ty: PatternTypeProjection<'tcx>, sp: Span) -> Self {
102+
let mut new = self.clone();
103+
new.contents.push((user_ty, sp));
104+
new
105+
}
106+
107+
pub(crate) fn leaf(&self, _index: usize) -> Self {
108+
unimplemented!()
109+
}
110+
111+
pub(crate) fn variant(&self, _index: usize) -> Self {
112+
unimplemented!()
113+
}
114+
}
115+
68116
#[derive(Copy, Clone, Debug)]
69117
pub struct PatternTypeProjection<'tcx>(UserTypeProjection<'tcx>);
70118

src/librustc_mir/shim.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
142142
LocalDecl {
143143
mutability,
144144
ty,
145-
user_ty: None,
145+
user_ty: UserTypeProjections::none(),
146146
name: None,
147147
source_info,
148148
visibility_scope: source_info.scope,

0 commit comments

Comments
 (0)