Skip to content

Commit 50754d0

Browse files
committed
add a AscribeUserType pattern, largely ignored
1 parent 4b5f19a commit 50754d0

File tree

7 files changed

+71
-7
lines changed

7 files changed

+71
-7
lines changed

src/librustc_mir/build/matches/mod.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
1919
use build::scope::{CachedBlock, DropKind};
2020
use rustc_data_structures::fx::FxHashMap;
2121
use rustc_data_structures::bitvec::BitArray;
22-
use rustc::ty::{self, Ty};
22+
use rustc::ty::{self, CanonicalTy, Ty};
2323
use rustc::mir::*;
2424
use rustc::hir;
2525
use hair::*;
@@ -168,6 +168,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
168168
span: pattern.span,
169169
match_pairs: vec![MatchPair::new(discriminant_place.clone(), pattern)],
170170
bindings: vec![],
171+
ascriptions: vec![],
171172
guard,
172173
arm_index,
173174
pat_index,
@@ -253,6 +254,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
253254
span: irrefutable_pat.span,
254255
match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)],
255256
bindings: vec![],
257+
ascriptions: vec![],
256258
guard: None,
257259

258260
// since we don't call `match_candidates`, next fields is unused
@@ -398,6 +400,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
398400
}
399401
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {
400402
}
403+
PatternKind::AscribeUserType { ref subpattern, .. } |
401404
PatternKind::Deref { ref subpattern } => {
402405
self.visit_bindings(subpattern, f);
403406
}
@@ -429,6 +432,9 @@ pub struct Candidate<'pat, 'tcx:'pat> {
429432
// ...these bindings established...
430433
bindings: Vec<Binding<'tcx>>,
431434

435+
// ...these types asserted...
436+
ascriptions: Vec<Ascription<'tcx>>,
437+
432438
// ...and the guard must be evaluated...
433439
guard: Option<Guard<'tcx>>,
434440

@@ -454,6 +460,16 @@ struct Binding<'tcx> {
454460
binding_mode: BindingMode<'tcx>,
455461
}
456462

463+
/// Indicates that the type of `source` must be a subtype of the
464+
/// user-given type `user_ty`; this is basically a no-op but can
465+
/// influence region inference.
466+
#[derive(Clone, Debug)]
467+
struct Ascription<'tcx> {
468+
span: Span,
469+
source: Place<'tcx>,
470+
user_ty: CanonicalTy<'tcx>,
471+
}
472+
457473
#[derive(Clone, Debug)]
458474
pub struct MatchPair<'pat, 'tcx:'pat> {
459475
// this place...

src/librustc_mir/build/matches/simplify.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
//! testing a value against a constant.
2424
2525
use build::{BlockAnd, BlockAndExtension, Builder};
26-
use build::matches::{Binding, MatchPair, Candidate};
26+
use build::matches::{Ascription, Binding, MatchPair, Candidate};
2727
use hair::*;
2828
use rustc::mir::*;
2929

@@ -63,6 +63,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
6363
candidate: &mut Candidate<'pat, 'tcx>)
6464
-> Result<(), MatchPair<'pat, 'tcx>> {
6565
match *match_pair.pattern.kind {
66+
PatternKind::AscribeUserType { ref subpattern, user_ty } => {
67+
candidate.ascriptions.push(Ascription {
68+
span: match_pair.pattern.span,
69+
user_ty,
70+
source: match_pair.place.clone(),
71+
});
72+
73+
candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
74+
75+
Ok(())
76+
}
77+
6678
PatternKind::Wild => {
6779
// nothing left to do
6880
Ok(())

src/librustc_mir/build/matches/test.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
9696
}
9797
}
9898

99+
PatternKind::AscribeUserType { .. } |
99100
PatternKind::Array { .. } |
100101
PatternKind::Slice { .. } |
101102
PatternKind::Wild |
@@ -138,6 +139,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
138139
PatternKind::Array { .. } |
139140
PatternKind::Wild |
140141
PatternKind::Binding { .. } |
142+
PatternKind::AscribeUserType { .. } |
141143
PatternKind::Leaf { .. } |
142144
PatternKind::Deref { .. } => {
143145
// don't know how to add these patterns to a switch
@@ -638,6 +640,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
638640
span: candidate.span,
639641
match_pairs: other_match_pairs,
640642
bindings: candidate.bindings.clone(),
643+
ascriptions: candidate.ascriptions.clone(),
641644
guard: candidate.guard.clone(),
642645
arm_index: candidate.arm_index,
643646
pat_index: candidate.pat_index,
@@ -702,6 +705,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
702705
span: candidate.span,
703706
match_pairs: all_match_pairs,
704707
bindings: candidate.bindings.clone(),
708+
ascriptions: candidate.ascriptions.clone(),
705709
guard: candidate.guard.clone(),
706710
arm_index: candidate.arm_index,
707711
pat_index: candidate.pat_index,

src/librustc_mir/hair/cx/block.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,26 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
7676
first_statement_index: region::FirstStatementIndex::new(index),
7777
});
7878

