]> git.lizzy.rs Git - rust.git/commitdiff
add a `AscribeUserType` pattern, largely ignored
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 31 Aug 2018 22:34:15 +0000 (18:34 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 10 Sep 2018 12:22:31 +0000 (08:22 -0400)
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/simplify.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/mod.rs

index f46e3a9f1fd84c509e863dcd4f6048d9e057196e..21b837f1db93e4ae17280ca78e5d9e63e1951f58 100644 (file)
@@ -19,7 +19,7 @@
 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 @@ pub fn match_expr(&mut self,
                         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 @@ pub fn place_into_pattern(&mut self,
             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 @@ pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
             }
             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...
index 147b8cc2175af9d88de2a6400b16cb5f24c644f1..14da8e9083892fb435c743a83573f5fc412f4839 100644 (file)
@@ -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 @@ fn simplify_match_pair<'pat>(&mut self,
                                  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(())
index 4a0b4b0c88580ffcd8f822333acdd72f788c8ed8..2c606ebf322a844ce1d851bbd21a340bec3e7915 100644 (file)
@@ -96,6 +96,7 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
                 }
             }
 
+            PatternKind::AscribeUserType { .. } |
             PatternKind::Array { .. } |
             PatternKind::Slice { .. } |
             PatternKind::Wild |
@@ -138,6 +139,7 @@ pub fn add_cases_to_switch<'pat>(&mut self,
             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 @@ fn candidate_without_match_pair<'pat>(&mut self,
             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 @@ fn candidate_after_variant_switch<'pat>(&mut self,
             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,
index 6c8b5d97b6ff314abb58ec95be28d7ed02c9998e..85a9734a601011234096a268834990f9b37ee5bc 100644 (file)
@@ -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),
                             },
index 0fd130c9041f87425b1c53bf24173d33b78cc9e0..d86aee5431267b1e3e1fb7044dab29a64867c279 100644 (file)
@@ -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> ...
index d7fbbc88cc16d63e864e93c11e174b5163d852c9..a29c81e38e5a45927de24cdda0802ca7e048b121 100644 (file)
@@ -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())
         }
index 384ee0079dc84c70ec55b11169a9a8e63d18a143..cd44869211a7d9f62d6a32d9568cd46f04c23c91 100644 (file)
@@ -20,7 +20,7 @@
 
 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 @@ fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
 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 @@ fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
     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,