about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-03-11 01:28:16 +0000
committerbors <bors@rust-lang.org>2019-03-11 01:28:16 +0000
commitc2ddf5a1dd54ebe18ffb794e096c28a4ed8e1d16 (patch)
treea660ad702e541881d16e20426197ce2ef8a69680
parent9d71ec1358ac063fe6ff1eaed0ba6ed3cedde610 (diff)
parent8c16507045a76ef616533ec29626f6ce6be40a6c (diff)
downloadrust-c2ddf5a1dd54ebe18ffb794e096c28a4ed8e1d16.tar.gz
rust-c2ddf5a1dd54ebe18ffb794e096c28a4ed8e1d16.zip
Auto merge of #58784 - oli-obk:accidental_promotion, r=eddyb
Don't promote function calls to nonpromotable things

fixes https://github.com/rust-lang/rust/issues/58767 and fixes https://github.com/rust-lang/rust/issues/58634

r? @eddyb

should we additionally check the function call return type? It might be a promotable function (or any `const fn` inside a `const fn`), but its return type might contain interior mutability.
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs9
-rw-r--r--src/test/ui/consts/invalid_promotion.rs18
2 files changed, 22 insertions, 5 deletions
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 20e5c0a23bc..97d566e586e 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -499,6 +499,8 @@ impl Qualif for IsNotConst {
 
 // Refers to temporaries which cannot be promoted as
 // promote_consts decided they weren't simple enough.
+// FIXME(oli-obk,eddyb): Remove this flag entirely and
+// solely process this information via `IsNotConst`.
 struct IsNotPromotable;
 
 impl Qualif for IsNotPromotable {
@@ -507,7 +509,7 @@ impl Qualif for IsNotPromotable {
     fn in_call(
         cx: &ConstCx<'_, 'tcx>,
         callee: &Operand<'tcx>,
-        _args: &[Operand<'tcx>],
+        args: &[Operand<'tcx>],
         _return_ty: Ty<'tcx>,
     ) -> bool {
         if cx.mode == Mode::Fn {
@@ -520,10 +522,7 @@ impl Qualif for IsNotPromotable {
             }
         }
 
-        // FIXME(eddyb) do we need "not promotable" in anything
-        // other than `Mode::Fn` by any chance?
-
-        false
+        Self::in_operand(cx, callee) || args.iter().any(|arg| Self::in_operand(cx, arg))
     }
 }
 
diff --git a/src/test/ui/consts/invalid_promotion.rs b/src/test/ui/consts/invalid_promotion.rs
new file mode 100644
index 00000000000..f98406e50e9
--- /dev/null
+++ b/src/test/ui/consts/invalid_promotion.rs
@@ -0,0 +1,18 @@
+// compile-pass
+// note this was only reproducible with lib crates
+// compile-flags: --crate-type=lib
+
+pub struct Hz;
+
+impl Hz {
+    pub const fn num(&self) -> u32 {
+        42
+    }
+    pub const fn normalized(&self) -> Hz {
+        Hz
+    }
+
+    pub const fn as_u32(&self) -> u32 {
+        self.normalized().num() // this used to promote the `self.normalized()`
+    }
+}