about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2018-11-24 12:56:24 +0100
committerDavid Wood <david@davidtw.co>2018-12-30 14:30:58 +0100
commit4be7214d30b121762c8675c3e732083da262b136 (patch)
tree760abdaa2343eb58aab7b004ef8a2f305083d869
parentb182a21163c673034a89acf01cd8797a8313ed11 (diff)
downloadrust-4be7214d30b121762c8675c3e732083da262b136.tar.gz
rust-4be7214d30b121762c8675c3e732083da262b136.zip
Type annotations in associated constant patterns.
This commit adds support for respecting user type annotations with
associated constants in patterns.
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs26
-rw-r--r--src/librustc_typeck/check/method/mod.rs22
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs2
-rw-r--r--src/test/ui/issue-55511.nll.stderr15
-rw-r--r--src/test/ui/issue-55511.rs18
-rw-r--r--src/test/ui/issue-55511.stderr14
7 files changed, 86 insertions, 13 deletions
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index fd3b07c0357..00de40d8cff 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -848,7 +848,28 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         };
                         match self.tcx.at(span).const_eval(self.param_env.and(cid)) {
                             Ok(value) => {
-                                return self.const_to_pat(instance, value, id, span)
+                                let pattern = self.const_to_pat(instance, value, id, span);
+                                if !is_associated_const {
+                                    return pattern;
+                                }
+
+                                let user_provided_types = self.tables().user_provided_types();
+                                return if let Some(u_ty) = user_provided_types.get(id) {
+                                    let user_ty = PatternTypeProjection::from_user_type(*u_ty);
+                                    Pattern {
+                                        span,
+                                        kind: Box::new(
+                                            PatternKind::AscribeUserType {
+                                                subpattern: pattern,
+                                                user_ty,
+                                                user_ty_span: span,
+                                            }
+                                        ),
+                                        ty: value.ty,
+                                    }
+                                } else {
+                                    pattern
+                                }
                             },
                             Err(_) => {
                                 self.tcx.sess.span_err(
@@ -938,7 +959,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         id: hir::HirId,
         span: Span,
     ) -> Pattern<'tcx> {
-        debug!("const_to_pat: cv={:#?}", cv);
+        debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
         let adt_subpattern = |i, variant_opt| {
             let field = Field::new(i);
             let val = const_field(
@@ -956,6 +977,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                 }
             }).collect::<Vec<_>>()
         };
+        debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
         let kind = match cv.ty.sty {
             ty::Float(_) => {
                 let id = self.tcx.hir().hir_to_node_id(id);
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index fe5f43e3c01..1758f762524 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -357,16 +357,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         })
     }
 
-    pub fn resolve_ufcs(&self,
-                        span: Span,
-                        method_name: ast::Ident,
-                        self_ty: Ty<'tcx>,
-                        expr_id: ast::NodeId)
-                        -> Result<Def, MethodError<'tcx>> {
-        debug!("resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}",
-            method_name,
-            self_ty,
-            expr_id
+    pub fn resolve_ufcs(
+        &self,
+        span: Span,
+        method_name: ast::Ident,
+        self_ty: Ty<'tcx>,
+        expr_id: ast::NodeId
+    ) -> Result<Def, MethodError<'tcx>> {
+        debug!(
+            "resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}",
+            method_name, self_ty, expr_id,
         );
 
         let tcx = self.tcx;
@@ -375,6 +375,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         match self.probe_for_name(span, mode, method_name, IsSuggestion(false),
                                   self_ty, expr_id, ProbeScope::TraitsInScope) {
             Ok(pick) => {
+                debug!("resolve_ufcs: pick={:?}", pick);
                 if let Some(import_id) = pick.import_id {
                     let import_def_id = tcx.hir().local_def_id(import_id);
                     debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
@@ -383,6 +384,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
 
                 let def = pick.item.def();
+                debug!("resolve_ufcs: def={:?}", def);
                 tcx.check_stability(def.def_id(), Some(expr_id), span);
 
                 Ok(def)
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index acb873206d5..ff4574eb283 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4584,6 +4584,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                        span: Span)
                                        -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
     {
+        debug!("resolve_ty_and_def_ufcs: qpath={:?} node_id={:?} span={:?}", qpath, node_id, span);
         let (ty, qself, item_segment) = match *qpath {
             QPath::Resolved(ref opt_qself, ref path) => {
                 return (path.def,
@@ -5104,6 +5105,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             Def::Method(def_id) |
             Def::AssociatedConst(def_id) => {
                 let container = tcx.associated_item(def_id).container;
+                debug!("instantiate_value_path: def={:?} container={:?}", def, container);
                 match container {
                     ty::TraitContainer(trait_did) => {
                         callee::check_legal_trait_for_method_call(tcx, span, trait_did)
diff --git a/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs b/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs
index 647652d0273..4801369cfd1 100644
--- a/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs
+++ b/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![allow(dead_code)]
+#![allow(dead_code, unreachable_patterns)]
 
 struct Foo;
 
diff --git a/src/test/ui/issue-55511.nll.stderr b/src/test/ui/issue-55511.nll.stderr
new file mode 100644
index 00000000000..97f8015dfc1
--- /dev/null
+++ b/src/test/ui/issue-55511.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-55511.rs:13:28
+   |
+LL |     let b = Some(Cell::new(&a));
+   |                            ^^ borrowed value does not live long enough
+LL |     match b {
+LL |         <() as Foo<'static>>::C => { }
+   |         ----------------------- type annotation requires that `a` is borrowed for `'static`
+...
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issue-55511.rs b/src/test/ui/issue-55511.rs
new file mode 100644
index 00000000000..93bd78c44d9
--- /dev/null
+++ b/src/test/ui/issue-55511.rs
@@ -0,0 +1,18 @@
+use std::cell::Cell;
+
+trait Foo<'a> {
+    const C: Option<Cell<&'a u32>>;
+}
+
+impl<'a, T> Foo<'a> for T {
+    const C: Option<Cell<&'a u32>> = None;
+}
+
+fn main() {
+    let a = 22;
+    let b = Some(Cell::new(&a));
+    match b {
+        <() as Foo<'static>>::C => { }
+        _ => { }
+    }
+}
diff --git a/src/test/ui/issue-55511.stderr b/src/test/ui/issue-55511.stderr
new file mode 100644
index 00000000000..24668f04551
--- /dev/null
+++ b/src/test/ui/issue-55511.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-55511.rs:13:29
+   |
+LL |     let b = Some(Cell::new(&a));
+   |                             ^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.