未验证 提交 68d5fdde 编写于 作者: K kennytm 提交者: GitHub

Rollup merge of #54816 - oli-obk:double_promotion, r=alexreg

Don't try to promote already promoted out temporaries

fixes #53201

r? @EddyB
......@@ -333,6 +333,14 @@ fn interior_base<'a, 'tcx>(place: &'a mut Place<'tcx>)
let operand = Operand::Copy(promoted_place(ty, span));
mem::replace(&mut args[index], operand)
}
// We expected a `TerminatorKind::Call` for which we'd like to promote an
// argument. `qualify_consts` saw a `TerminatorKind::Call` here, but
// we are seeing a `Goto`. That means that the `promote_temps` method
// already promoted this call away entirely. This case occurs when calling
// a function requiring a constant argument and as that constant value
// providing a value whose computation contains another call to a function
// requiring a constant argument.
TerminatorKind::Goto { .. } => return,
_ => bug!()
}
}
......
......@@ -820,7 +820,9 @@ fn visit_terminator_kind(&mut self,
let fn_ty = func.ty(self.mir, self.tcx);
let mut callee_def_id = None;
let (mut is_shuffle, mut is_const_fn) = (false, false);
let mut is_shuffle = false;
let mut is_const_fn = false;
let mut is_promotable_const_fn = false;
if let ty::FnDef(def_id, _) = fn_ty.sty {
callee_def_id = Some(def_id);
match self.tcx.fn_sig(def_id).abi() {
......@@ -881,6 +883,9 @@ fn visit_terminator_kind(&mut self,
// functions without #[rustc_promotable]
if self.tcx.is_promotable_const_fn(def_id) {
is_const_fn = true;
is_promotable_const_fn = true;
} else if self.tcx.is_const_fn(def_id) {
is_const_fn = true;
}
} else {
// stable const fn or unstable const fns with their feature gate
......@@ -982,7 +987,17 @@ fn visit_terminator_kind(&mut self,
if !constant_arguments.contains(&i) {
return
}
if this.qualif.is_empty() {
// Since the argument is required to be constant,
// we care about constness, not promotability.
// If we checked for promotability, we'd miss out on
// the results of function calls (which are never promoted
// in runtime code)
// This is not a problem, because the argument explicitly
// requests constness, in contrast to regular promotion
// which happens even without the user requesting it.
// We can error out with a hard error if the argument is not
// constant here.
if (this.qualif - Qualif::NOT_PROMOTABLE).is_empty() {
this.promotion_candidates.push(candidate);
} else {
this.tcx.sess.span_err(this.span,
......@@ -1011,7 +1026,11 @@ fn visit_terminator_kind(&mut self,
// Be conservative about the returned value of a const fn.
let tcx = self.tcx;
let ty = dest.ty(self.mir, tcx).to_ty(tcx);
self.qualif = Qualif::empty();
if is_const_fn && !is_promotable_const_fn && self.mode == Mode::Fn {
self.qualif = Qualif::NOT_PROMOTABLE;
} else {
self.qualif = Qualif::empty();
}
self.add_type(ty);
}
self.assign(dest, location);
......
// compile-pass
#![feature(const_fn, rustc_attrs)]
#[rustc_args_required_const(0)]
pub const fn a(value: u8) -> u8 {
value
}
#[rustc_args_required_const(0)]
pub fn b(_: u8) {
unimplemented!()
}
fn main() {
let _ = b(a(0));
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册