about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-22 14:33:08 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-30 09:43:41 +0100
commit4d2bed946016b17e888d605b5e2a0849aa23f0b2 (patch)
tree8926fe4b029a4db676243ced6bf7a7c656923a95
parent3e90a12a8a95933604a8b609197fce61bb24a38c (diff)
downloadrust-4d2bed946016b17e888d605b5e2a0849aa23f0b2.tar.gz
rust-4d2bed946016b17e888d605b5e2a0849aa23f0b2.zip
Stabilize `const_let` inside const functions
-rw-r--r--src/librustc/mir/mod.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs52
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs19
-rw-r--r--src/test/ui/consts/const-fn-destructuring-arg.rs14
-rw-r--r--src/test/ui/consts/const-fn-destructuring-arg.stderr35
-rw-r--r--src/test/ui/consts/const-fn-not-safe-for-const.rs6
-rw-r--r--src/test/ui/consts/const-fn-not-safe-for-const.stderr52
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr8
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.rs2
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_let.rs12
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_let.stderr34
12 files changed, 56 insertions, 188 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 368f83eb611..2607f5fd08b 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1748,6 +1748,8 @@ pub enum StatementKind<'tcx> {
     /// (e.g. inspecting constants and discriminant values), and the
     /// kind of pattern it comes from. This is in order to adapt potential
     /// error messages to these specific patterns.
+    ///
+    /// Note that this also is emitted for regular `let` bindings to aid destructuring diagnostics
     FakeRead(FakeReadCause, Place<'tcx>),
 
     /// Write the discriminant for a variant to the enum Place.
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 09fe7b14c79..61e79990f92 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -243,7 +243,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
             return;
         }
 
