-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Do not promote values with const drop that need to be dropped #89988
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,8 @@ pub fn in_any_value_of_ty( | |
) -> ConstQualifs { | ||
ConstQualifs { | ||
has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty), | ||
needs_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty), | ||
needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty), | ||
needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty), | ||
custom_eq: CustomEq::in_any_value_of_ty(cx, ty), | ||
error_occured, | ||
} | ||
|
@@ -98,17 +99,39 @@ impl Qualif for HasMutInterior { | |
} | ||
|
||
/// Constant containing an ADT that implements `Drop`. | ||
/// This must be ruled out (a) because we cannot run `Drop` during compile-time | ||
/// as that might not be a `const fn`, and (b) because implicit promotion would | ||
/// remove side-effects that occur as part of dropping that value. | ||
/// This must be ruled out because implicit promotion would remove side-effects | ||
/// that occur as part of dropping that value. N.B., the implicit promotion has | ||
/// to reject const Drop implementations because even if side-effects are ruled | ||
/// out through other means, the execution of the drop could diverge. | ||
pub struct NeedsDrop; | ||
|
||
impl Qualif for NeedsDrop { | ||
const ANALYSIS_NAME: &'static str = "flow_needs_drop"; | ||
const IS_CLEARED_ON_MOVE: bool = true; | ||
|
||
fn in_qualifs(qualifs: &ConstQualifs) -> bool { | ||
qualifs.needs_drop | ||
tmiasko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { | ||
ty.needs_drop(cx.tcx, cx.param_env) | ||
} | ||
|
||
fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { | ||
adt.has_dtor(cx.tcx) | ||
} | ||
} | ||
|
||
/// Constant containing an ADT that implements non-const `Drop`. | ||
/// This must be ruled out because we cannot run `Drop` during compile-time. | ||
pub struct NeedsNonConstDrop; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we have both NeedsDrop and NeedsNonConrstDrop? That seems rather redundant. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We only want to detect nonconst drops in const items, as const drops can actually get executed just fine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So why does check_consts have NeedsDrop then? Promotion is a separate pass after all. |
||
|
||
impl Qualif for NeedsNonConstDrop { | ||
const ANALYSIS_NAME: &'static str = "flow_needs_nonconst_drop"; | ||
const IS_CLEARED_ON_MOVE: bool = true; | ||
|
||
fn in_qualifs(qualifs: &ConstQualifs) -> bool { | ||
qualifs.needs_drop | ||
qualifs.needs_non_const_drop | ||
} | ||
|
||
fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#![feature(const_trait_impl)] | ||
#![feature(const_mut_refs)] | ||
|
||
struct A(); | ||
|
||
impl const Drop for A { | ||
fn drop(&mut self) {} | ||
} | ||
|
||
const C: A = A(); | ||
|
||
fn main() { | ||
let _: &'static A = &A(); //~ ERROR temporary value dropped while borrowed | ||
let _: &'static [A] = &[C]; //~ ERROR temporary value dropped while borrowed | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
error[E0716]: temporary value dropped while borrowed | ||
--> $DIR/promoted-const-drop.rs:13:26 | ||
| | ||
LL | let _: &'static A = &A(); | ||
| ---------- ^^^ creates a temporary which is freed while still in use | ||
| | | ||
| type annotation requires that borrow lasts for `'static` | ||
LL | let _: &'static [A] = &[C]; | ||
LL | } | ||
| - temporary value is freed at the end of this statement | ||
|
||
error[E0716]: temporary value dropped while borrowed | ||
--> $DIR/promoted-const-drop.rs:14:28 | ||
| | ||
LL | let _: &'static [A] = &[C]; | ||
| ------------ ^^^ creates a temporary which is freed while still in use | ||
| | | ||
| type annotation requires that borrow lasts for `'static` | ||
LL | } | ||
| - temporary value is freed at the end of this statement | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0716`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"diverge" means "running into an endless loop", right? Panics seem like a much simpler example to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sentence was intended to encompass panicking. In the context of rustc we generally use diverge to describe a computation that does not return normally, but I can see where you are coming from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see. Yeah I think that is not standard terminology, at least not in my peer group. ;)