add a AscribeUserType
pattern, largely ignored
This commit is contained in:
parent
4b5f19a0b0
commit
50754d0513
@ -19,7 +19,7 @@ use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
|
||||
use build::scope::{CachedBlock, DropKind};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::bitvec::BitArray;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::{self, CanonicalTy, Ty};
|
||||
use rustc::mir::*;
|
||||
use rustc::hir;
|
||||
use hair::*;
|
||||
@ -168,6 +168,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
span: pattern.span,
|
||||
match_pairs: vec![MatchPair::new(discriminant_place.clone(), pattern)],
|
||||
bindings: vec![],
|
||||
ascriptions: vec![],
|
||||
guard,
|
||||
arm_index,
|
||||
pat_index,
|
||||
@ -253,6 +254,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
span: irrefutable_pat.span,
|
||||
match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)],
|
||||
bindings: vec![],
|
||||
ascriptions: vec![],
|
||||
guard: None,
|
||||
|
||||
// since we don't call `match_candidates`, next fields is unused
|
||||
@ -398,6 +400,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {
|
||||
}
|
||||
PatternKind::AscribeUserType { ref subpattern, .. } |
|
||||
PatternKind::Deref { ref subpattern } => {
|
||||
self.visit_bindings(subpattern, f);
|
||||
}
|
||||
@ -429,6 +432,9 @@ pub struct Candidate<'pat, 'tcx:'pat> {
|
||||
// ...these bindings established...
|
||||
bindings: Vec<Binding<'tcx>>,
|
||||
|
||||
// ...these types asserted...
|
||||
ascriptions: Vec<Ascription<'tcx>>,
|
||||
|
||||
// ...and the guard must be evaluated...
|
||||
guard: Option<Guard<'tcx>>,
|
||||
|
||||
@ -454,6 +460,16 @@ struct Binding<'tcx> {
|
||||
binding_mode: BindingMode<'tcx>,
|
||||
}
|
||||
|
||||
/// Indicates that the type of `source` must be a subtype of the
|
||||
/// user-given type `user_ty`; this is basically a no-op but can
|
||||
/// influence region inference.
|
||||
#[derive(Clone, Debug)]
|
||||
struct Ascription<'tcx> {
|
||||
span: Span,
|
||||
source: Place<'tcx>,
|
||||
user_ty: CanonicalTy<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MatchPair<'pat, 'tcx:'pat> {
|
||||
// this place...
|
||||
|
@ -23,7 +23,7 @@
|
||||
//! testing a value against a constant.
|
||||
|
||||
use build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use build::matches::{Binding, MatchPair, Candidate};
|
||||
use build::matches::{Ascription, Binding, MatchPair, Candidate};
|
||||
use hair::*;
|
||||
use rustc::mir::*;
|
||||
|
||||
@ -63,6 +63,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
candidate: &mut Candidate<'pat, 'tcx>)
|
||||
-> Result<(), MatchPair<'pat, 'tcx>> {
|
||||
match *match_pair.pattern.kind {
|
||||
PatternKind::AscribeUserType { ref subpattern, user_ty } => {
|
||||
candidate.ascriptions.push(Ascription {
|
||||
span: match_pair.pattern.span,
|
||||
user_ty,
|
||||
source: match_pair.place.clone(),
|
||||
});
|
||||
|
||||
candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
PatternKind::Wild => {
|
||||
// nothing left to do
|
||||
Ok(())
|
||||
|
@ -96,6 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::AscribeUserType { .. } |
|
||||
PatternKind::Array { .. } |
|
||||
PatternKind::Slice { .. } |
|
||||
PatternKind::Wild |
|
||||
@ -138,6 +139,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
PatternKind::Array { .. } |
|
||||
PatternKind::Wild |
|
||||
PatternKind::Binding { .. } |
|
||||
PatternKind::AscribeUserType { .. } |
|
||||
PatternKind::Leaf { .. } |
|
||||
PatternKind::Deref { .. } => {
|
||||
// don't know how to add these patterns to a switch
|
||||
@ -638,6 +640,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
span: candidate.span,
|
||||
match_pairs: other_match_pairs,
|
||||
bindings: candidate.bindings.clone(),
|
||||
ascriptions: candidate.ascriptions.clone(),
|
||||
guard: candidate.guard.clone(),
|
||||
arm_index: candidate.arm_index,
|
||||
pat_index: candidate.pat_index,
|
||||
@ -702,6 +705,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
span: candidate.span,
|
||||
match_pairs: all_match_pairs,
|
||||
bindings: candidate.bindings.clone(),
|
||||
ascriptions: candidate.ascriptions.clone(),
|
||||
guard: candidate.guard.clone(),
|
||||
arm_index: candidate.arm_index,
|
||||
pat_index: candidate.pat_index,
|
||||
|
@ -76,14 +76,26 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
first_statement_index: region::FirstStatementIndex::new(index),
|
||||
});
|
||||
|
||||
let ty = local.ty.clone().map(|ty| ty.hir_id);
|
||||
let pattern = cx.pattern_from_hir(&local.pat);
|
||||
let mut pattern = cx.pattern_from_hir(&local.pat);
|
||||
|
||||
if let Some(ty) = &local.ty {
|
||||
if let Some(user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) {
|
||||
pattern = Pattern {
|
||||
ty: pattern.ty,
|
||||
span: pattern.span,
|
||||
kind: Box::new(PatternKind::AscribeUserType {
|
||||
user_ty: *user_ty,
|
||||
subpattern: pattern
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
kind: StmtKind::Let {
|
||||
remainder_scope: remainder_scope,
|
||||
init_scope: region::Scope::Node(hir_id.local_id),
|
||||
pattern,
|
||||
ty,
|
||||
initializer: local.init.to_ref(),
|
||||
lint_level: cx.lint_level_of(local.id),
|
||||
},
|
||||
|
@ -94,6 +94,8 @@ pub enum StmtKind<'tcx> {
|
||||
init_scope: region::Scope,
|
||||
|
||||
/// `let <PAT> = ...`
|
||||
///
|
||||
/// if a type is included, it is added as an ascription pattern
|
||||
pattern: Pattern<'tcx>,
|
||||
|
||||
/// let pat: ty = <INIT> ...
|
||||
|
@ -1235,6 +1235,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt,
|
||||
-> Option<Vec<Constructor<'tcx>>>
|
||||
{
|
||||
match *pat.kind {
|
||||
PatternKind::AscribeUserType { ref subpattern, .. } => pat_constructors(cx, subpattern, pcx),
|
||||
PatternKind::Binding { .. } | PatternKind::Wild => None,
|
||||
PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]),
|
||||
PatternKind::Variant { adt_def, variant_index, .. } => {
|
||||
@ -1606,6 +1607,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
||||
let pat = &r[0];
|
||||
|
||||
let head: Option<Vec<&Pattern>> = match *pat.kind {
|
||||
PatternKind::AscribeUserType { ref subpattern, .. } =>
|
||||
specialize(cx, ::std::slice::from_ref(&subpattern), constructor, wild_patterns),
|
||||
|
||||
PatternKind::Binding { .. } | PatternKind::Wild => {
|
||||
Some(wild_patterns.to_owned())
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ use interpret::{const_field, const_variant_index};
|
||||
|
||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
|
||||
use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
|
||||
use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
|
||||
use rustc::ty::subst::{Substs, Kind};
|
||||
use rustc::hir::{self, PatKind, RangeEnd};
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
@ -66,6 +66,11 @@ pub struct Pattern<'tcx> {
|
||||
pub enum PatternKind<'tcx> {
|
||||
Wild,
|
||||
|
||||
AscribeUserType {
|
||||
user_ty: CanonicalTy<'tcx>,
|
||||
subpattern: Pattern<'tcx>,
|
||||
},
|
||||
|
||||
/// x, ref x, x @ P, etc
|
||||
Binding {
|
||||
mutability: Mutability,
|
||||
@ -125,6 +130,8 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self.kind {
|
||||
PatternKind::Wild => write!(f, "_"),
|
||||
PatternKind::AscribeUserType { ref subpattern, .. } =>
|
||||
write!(f, "{}: _", subpattern),
|
||||
PatternKind::Binding { mutability, name, mode, ref subpattern, .. } => {
|
||||
let is_mut = match mode {
|
||||
BindingMode::ByValue => mutability == Mutability::Mut,
|
||||
@ -939,7 +946,7 @@ macro_rules! CloneImpls {
|
||||
CloneImpls!{ <'tcx>
|
||||
Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>,
|
||||
Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
|
||||
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>
|
||||
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>, CanonicalTy<'tcx>
|
||||
}
|
||||
|
||||
impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
|
||||
@ -973,6 +980,13 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
|
||||
fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
match *self {
|
||||
PatternKind::Wild => PatternKind::Wild,
|
||||
PatternKind::AscribeUserType {
|
||||
ref subpattern,
|
||||
user_ty,
|
||||
} => PatternKind::AscribeUserType {
|
||||
subpattern: subpattern.fold_with(folder),
|
||||
user_ty: user_ty.fold_with(folder),
|
||||
},
|
||||
PatternKind::Binding {
|
||||
mutability,
|
||||
name,
|
||||
|
Loading…
x
Reference in New Issue
Block a user