-        if self.tcx.features().const_let {
+        if self.const_let_allowed() {
             let mut dest = dest;
             let index = loop {
                 match dest {
@@ -320,6 +320,10 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
         }
     }
 
+    fn const_let_allowed(&self) -> bool {
+        self.tcx.features().const_let || self.mode == Mode::ConstFn
+    }
+
     /// Qualify a whole const, static initializer or const fn.
     fn qualify_const(&mut self) -> (Qualif, Lrc<BitSet<Local>>) {
         debug!("qualifying {} {:?}", self.mode, self.def_id);
@@ -357,7 +361,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
                 TerminatorKind::FalseUnwind { .. } => None,
 
                 TerminatorKind::Return => {
-                    if !self.tcx.features().const_let {
+                    if !self.const_let_allowed() {
                         // Check for unused values. This usually means
                         // there are extra statements in the AST.
                         for temp in mir.temps_iter() {
@@ -464,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             LocalKind::ReturnPointer => {
                 self.not_const();
             }
-            LocalKind::Var if !self.tcx.features().const_let => {
+            LocalKind::Var if !self.const_let_allowed() => {
                 if self.mode != Mode::Fn {
                     emit_feature_err(&self.tcx.sess.parse_sess, "const_let",
                                     self.span, GateIssue::Language,
@@ -1154,48 +1158,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
         debug!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location);
         self.visit_rvalue(rvalue, location);
 
-        // Check the allowed const fn argument forms.
-        if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) {
-            if self.mir.local_kind(index) == LocalKind::Var &&
-               self.const_fn_arg_vars.insert(index) &&
-               !self.tcx.features().const_let {
-
-                // Direct use of an argument is permitted.
-                match *rvalue {
-                    Rvalue::Use(Operand::Copy(Place::Local(local))) |
-                    Rvalue::Use(Operand::Move(Place::Local(local))) => {
-                        if self.mir.local_kind(local) == LocalKind::Arg {
-                            return;
-                        }
-                    }
-                    _ => {}
-                }
-
-                // Avoid a generic error for other uses of arguments.
-                if self.qualif.contains(Qualif::FN_ARGUMENT) {
-                    let decl = &self.mir.local_decls[index];
-                    let mut err = feature_err(
-                        &self.tcx.sess.parse_sess,
-                        "const_let",
-                        decl.source_info.span,
-                        GateIssue::Language,
-                        "arguments of constant functions can only be immutable by-value bindings"
-                    );
-                    if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                        err.note("Constant functions are not allowed to mutate anything. Thus, \
-                                  binding to an argument with a mutable pattern is not allowed.");
-                        err.note("Remove any mutable bindings from the argument list to fix this \
-                                  error. In case you need to mutate the argument, try lazily \
-                                  initializing a global variable instead of using a const fn, or \
-                                  refactoring the code to a functional style to avoid mutation if \
-                                  possible.");
-                    }
-                    err.emit();
-                    return;
-                }
-            }
-        }
-
         self.assign(dest, location);
     }
 
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 13e134ba859..5729775e15d 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -64,12 +64,6 @@ pub fn is_min_const_fn(
         }
     }
 
-    for local in mir.vars_iter() {
-        return Err((
-            mir.local_decls[local].source_info.span,
-            "local variables in const fn are unstable".into(),
-        ));
-    }
     for local in &mir.local_decls {
         check_ty(tcx, local.ty, local.source_info.span)?;
     }
@@ -229,7 +223,7 @@ fn check_statement(
             check_rvalue(tcx, mir, rval, span)
         }
 
-        StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())),
+        StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span, PlaceMode::Read),
 
         // just an assignment
         StatementKind::SetDiscriminant { .. } => Ok(()),
@@ -270,15 +264,8 @@ fn check_place(
     mode: PlaceMode,
 ) -> McfResult {
     match place {
-        Place::Local(l) => match mode {
-            PlaceMode::Assign => match mir.local_kind(*l) {
-                LocalKind::Temp | LocalKind::ReturnPointer => Ok(()),
-                LocalKind::Arg | LocalKind::Var => {
-                    Err((span, "assignments in const fn are unstable".into()))
-                }
-            },
-            PlaceMode::Read => Ok(()),
-        },
+        // assignments to locals, arguments, temporaries or the return slot are fine
+        Place::Local(_) => Ok(()),
         // promoteds are always fine, they are essentially constants
         Place::Promoted(_) => Ok(()),
         Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
diff --git a/src/test/ui/consts/const-fn-destructuring-arg.rs b/src/test/ui/consts/const-fn-destructuring-arg.rs
index fce1688716d..8aa6871fa75 100644
--- a/src/test/ui/consts/const-fn-destructuring-arg.rs
+++ b/src/test/ui/consts/const-fn-destructuring-arg.rs
@@ -8,20 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// test that certain things are disallowed in constant functions
+// compile-pass
 
-#![feature(const_fn)]
-
-// no destructuring
-const fn i((
-            a,
-            //~^ ERROR arguments of constant functions can only be immutable by-value bindings
-            b
-            //~^ ERROR arguments of constant functions can only be immutable by-value bindings
-           ): (u32, u32)) -> u32 {
+const fn i((a, b): (u32, u32)) -> u32 {
     a + b
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR let bindings in constant functions are unstable
 }
 
 fn main() {}
diff --git a/src/test/ui/consts/const-fn-destructuring-arg.stderr b/src/test/ui/consts/const-fn-destructuring-arg.stderr
deleted file mode 100644
index 029d63a7720..00000000000
--- a/src/test/ui/consts/const-fn-destructuring-arg.stderr
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0658]: arguments of constant functions can only be immutable by-value bindings (see issue #48821)
-  --> $DIR/const-fn-destructuring-arg.rs:17:13
-   |
-LL |             a,
-   |             ^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: arguments of constant functions can only be immutable by-value bindings (see issue #48821)
-  --> $DIR/const-fn-destructuring-arg.rs:19:13
-   |
-LL |             b
-   |             ^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-destructuring-arg.rs:22:5
-   |
-LL |     a + b
-   |     ^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-destructuring-arg.rs:22:9
-   |
-LL |     a + b
-   |         ^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.rs b/src/test/ui/consts/const-fn-not-safe-for-const.rs
index 30a738a83a3..aee5539980c 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.rs
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.rs
@@ -38,14 +38,8 @@ const fn get_Y_addr() -> &'static u32 {
 
 const fn get() -> u32 {
     let x = 22;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
     let y = 44;
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR statements in constant functions are unstable
     x + y
-    //~^ ERROR let bindings in constant functions are unstable
-    //~| ERROR let bindings in constant functions are unstable
 }
 
 fn main() {}
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
index 613670acc93..90a7314b7d1 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
@@ -16,55 +16,7 @@ error[E0013]: constant functions cannot refer to statics, use a constant instead
 LL |     &Y
    |     ^^
 
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:40:13
-   |
-LL |     let x = 22;
-   |             ^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:40:13
-   |
-LL |     let x = 22;
-   |             ^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:43:13
-   |
-LL |     let y = 44;
-   |             ^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:43:13
-   |
-LL |     let y = 44;
-   |             ^^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:46:5
-   |
-LL |     x + y
-   |     ^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
-  --> $DIR/const-fn-not-safe-for-const.rs:46:9
-   |
-LL |     x + y
-   |         ^
-   |
-   = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 9 previous errors
+error: aborting due to 3 previous errors
 
-Some errors occurred: E0013, E0015, E0658.
+Some errors occurred: E0013, E0015.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
index f43befb37c1..39adf088642 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -112,12 +112,6 @@ error: `if`, `match`, `&&` and `||` are not stable in const fn
 LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
    |                             ^^^^^^^^^^^
 
-error: local variables in const fn are unstable
-  --> $DIR/min_const_fn.rs:109:34
-   |
-LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
-   |                                  ^
-
 error: `if`, `match`, `&&` and `||` are not stable in const fn
   --> $DIR/min_const_fn.rs:110:44
    |
@@ -221,7 +215,7 @@ error: function pointers in const fn are unstable
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
 
-error: aborting due to 35 previous errors
+error: aborting due to 34 previous errors
 
 Some errors occurred: E0493, E0515.
 For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
index 0dba3a7de53..80db24006ec 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs
@@ -106,7 +106,7 @@ const fn foo30_2(x: *mut u32) -> usize { x as usize }
 const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
-const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+const fn foo30_6() -> bool { let x = true; x }
 const fn foo36(a: bool, b: bool) -> bool { a && b }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo37(a: bool, b: bool) -> bool { a || b }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index bcb9be6e548..530282cfea9 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -112,12 +112,6 @@ error: `if`, `match`, `&&` and `||` are not stable in const fn
 LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
    |                             ^^^^^^^^^^^
 
-error: local variables in const fn are unstable
-  --> $DIR/min_const_fn.rs:109:34
-   |
-LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
-   |                                  ^
-
 error: `if`, `match`, `&&` and `||` are not stable in const fn
   --> $DIR/min_const_fn.rs:110:44
    |
@@ -208,6 +202,6 @@ error: function pointers in const fn are unstable
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
 
-error: aborting due to 35 previous errors
+error: aborting due to 34 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/feature-gates/feature-gate-const_let.rs b/src/test/ui/feature-gates/feature-gate-const_let.rs
index 05d02e62bc8..aad251a205e 100644
--- a/src/test/ui/feature-gates/feature-gate-const_let.rs
+++ b/src/test/ui/feature-gates/feature-gate-const_let.rs
@@ -10,13 +10,13 @@
 
 // Test use of const let without feature gate.
 
-#![feature(const_fn)]
-
-const fn foo() -> usize {
+const FOO: usize = {
+    //~^ ERROR statements in constants are unstable
+    //~| ERROR: let bindings in constants are unstable
     let x = 42;
-    //~^ ERROR statements in constant functions are unstable
-    //~| ERROR: let bindings in constant functions are unstable
+    //~^ ERROR statements in constants are unstable
+    //~| ERROR: let bindings in constants are unstable
     42
-}
+};
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_let.stderr b/src/test/ui/feature-gates/feature-gate-const_let.stderr
index 6a7f6255678..4fab6ec540e 100644
--- a/src/test/ui/feature-gates/feature-gate-const_let.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_let.stderr
@@ -1,4 +1,4 @@
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+error[E0658]: let bindings in constants are unstable (see issue #48821)
   --> $DIR/feature-gate-const_let.rs:16:13
    |
 LL |     let x = 42;
@@ -6,7 +6,7 @@ LL |     let x = 42;
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
-error[E0658]: statements in constant functions are unstable (see issue #48821)
+error[E0658]: statements in constants are unstable (see issue #48821)
   --> $DIR/feature-gate-const_let.rs:16:13
    |
 LL |     let x = 42;
@@ -14,6 +14,34 @@ LL |     let x = 42;
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:13:1
+   |
+LL | / const FOO: usize = {
+LL | |     //~^ ERROR statements in constants are unstable
+LL | |     //~| ERROR: let bindings in constants are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/feature-gate-const_let.rs:13:1
+   |
+LL | / const FOO: usize = {
+LL | |     //~^ ERROR statements in constants are unstable
+LL | |     //~| ERROR: let bindings in constants are unstable
+LL | |     let x = 42;
+...  |
+LL | |     42
+LL | | };
+   | |__^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0658`.