]> git.lizzy.rs Git - rust.git/commitdiff
add pattern type ascriptions for tuple/brace structs/enums
authorNiko Matsakis <niko@alum.mit.edu>
Mon, 8 Oct 2018 23:03:24 +0000 (19:03 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 8 Oct 2018 23:20:37 +0000 (19:20 -0400)
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_typeck/check/mod.rs
src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr [new file with mode: 0644]

index 656c78a46ed78c84d75ce5366cdc21c004fec938..c2a7172d54cca22cf2a105366bf4d27a510d2c67 100644 (file)
@@ -1307,6 +1307,14 @@ fn ascribe_types<'pat>(
     ) {
         for ascription in ascriptions {
             let source_info = self.source_info(ascription.span);
+
+            debug!(
+                "adding user ascription at span {:?} of place {:?} and {:?}",
+                source_info.span,
+                ascription.source,
+                ascription.user_ty,
+            );
+
             self.cfg.push(
                 block,
                 Statement {
index b22cc4a1a42b50d14c1d139f99a9044c334b13b9..04090e5087ffc47c21a579d03e231bc195909447 100644 (file)
@@ -18,6 +18,8 @@
 
 use const_eval::{const_field, const_variant_index};
 
+use hair::util::UserAnnotatedTyHelpers;
+
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
 use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
@@ -529,8 +531,9 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                                        field: Field::new(i),
                                        pattern: self.lower_pattern(field),
                                    })
-                                   .collect();
-                self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
+                    .collect();
+
+                self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
             }
 
             PatKind::Struct(ref qpath, ref fields, _) => {
@@ -546,7 +549,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                           })
                           .collect();
 
-                self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
+                self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
             }
         };
 
@@ -637,12 +640,12 @@ fn slice_or_array_pattern(
     fn lower_variant_or_leaf(
         &mut self,
         def: Def,
+        hir_id: hir::HirId,
         span: Span,
         ty: Ty<'tcx>,
-        subpatterns: Vec<FieldPattern<'tcx>>)
-        -> PatternKind<'tcx>
-    {
-        match def {
+        subpatterns: Vec<FieldPattern<'tcx>>,
+    ) -> PatternKind<'tcx> {
+        let mut kind = match def {
             Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
                 let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
                 let adt_def = self.tcx.adt_def(enum_id);
@@ -675,7 +678,24 @@ fn lower_variant_or_leaf(
                 self.errors.push(PatternError::NonConstPath(span));
                 PatternKind::Wild
             }
+        };
+
+        if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
+            let subpattern = Pattern {
+                span,
+                ty,
+                kind: Box::new(kind),
+            };
+
+            debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span);
+
+            kind = PatternKind::AscribeUserType {
+                subpattern,
+                user_ty,
+            };
         }
+
+        kind
     }
 
     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
@@ -729,7 +749,7 @@ fn lower_path(&mut self,
                     },
                 }
             }
-            _ => self.lower_variant_or_leaf(def, span, ty, vec![]),
+            _ => self.lower_variant_or_leaf(def, id, span, ty, vec![]),
         };
 
         Pattern {
@@ -894,6 +914,17 @@ fn const_to_pat(
     }
 }
 
+impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
+        self.tcx
+    }
+
+    fn tables(&self) -> &ty::TypeckTables<'tcx> {
+        self.tables
+    }
+}
+
+
 pub trait PatternFoldable<'tcx> : Sized {
     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
         self.super_fold_with(folder)
index 529f1e6161be987dd9a429d0c9d173f8066b9a5b..52ed279b853935466f78e6760b6508d5b81c4970 100644 (file)
@@ -2164,6 +2164,13 @@ pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
     /// occurred**, so that annotations like `Vec<_>` are preserved
     /// properly.
     pub fn write_user_substs_from_substs(&self, hir_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
+        debug!(
+            "write_user_substs_from_substs({:?}, {:?}) in fcx {}",
+            hir_id,
+            substs,
+            self.tag(),
+        );
+
         if !substs.is_noop() {
             let user_substs = self.infcx.canonicalize_response(&substs);
             debug!("instantiate_value_path: user_substs = {:?}", user_substs);
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs
new file mode 100644 (file)
index 0000000..526134b
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+enum Foo<'a> {
+    Bar { field: &'a u32 }
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static> { field: _z } = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
new file mode 100644 (file)
index 0000000..5dbbf7c
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:9:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_enum_variant.rs:16:33
+   |
+LL |     let foo = Foo::Bar { field: &y };
+   |                                 ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs
new file mode 100644 (file)
index 0000000..1c92858
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+struct Foo<'a> { field: &'a u32 }
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static> { field: _z } = foo;
+}
+
+fn in_main() {
+    let y = 22;
+    let foo = Foo { field: &y };
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static> { field: _z } => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
new file mode 100644 (file)
index 0000000..0108a18
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:7:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_brace_struct.rs:14:28
+   |
+LL |     let foo = Foo { field: &y };
+   |                            ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs
new file mode 100644 (file)
index 0000000..d6c364f
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(nll)]
+
+enum Foo<'a> {
+    Bar(&'a u32)
+}
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::Bar::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo::Bar(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::Bar::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
new file mode 100644 (file)
index 0000000..b18fdc3
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:9:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_enum_variant.rs:16:24
+   |
+LL |     let foo = Foo::Bar(&y);
+   |                        ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs
new file mode 100644 (file)
index 0000000..626ca90
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(nll)]
+
+struct Foo<'a>(&'a u32);
+
+fn in_let() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    let Foo::<'static>(_z) = foo;
+}
+
+fn in_match() {
+    let y = 22;
+    let foo = Foo(&y);
+    //~^ ERROR `y` does not live long enough
+    match foo {
+        Foo::<'static>(_z) => {
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr b/src/test/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
new file mode 100644 (file)
index 0000000..b72fda9
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:7:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/pattern_substs_on_tuple_struct.rs:14:19
+   |
+LL |     let foo = Foo(&y);
+   |                   ^^ borrowed value does not live long enough
+...
+LL | }
+   | - `y` dropped here while still borrowed
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.