about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-04-08 14:05:06 +0000
committerbors <bors@rust-lang.org>2017-04-08 14:05:06 +0000
commita61011761deeab9e308e6d103b1dc7aaf334f6e3 (patch)
treead81d56b54b321b5afb8f9aa29e593f2cd13b351
parentfe39e94d6cd6eba00b3aadf323b3f4d029aad7eb (diff)
parentc9932b395ada3c367aea5e79645c10657262ea6f (diff)
downloadrust-a61011761deeab9e308e6d103b1dc7aaf334f6e3.tar.gz
rust-a61011761deeab9e308e6d103b1dc7aaf334f6e3.zip
Auto merge of #41055 - Archytaus:compile-fail/const-match-pattern-arm, r=arielb1
Fixed ICEs with pattern matching in const expression

Fixed 2 ICEs with when pattern matching inside a constant expression.

Both of these ICEs now resolve to an appropriate compiler error.

1. ICE was caused by a compiler bug to implement discriminant const qualify.

    I removed this intentionally thrown bug and changed it to a FIXME as the unimplemented expression type is handled as a compiler error elsewhere.

2. ICE was caused during a drop check when checking if a variable lifetime outlives the current scope if there was no parent scope .

    I've changed it to stop checking if there is no parent scope for the current scope. It is valid syntax for a const variable to be assigned a match expression with no enclosing scope.

    The ICE seemed to mainly be used as a defensive check for bugs elsewhere.

Fixes #38199.
Fixes #31577.
Fixes #29093.
Fixes #40012.
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs11
-rw-r--r--src/librustc_typeck/check/dropck.rs9
-rw-r--r--src/test/compile-fail/const-match-pattern-arm.rs25
3 files changed, 33 insertions, 12 deletions
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 9d236bd013c..8eabe92fb98 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -603,7 +603,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             Rvalue::Cast(CastKind::ReifyFnPointer, ..) |
             Rvalue::Cast(CastKind::UnsafeFnPointer, ..) |
             Rvalue::Cast(CastKind::ClosureFnPointer, ..) |
-            Rvalue::Cast(CastKind::Unsize, ..) => {}
+            Rvalue::Cast(CastKind::Unsize, ..) |
+            Rvalue::Discriminant(..) => {}
 
             Rvalue::Len(_) => {
                 // Static lvalues in consts would have errored already,
@@ -721,14 +722,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                 }
             }
 
-            Rvalue::Discriminant(..) => {
-                // FIXME discriminant
-                self.add(Qualif::NOT_CONST);
-                if self.mode != Mode::Fn {
-                    bug!("implement discriminant const qualify");
-                }
-            }
-
             Rvalue::Box(_) => {
                 self.add(Qualif::NOT_CONST);
                 if self.mode != Mode::Fn {
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 90d2a15cf08..9f41373dab1 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -278,9 +278,12 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
     debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
            typ, scope);
 
-    let parent_scope = rcx.tcx.region_maps.opt_encl_scope(scope).unwrap_or_else(|| {
-        span_bug!(span, "no enclosing scope found for scope: {:?}", scope)
-    });
+
+    let parent_scope = match rcx.tcx.region_maps.opt_encl_scope(scope) {
+      Some(parent_scope) => parent_scope,
+      // If no enclosing scope, then it must be the root scope which cannot be outlived.
+      None => return
+    };
 
     let result = iterate_over_potentially_unsafe_regions_in_type(
         &mut DropckContext {
diff --git a/src/test/compile-fail/const-match-pattern-arm.rs b/src/test/compile-fail/const-match-pattern-arm.rs
new file mode 100644
index 00000000000..452aa87d6ba
--- /dev/null
+++ b/src/test/compile-fail/const-match-pattern-arm.rs
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const x: bool = match Some(true) {
+    Some(value) => true,
+    //~^ ERROR: constant contains unimplemented expression type [E0019]
+    _ => false
+};
+
+const y: bool = {
+    match Some(true) {
+        Some(value) => true,
+        //~^ ERROR: constant contains unimplemented expression type [E0019]
+        _ => false
+    }
+};
+
+fn main() {}