From 1dc4e417fa2a73d5ffa24428df6b7d4dbbf41f4a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 18 Jan 2019 11:40:53 +0100 Subject: [PATCH 1/3] Manually inline a function that was only used once --- src/librustc/ty/mod.rs | 10 ---------- src/librustc_mir/interpret/eval_context.rs | 10 +++++----- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 26b4735d926a5..2fdcb2681db0b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2946,16 +2946,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - /// Given the DefId of an item, returns its MIR, borrowed immutably. - /// Returns None if there is no MIR for the DefId - pub fn maybe_optimized_mir(self, did: DefId) -> Option<&'gcx Mir<'gcx>> { - if self.is_mir_available(did) { - Some(self.optimized_mir(did)) - } else { - None - } - } - /// Get the attributes of a definition. pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> { if let Some(id) = self.hir().as_local_node_id(did) { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 19362b6cfdb1c..90f7ba761ea1d 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -265,11 +265,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } trace!("load mir {:?}", instance); match instance { - ty::InstanceDef::Item(def_id) => { - self.tcx.maybe_optimized_mir(def_id).ok_or_else(|| - EvalErrorKind::NoMirFor(self.tcx.item_path_str(def_id)).into() - ) - } + ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) { + Ok(self.tcx.optimized_mir(did)) + } else { + err!(NoMirFor(self.tcx.item_path_str(def_id))) + }, _ => Ok(self.tcx.instance_mir(instance)), } } From efda6816bd29beea2702c7c3f76a252a405e60ae Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 18 Jan 2019 13:31:05 +0100 Subject: [PATCH 2/3] Allow evaluating trivial drop glue in constants --- src/librustc_mir/const_eval.rs | 29 ++++++++++++++++------------- src/test/ui/consts/drop_none.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/consts/drop_none.rs diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index f5f4048167938..f6ecf7c9436a2 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -391,19 +391,22 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> ret: Option, ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> { debug!("eval_fn_call: {:?}", instance); - // Execution might have wandered off into other crates, so we cannot to a stability- - // sensitive check here. But we can at least rule out functions that are not const - // at all. - if !ecx.tcx.is_const_fn_raw(instance.def_id()) { - // Some functions we support even if they are non-const -- but avoid testing - // that for const fn! We certainly do *not* want to actually call the fn - // though, so be sure we return here. - return if ecx.hook_fn(instance, args, dest)? { - ecx.goto_block(ret)?; // fully evaluated and done - Ok(None) - } else { - err!(MachineError(format!("calling non-const function `{}`", instance))) - }; + // Only check non-glue functions + if let ty::InstanceDef::Item(def_id) = instance.def { + // Execution might have wandered off into other crates, so we cannot to a stability- + // sensitive check here. But we can at least rule out functions that are not const + // at all. + if !ecx.tcx.is_const_fn_raw(def_id) { + // Some functions we support even if they are non-const -- but avoid testing + // that for const fn! We certainly do *not* want to actually call the fn + // though, so be sure we return here. + return if ecx.hook_fn(instance, args, dest)? { + ecx.goto_block(ret)?; // fully evaluated and done + Ok(None) + } else { + err!(MachineError(format!("calling non-const function `{}`", instance))) + }; + } } // This is a const fn. Call it. Ok(Some(match ecx.load_mir(instance.def) { diff --git a/src/test/ui/consts/drop_none.rs b/src/test/ui/consts/drop_none.rs new file mode 100644 index 0000000000000..86a197ffb993e --- /dev/null +++ b/src/test/ui/consts/drop_none.rs @@ -0,0 +1,13 @@ +// compile-pass +#![allow(dead_code)] +struct A; +impl Drop for A { + fn drop(&mut self) {} +} + +const FOO: Option = None; + +const BAR: () = (FOO, ()).1; + + +fn main() {} From 506393eaaf912ece2d216de4b6e2fd7ca04a945d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 23 Jan 2019 16:21:33 +0100 Subject: [PATCH 3/3] Add a compile-fail test for `Drop` in constants in the presence of `Option`s --- src/test/ui/static/static-drop-scope.nll.stderr | 14 +++++++++++++- src/test/ui/static/static-drop-scope.rs | 8 ++++++++ src/test/ui/static/static-drop-scope.stderr | 14 +++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/test/ui/static/static-drop-scope.nll.stderr b/src/test/ui/static/static-drop-scope.nll.stderr index 3c01f694bff47..df6383b4fc222 100644 --- a/src/test/ui/static/static-drop-scope.nll.stderr +++ b/src/test/ui/static/static-drop-scope.nll.stderr @@ -54,7 +54,19 @@ error[E0493]: destructors cannot be evaluated at compile-time LL | (x, ()).1 | ^^^^^^^ constant functions cannot evaluate destructors -error: aborting due to 8 previous errors +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:31:34 + | +LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; + | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:36:43 + | +LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; + | ^^^^^^^^^^^ constants cannot evaluate destructors + +error: aborting due to 10 previous errors Some errors occurred: E0493, E0716. For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/static/static-drop-scope.rs b/src/test/ui/static/static-drop-scope.rs index a11a9f020e0dc..e5a9f2a405644 100644 --- a/src/test/ui/static/static-drop-scope.rs +++ b/src/test/ui/static/static-drop-scope.rs @@ -28,4 +28,12 @@ const fn const_drop2(x: T) { //~^ ERROR destructors cannot be evaluated at compile-time } +const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; +//~^ ERROR destructors cannot be evaluated at compile-time + +const HELPER: Option = Some(WithDtor); + +const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; +//~^ ERROR destructors cannot be evaluated at compile-time + fn main () {} diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr index 89b31d95a2a4e..3e3032eb4fb60 100644 --- a/src/test/ui/static/static-drop-scope.stderr +++ b/src/test/ui/static/static-drop-scope.stderr @@ -54,7 +54,19 @@ error[E0493]: destructors cannot be evaluated at compile-time LL | (x, ()).1 | ^^^^^^^ constant functions cannot evaluate destructors -error: aborting due to 8 previous errors +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:31:34 + | +LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; + | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:36:43 + | +LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; + | ^^^^^^^^^^^ constants cannot evaluate destructors + +error: aborting due to 10 previous errors Some errors occurred: E0493, E0597. For more information about an error, try `rustc --explain E0493`.