79-
let ty = local.ty.clone().map(|ty| ty.hir_id);
80-
let pattern = cx.pattern_from_hir(&local.pat);
79+
let mut pattern = cx.pattern_from_hir(&local.pat);
80+
81+
if let Some(ty) = &local.ty {
82+
if let Some(user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) {
83+
pattern = Pattern {
84+
ty: pattern.ty,
85+
span: pattern.span,
86+
kind: Box::new(PatternKind::AscribeUserType {
87+
user_ty: *user_ty,
88+
subpattern: pattern
89+
})
90+
};
91+
}
92+
}
93+
8194
result.push(StmtRef::Mirror(Box::new(Stmt {
8295
kind: StmtKind::Let {
8396
remainder_scope: remainder_scope,
8497
init_scope: region::Scope::Node(hir_id.local_id),
8598
pattern,
86-
ty,
8799
initializer: local.init.to_ref(),
88100
lint_level: cx.lint_level_of(local.id),
89101
},

src/librustc_mir/hair/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ pub enum StmtKind<'tcx> {
9494
init_scope: region::Scope,
9595

9696
/// `let <PAT> = ...`
97+
///
98+
/// if a type is included, it is added as an ascription pattern
9799
pattern: Pattern<'tcx>,
98100

99101
/// let pat: ty = <INIT> ...

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt,
12351235
-> Option<Vec<Constructor<'tcx>>>
12361236
{
12371237
match *pat.kind {
1238+
PatternKind::AscribeUserType { ref subpattern, .. } => pat_constructors(cx, subpattern, pcx),
12381239
PatternKind::Binding { .. } | PatternKind::Wild => None,
12391240
PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]),
12401241
PatternKind::Variant { adt_def, variant_index, .. } => {
@@ -1606,6 +1607,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
16061607
let pat = &r[0];
16071608

16081609
let head: Option<Vec<&Pattern>> = match *pat.kind {
1610+
PatternKind::AscribeUserType { ref subpattern, .. } =>
1611+
specialize(cx, ::std::slice::from_ref(&subpattern), constructor, wild_patterns),
1612+
16091613
PatternKind::Binding { .. } | PatternKind::Wild => {
16101614
Some(wild_patterns.to_owned())
16111615
}

src/librustc_mir/hair/pattern/mod.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use interpret::{const_field, const_variant_index};
2020

2121
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
2222
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
23-
use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
23+
use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
2424
use rustc::ty::subst::{Substs, Kind};
2525
use rustc::hir::{self, PatKind, RangeEnd};
2626
use rustc::hir::def::{Def, CtorKind};
@@ -66,6 +66,11 @@ pub struct Pattern<'tcx> {
6666
pub enum PatternKind<'tcx> {
6767
Wild,
6868

69+
AscribeUserType {
70+
user_ty: CanonicalTy<'tcx>,
71+
subpattern: Pattern<'tcx>,
72+
},
73+
6974
/// x, ref x, x @ P, etc
7075
Binding {
7176
mutability: Mutability,
@@ -125,6 +130,8 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
125130
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126131
match *self.kind {
127132
PatternKind::Wild => write!(f, "_"),
133+
PatternKind::AscribeUserType { ref subpattern, .. } =>
134+
write!(f, "{}: _", subpattern),
128135
PatternKind::Binding { mutability, name, mode, ref subpattern, .. } => {
129136
let is_mut = match mode {
130137
BindingMode::ByValue => mutability == Mutability::Mut,
@@ -939,7 +946,7 @@ macro_rules! CloneImpls {
939946
CloneImpls!{ <'tcx>
940947
Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>,
941948
Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
942-
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>
949+
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>, CanonicalTy<'tcx>
943950
}
944951

945952
impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
@@ -973,6 +980,13 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
973980
fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
974981
match *self {
975982
PatternKind::Wild => PatternKind::Wild,
983+
PatternKind::AscribeUserType {
984+
ref subpattern,
985+
user_ty,
986+
} => PatternKind::AscribeUserType {
987+
subpattern: subpattern.fold_with(folder),
988+
user_ty: user_ty.fold_with(folder),
989+
},
976990
PatternKind::Binding {
977991
mutability,
978992
name,

0 commit comments

Comments
 (0)