Gate const drop behind const_destruct feature, and fix const_precise_live_drops post-drop-elaboration check
This commit is contained in:
parent
b75c1c3dd6
commit
2088260852
28 changed files with 364 additions and 107 deletions
|
|
@ -24,7 +24,7 @@ use rustc_span::{Span, Symbol, sym};
|
|||
use rustc_trait_selection::traits::{
|
||||
Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
|
||||
};
|
||||
use tracing::{debug, instrument, trace};
|
||||
use tracing::{instrument, trace};
|
||||
|
||||
use super::ops::{self, NonConstOp, Status};
|
||||
use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
|
||||
|
|
@ -47,7 +47,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
|
|||
/// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
|
||||
///
|
||||
/// Only updates the cursor if absolutely necessary
|
||||
fn needs_drop(
|
||||
pub(crate) fn needs_drop(
|
||||
&mut self,
|
||||
ccx: &'mir ConstCx<'mir, 'tcx>,
|
||||
local: Local,
|
||||
|
|
@ -324,6 +324,14 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Emits an error at the given `span` if an expression cannot be evaluated in the current
|
||||
/// context. This is meant for use in a post-const-checker pass such as the const precise
|
||||
/// live drops lint.
|
||||
pub fn check_op_spanned_post<O: NonConstOp<'tcx>>(mut self, op: O, span: Span) {
|
||||
self.check_op_spanned(op, span);
|
||||
assert!(self.secondary_errors.is_empty());
|
||||
}
|
||||
|
||||
fn check_static(&mut self, def_id: DefId, span: Span) {
|
||||
if self.tcx.is_thread_local_static(def_id) {
|
||||
self.tcx.dcx().span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
|
||||
|
|
@ -869,12 +877,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
let mut err_span = self.span;
|
||||
let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty;
|
||||
|
||||
let ty_needs_non_const_drop =
|
||||
qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place);
|
||||
|
||||
debug!(?ty_of_dropped_place, ?ty_needs_non_const_drop);
|
||||
|
||||
if !ty_needs_non_const_drop {
|
||||
let needs_drop = if let Some(local) = dropped_place.as_local() {
|
||||
self.qualifs.needs_drop(self.ccx, local, location)
|
||||
} else {
|
||||
qualifs::NeedsDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
|
||||
};
|
||||
// If this type doesn't need a drop at all, then there's nothing to enforce.
|
||||
if !needs_drop {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -883,18 +892,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
err_span = self.body.local_decls[local].source_info.span;
|
||||
self.qualifs.needs_non_const_drop(self.ccx, local, location)
|
||||
} else {
|
||||
true
|
||||
qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
|
||||
};
|
||||
|
||||
if needs_non_const_drop {
|
||||
self.check_op_spanned(
|
||||
ops::LiveDrop {
|
||||
dropped_at: Some(terminator.source_info.span),
|
||||
dropped_ty: ty_of_dropped_place,
|
||||
},
|
||||
err_span,
|
||||
);
|
||||
}
|
||||
self.check_op_spanned(
|
||||
ops::LiveDrop {
|
||||
dropped_at: Some(terminator.source_info.span),
|
||||
dropped_ty: ty_of_dropped_place,
|
||||
needs_non_const_drop,
|
||||
},
|
||||
err_span,
|
||||
);
|
||||
}
|
||||
|
||||
TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
|
||||
|
|
|
|||
|
|
@ -461,15 +461,41 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm {
|
|||
pub(crate) struct LiveDrop<'tcx> {
|
||||
pub dropped_at: Option<Span>,
|
||||
pub dropped_ty: Ty<'tcx>,
|
||||
pub needs_non_const_drop: bool,
|
||||
}
|
||||
impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
|
||||
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
|
||||
if self.needs_non_const_drop {
|
||||
Status::Forbidden
|
||||
} else {
|
||||
Status::Unstable {
|
||||
gate: sym::const_destruct,
|
||||
gate_already_checked: false,
|
||||
safe_to_expose_on_stable: false,
|
||||
is_function_call: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||
ccx.dcx().create_err(errors::LiveDrop {
|
||||
span,
|
||||
dropped_ty: self.dropped_ty,
|
||||
kind: ccx.const_kind(),
|
||||
dropped_at: self.dropped_at,
|
||||
})
|
||||
if self.needs_non_const_drop {
|
||||
ccx.dcx().create_err(errors::LiveDrop {
|
||||
span,
|
||||
dropped_ty: self.dropped_ty,
|
||||
kind: ccx.const_kind(),
|
||||
dropped_at: self.dropped_at,
|
||||
})
|
||||
} else {
|
||||
ccx.tcx.sess.create_feature_err(
|
||||
errors::LiveDrop {
|
||||
span,
|
||||
dropped_ty: self.dropped_ty,
|
||||
kind: ccx.const_kind(),
|
||||
dropped_at: self.dropped_at,
|
||||
},
|
||||
sym::const_destruct,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{self, BasicBlock, Location};
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::symbol::sym;
|
||||
use tracing::trace;
|
||||
|
||||
use super::ConstCx;
|
||||
use super::check::Qualifs;
|
||||
use super::ops::{self, NonConstOp};
|
||||
use super::ops::{self};
|
||||
use super::qualifs::{NeedsNonConstDrop, Qualif};
|
||||
use crate::check_consts::check::Checker;
|
||||
use crate::check_consts::qualifs::NeedsDrop;
|
||||
use crate::check_consts::rustc_allow_const_fn_unstable;
|
||||
|
||||
/// Returns `true` if we should use the more precise live drop checker that runs after drop
|
||||
|
|
@ -64,12 +65,6 @@ impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> CheckLiveDrops<'_, 'tcx> {
|
||||
fn check_live_drop(&self, span: Span, dropped_ty: Ty<'tcx>) {
|
||||
ops::LiveDrop { dropped_at: None, dropped_ty }.build_error(self.ccx, span).emit();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
|
||||
fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &mir::BasicBlockData<'tcx>) {
|
||||
trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);
|
||||
|
|
@ -87,28 +82,39 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
|
|||
|
||||
match &terminator.kind {
|
||||
mir::TerminatorKind::Drop { place: dropped_place, .. } => {
|
||||
let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
|
||||
let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty;
|
||||
|
||||
if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
|
||||
// Instead of throwing a bug, we just return here. This is because we have to
|
||||
// run custom `const Drop` impls.
|
||||
let needs_drop = if let Some(local) = dropped_place.as_local() {
|
||||
self.qualifs.needs_drop(self.ccx, local, location)
|
||||
} else {
|
||||
NeedsDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
|
||||
};
|
||||
// If this type doesn't need a drop at all, then there's nothing to enforce.
|
||||
if !needs_drop {
|
||||
return;
|
||||
}
|
||||
|
||||
if dropped_place.is_indirect() {
|
||||
self.check_live_drop(terminator.source_info.span, dropped_ty);
|
||||
return;
|
||||
}
|
||||
let mut err_span = terminator.source_info.span;
|
||||
|
||||
// Drop elaboration is not precise enough to accept code like
|
||||
// `tests/ui/consts/control-flow/drop-pass.rs`; e.g., when an `Option<Vec<T>>` is
|
||||
// initialized with `None` and never changed, it still emits drop glue.
|
||||
// Hence we additionally check the qualifs here to allow more code to pass.
|
||||
if self.qualifs.needs_non_const_drop(self.ccx, dropped_place.local, location) {
|
||||
// Use the span where the dropped local was declared for the error.
|
||||
let span = self.body.local_decls[dropped_place.local].source_info.span;
|
||||
self.check_live_drop(span, dropped_ty);
|
||||
}
|
||||
let needs_non_const_drop = if let Some(local) = dropped_place.as_local() {
|
||||
// Use the span where the local was declared as the span of the drop error.
|
||||
err_span = self.body.local_decls[local].source_info.span;
|
||||
self.qualifs.needs_non_const_drop(self.ccx, local, location)
|
||||
} else {
|
||||
NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
|
||||
};
|
||||
|
||||
// I know it's not great to be creating a new const checker, but I'd
|
||||
// rather use it so we can deduplicate the error emitting logic that
|
||||
// it contains.
|
||||
Checker::new(self.ccx).check_op_spanned_post(
|
||||
ops::LiveDrop {
|
||||
dropped_at: Some(terminator.source_info.span),
|
||||
dropped_ty: ty_of_dropped_place,
|
||||
needs_non_const_drop,
|
||||
},
|
||||
err_span,
|
||||
);
|
||||
}
|
||||
|
||||
mir::TerminatorKind::UnwindTerminate(_)
|
||||
|
|
|
|||
|
|
@ -62,12 +62,12 @@ pub trait Qualif {
|
|||
/// It also determines the `Qualif`s for primitive types.
|
||||
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool;
|
||||
|
||||
/// Returns `true` if the `Qualif` is structural in an ADT's fields, i.e. that we may
|
||||
/// recurse into an operand if we know what it is.
|
||||
/// Returns `true` if the `Qualif` is structural in an ADT's fields, i.e. if we may
|
||||
/// recurse into an operand *value* to determine whether it has this `Qualif`.
|
||||
///
|
||||
/// If this returns false, `in_any_value_of_ty` will be invoked to determine the
|
||||
/// final qualif for this ADT.
|
||||
fn is_structural_in_adt<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool;
|
||||
fn is_structural_in_adt_value<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool;
|
||||
}
|
||||
|
||||
/// Constant containing interior mutability (`UnsafeCell<T>`).
|
||||
|
|
@ -123,7 +123,7 @@ impl Qualif for HasMutInterior {
|
|||
!errors.is_empty()
|
||||
}
|
||||
|
||||
fn is_structural_in_adt<'tcx>(_cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {
|
||||
fn is_structural_in_adt_value<'tcx>(_cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {
|
||||
// Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
|
||||
// It arises structurally for all other types.
|
||||
!adt.is_unsafe_cell()
|
||||
|
|
@ -140,6 +140,7 @@ pub struct NeedsDrop;
|
|||
impl Qualif for NeedsDrop {
|
||||
const ANALYSIS_NAME: &'static str = "flow_needs_drop";
|
||||
const IS_CLEARED_ON_MOVE: bool = true;
|
||||
const ALLOW_PROMOTED: bool = true;
|
||||
|
||||
fn in_qualifs(qualifs: &ConstQualifs) -> bool {
|
||||
qualifs.needs_drop
|
||||
|
|
@ -149,7 +150,7 @@ impl Qualif for NeedsDrop {
|
|||
ty.needs_drop(cx.tcx, cx.typing_env)
|
||||
}
|
||||
|
||||
fn is_structural_in_adt<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {
|
||||
fn is_structural_in_adt_value<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {
|
||||
!adt.has_dtor(cx.tcx)
|
||||
}
|
||||
}
|
||||
|
|
@ -179,34 +180,30 @@ impl Qualif for NeedsNonConstDrop {
|
|||
// that the components of this type are also `~const Destruct`. This
|
||||
// amounts to verifying that there are no values in this ADT that may have
|
||||
// a non-const drop.
|
||||
if cx.tcx.features().const_trait_impl() {
|
||||
let destruct_def_id = cx.tcx.require_lang_item(LangItem::Destruct, Some(cx.body.span));
|
||||
let infcx =
|
||||
cx.tcx.infer_ctxt().build(TypingMode::from_param_env(cx.typing_env.param_env));
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_obligation(Obligation::new(
|
||||
cx.tcx,
|
||||
ObligationCause::misc(cx.body.span, cx.def_id()),
|
||||
cx.typing_env.param_env,
|
||||
ty::Binder::dummy(ty::TraitRef::new(cx.tcx, destruct_def_id, [ty]))
|
||||
.to_host_effect_clause(cx.tcx, match cx.const_kind() {
|
||||
rustc_hir::ConstContext::ConstFn => ty::BoundConstness::Maybe,
|
||||
rustc_hir::ConstContext::Static(_)
|
||||
| rustc_hir::ConstContext::Const { .. } => ty::BoundConstness::Const,
|
||||
}),
|
||||
));
|
||||
!ocx.select_all_or_error().is_empty()
|
||||
} else {
|
||||
NeedsDrop::in_any_value_of_ty(cx, ty)
|
||||
}
|
||||
let destruct_def_id = cx.tcx.require_lang_item(LangItem::Destruct, Some(cx.body.span));
|
||||
let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_obligation(Obligation::new(
|
||||
cx.tcx,
|
||||
ObligationCause::misc(cx.body.span, cx.def_id()),
|
||||
param_env,
|
||||
ty::Binder::dummy(ty::TraitRef::new(cx.tcx, destruct_def_id, [ty]))
|
||||
.to_host_effect_clause(cx.tcx, match cx.const_kind() {
|
||||
rustc_hir::ConstContext::ConstFn => ty::BoundConstness::Maybe,
|
||||
rustc_hir::ConstContext::Static(_) | rustc_hir::ConstContext::Const { .. } => {
|
||||
ty::BoundConstness::Const
|
||||
}
|
||||
}),
|
||||
));
|
||||
!ocx.select_all_or_error().is_empty()
|
||||
}
|
||||
|
||||
fn is_structural_in_adt<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {
|
||||
fn is_structural_in_adt_value<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {
|
||||
// As soon as an ADT has a destructor, then the drop becomes non-structural
|
||||
// in its value since:
|
||||
// 1. The destructor may have `~const` bounds that need to be satisfied on
|
||||
// top of checking that the components of a specific operand are const-drop.
|
||||
// While this could be instead satisfied by checking that the `~const Drop`
|
||||
// 1. The destructor may have `~const` bounds which are not present on the type.
|
||||
// Someone needs to check that those are satisfied.
|
||||
// While this could be done instead satisfied by checking that the `~const Drop`
|
||||
// impl holds (i.e. replicating part of the `in_any_value_of_ty` logic above),
|
||||
// even in this case, we have another problem, which is,
|
||||
// 2. The destructor may *modify* the operand being dropped, so even if we
|
||||
|
|
@ -271,7 +268,7 @@ where
|
|||
// then we cannot recurse on its fields. Instead,
|
||||
// we fall back to checking the qualif for *any* value
|
||||
// of the ADT.
|
||||
if def.is_union() || !Q::is_structural_in_adt(cx, def) {
|
||||
if def.is_union() || !Q::is_structural_in_adt_value(cx, def) {
|
||||
return Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -426,6 +426,8 @@ declare_features! (
|
|||
(unstable, const_async_blocks, "1.53.0", Some(85368)),
|
||||
/// Allows `const || {}` closures in const contexts.
|
||||
(incomplete, const_closures, "1.68.0", Some(106003)),
|
||||
/// Uwu
|
||||
(unstable, const_destruct, "CURRENT_RUSTC_VERSION", Some(133214)),
|
||||
/// Allows `for _ in _` loops in const contexts.
|
||||
(unstable, const_for, "1.56.0", Some(87575)),
|
||||
/// Be more precise when looking for live drops in a const context.
|
||||
|
|
|
|||
|
|
@ -610,6 +610,7 @@ symbols! {
|
|||
const_compare_raw_pointers,
|
||||
const_constructor,
|
||||
const_deallocate,
|
||||
const_destruct,
|
||||
const_eval_limit,
|
||||
const_eval_select,
|
||||
const_evaluatable_checked,
|
||||
|
|
|
|||
|
|
@ -953,7 +953,7 @@ marker_impls! {
|
|||
///
|
||||
/// This should be used for `~const` bounds,
|
||||
/// as non-const bounds will always hold for every type.
|
||||
#[unstable(feature = "const_trait_impl", issue = "67792")]
|
||||
#[unstable(feature = "const_destruct", issue = "10")]
|
||||
#[lang = "destruct"]
|
||||
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
|
||||
#[rustc_deny_explicit_impl(implement_via_object = false)]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,23 @@
|
|||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/const-block-const-bound.rs:6:5
|
||||
|
|
||||
LL | use std::marker::Destruct;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/const-block-const-bound.rs:8:22
|
||||
|
|
||||
LL | const fn f<T: ~const Destruct>(x: T) {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-block-const-bound.rs:8:15
|
||||
|
|
||||
|
|
@ -20,6 +40,7 @@ LL | const fn f<T: ~const Destruct>(x: T) {}
|
|||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0493`.
|
||||
Some errors have detailed explanations: E0493, E0658.
|
||||
For more information about an error, try `rustc --explain E0493`.
|
||||
|
|
|
|||
|
|
@ -1,14 +1,20 @@
|
|||
error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
|
||||
--> $DIR/drop-fail.rs:8:9
|
||||
--> $DIR/drop-fail.rs:9:9
|
||||
|
|
||||
LL | let x = Some(Vec::new());
|
||||
| ^ the destructor for this type cannot be evaluated in constants
|
||||
...
|
||||
LL | };
|
||||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
|
||||
--> $DIR/drop-fail.rs:39:9
|
||||
--> $DIR/drop-fail.rs:40:9
|
||||
|
|
||||
LL | let mut tmp = None;
|
||||
| ^^^^^^^ the destructor for this type cannot be evaluated in constants
|
||||
...
|
||||
LL | };
|
||||
| - value is dropped here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//@ revisions: stock precise
|
||||
|
||||
#![feature(const_destruct)]
|
||||
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
||||
|
||||
// `x` is *not* always moved into the final value and may be dropped inside the initializer.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
|
||||
--> $DIR/drop-fail.rs:8:9
|
||||
--> $DIR/drop-fail.rs:9:9
|
||||
|
|
||||
LL | let x = Some(Vec::new());
|
||||
| ^ the destructor for this type cannot be evaluated in constants
|
||||
|
|
@ -8,7 +8,7 @@ LL | };
|
|||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `(Vec<i32>,)` cannot be evaluated at compile-time
|
||||
--> $DIR/drop-fail.rs:21:9
|
||||
--> $DIR/drop-fail.rs:22:9
|
||||
|
|
||||
LL | let vec_tuple = (Vec::new(),);
|
||||
| ^^^^^^^^^ the destructor for this type cannot be evaluated in constants
|
||||
|
|
@ -17,7 +17,7 @@ LL | };
|
|||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Result<Vec<i32>, Vec<i32>>` cannot be evaluated at compile-time
|
||||
--> $DIR/drop-fail.rs:29:9
|
||||
--> $DIR/drop-fail.rs:30:9
|
||||
|
|
||||
LL | let x: Result<_, Vec<i32>> = Ok(Vec::new());
|
||||
| ^ the destructor for this type cannot be evaluated in constants
|
||||
|
|
@ -26,7 +26,7 @@ LL | };
|
|||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
|
||||
--> $DIR/drop-fail.rs:39:9
|
||||
--> $DIR/drop-fail.rs:40:9
|
||||
|
|
||||
LL | let mut tmp = None;
|
||||
| ^^^^^^^ the destructor for this type cannot be evaluated in constants
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ error[E0493]: destructor of `S` cannot be evaluated at compile-time
|
|||
|
|
||||
LL | let s = S;
|
||||
| ^ the destructor for this type cannot be evaluated in constant functions
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,53 @@
|
|||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/fn_trait_refs.rs:9:5
|
||||
|
|
||||
LL | use std::marker::Destruct;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/fn_trait_refs.rs:13:31
|
||||
|
|
||||
LL | T: ~const Fn<()> + ~const Destruct,
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/fn_trait_refs.rs:20:34
|
||||
|
|
||||
LL | T: ~const FnMut<()> + ~const Destruct,
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/fn_trait_refs.rs:34:31
|
||||
|
|
||||
LL | T: ~const Fn<()> + ~const Destruct,
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/fn_trait_refs.rs:48:34
|
||||
|
|
||||
LL | T: ~const FnMut<()> + ~const Destruct,
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0635]: unknown feature `const_fn_trait_ref_impls`
|
||||
--> $DIR/fn_trait_refs.rs:3:12
|
||||
|
|
||||
|
|
@ -264,7 +314,7 @@ LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
|
|||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error: aborting due to 34 previous errors
|
||||
error: aborting due to 39 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0015, E0493, E0635.
|
||||
Some errors have detailed explanations: E0015, E0493, E0635, E0658.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ error[E0493]: destructor of `String` cannot be evaluated at compile-time
|
|||
--> $DIR/promoted_const_call2.rs:4:30
|
||||
|
|
||||
LL | let _: &'static _ = &id(&String::new());
|
||||
| ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants
|
||||
| ^^^^^^^^^^^^^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constants
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promoted_const_call2.rs:11:26
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
|
|||
|
|
||||
LL | let mut x = None;
|
||||
| ^^^^^ the destructor for this type cannot be evaluated in constants
|
||||
...
|
||||
LL | };
|
||||
| - value is dropped here
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
|
@ -26,6 +29,8 @@ error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
|
|||
|
|
||||
LL | let _z = x;
|
||||
| ^^ the destructor for this type cannot be evaluated in constants
|
||||
LL | };
|
||||
| - value is dropped here
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
|
@ -49,42 +54,62 @@ error[E0493]: destructor of `(u32, Option<String>)` cannot be evaluated at compi
|
|||
|
|
||||
LL | let mut a: (u32, Option<String>) = (0, None);
|
||||
| ^^^^^ the destructor for this type cannot be evaluated in constant functions
|
||||
LL | let _ = &mut a.1;
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Option<T>` cannot be evaluated at compile-time
|
||||
--> $DIR/qualif-indirect-mutation-fail.rs:34:9
|
||||
|
|
||||
LL | let x: Option<T> = None;
|
||||
| ^ the destructor for this type cannot be evaluated in constant functions
|
||||
LL | let _ = x.is_some();
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Option<T>` cannot be evaluated at compile-time
|
||||
--> $DIR/qualif-indirect-mutation-fail.rs:42:9
|
||||
|
|
||||
LL | let _y = x;
|
||||
| ^^ the destructor for this type cannot be evaluated in constant functions
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
|
||||
--> $DIR/qualif-indirect-mutation-fail.rs:50:9
|
||||
|
|
||||
LL | let mut y: Option<String> = None;
|
||||
| ^^^^^ the destructor for this type cannot be evaluated in constant functions
|
||||
LL | std::ptr::addr_of_mut!(y);
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
|
||||
--> $DIR/qualif-indirect-mutation-fail.rs:47:9
|
||||
|
|
||||
LL | let mut x: Option<String> = None;
|
||||
| ^^^^^ the destructor for this type cannot be evaluated in constant functions
|
||||
...
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
|
||||
--> $DIR/qualif-indirect-mutation-fail.rs:60:9
|
||||
|
|
||||
LL | let y: Option<String> = None;
|
||||
| ^ the destructor for this type cannot be evaluated in constant functions
|
||||
LL | std::ptr::addr_of!(y);
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
|
||||
--> $DIR/qualif-indirect-mutation-fail.rs:57:9
|
||||
|
|
||||
LL | let x: Option<String> = None;
|
||||
| ^ the destructor for this type cannot be evaluated in constant functions
|
||||
...
|
||||
LL | }
|
||||
| - value is dropped here
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//@ known-bug: #103507
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_impl, const_destruct)]
|
||||
|
||||
use std::marker::Destruct;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,43 @@
|
|||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/const-drop-bound.rs:7:5
|
||||
|
|
||||
LL | use std::marker::Destruct;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/const-drop-bound.rs:9:68
|
||||
|
|
||||
LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/const-drop-bound.rs:20:15
|
||||
|
|
||||
LL | T: ~const Destruct,
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/const-drop-bound.rs:21:15
|
||||
|
|
||||
LL | E: ~const Destruct,
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-drop-bound.rs:9:61
|
||||
|
|
||||
|
|
@ -44,8 +84,11 @@ error[E0493]: destructor of `E` cannot be evaluated at compile-time
|
|||
--> $DIR/const-drop-bound.rs:12:13
|
||||
|
|
||||
LL | Err(_e) => None,
|
||||
| ^^ the destructor for this type cannot be evaluated in constant functions
|
||||
| ^^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0493`.
|
||||
Some errors have detailed explanations: E0493, E0658.
|
||||
For more information about an error, try `rustc --explain E0493`.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,23 @@
|
|||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/const-drop-fail-2.rs:5:19
|
||||
|
|
||||
LL | use std::marker::{Destruct, PhantomData};
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `const_destruct`
|
||||
--> $DIR/const-drop-fail-2.rs:20:26
|
||||
|
|
||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #10 <https://github.com/rust-lang/rust/issues/10> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
|
||||
--> $DIR/const-drop-fail-2.rs:39:25
|
||||
|
|
||||
|
|
@ -35,7 +55,7 @@ LL | const fn check<T: ~const Destruct>(_: T) {}
|
|||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0493.
|
||||
Some errors have detailed explanations: E0277, E0493, E0658.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ error[E0493]: destructor of `T` cannot be evaluated at compile-time
|
|||
--> $DIR/const-drop-fail.rs:23:36
|
||||
|
|
||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||
| ^ the destructor for this type cannot be evaluated in constant functions
|
||||
| ^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//@ known-bug: #110395
|
||||
|
||||
//@ revisions: stock precise
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_impl, const_destruct)]
|
||||
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
||||
|
||||
use std::marker::{Destruct, PhantomData};
|
||||
|
|
|
|||
|
|
@ -76,13 +76,17 @@ error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time
|
|||
--> $DIR/const-drop.rs:23:13
|
||||
|
|
||||
LL | let _ = S(&mut c);
|
||||
| ^^^^^^^^^ the destructor for this type cannot be evaluated in constant functions
|
||||
| ^^^^^^^^^- value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error[E0493]: destructor of `T` cannot be evaluated at compile-time
|
||||
--> $DIR/const-drop.rs:18:32
|
||||
|
|
||||
LL | const fn a<T: ~const Destruct>(_: T) {}
|
||||
| ^ the destructor for this type cannot be evaluated in constant functions
|
||||
| ^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied
|
||||
--> $DIR/const-drop.rs:69:13
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// FIXME run-pass
|
||||
//@ known-bug: #110395
|
||||
//@ revisions: stock precise
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_impl, const_destruct)]
|
||||
#![feature(never_type)]
|
||||
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
rustc_attrs,
|
||||
fundamental,
|
||||
marker_trait_attr,
|
||||
const_trait_impl
|
||||
const_trait_impl,
|
||||
const_destruct,
|
||||
)]
|
||||
#![allow(internal_features, incomplete_features)]
|
||||
#![no_std]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//@ aux-build:minicore.rs
|
||||
//@ compile-flags: --crate-type=lib -Znext-solver
|
||||
|
||||
#![feature(no_core, const_trait_impl)]
|
||||
#![feature(no_core, const_trait_impl, const_destruct)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
error[E0493]: destructor of `ConstDrop` cannot be evaluated at compile-time
|
||||
--> $DIR/minicore-drop-without-feature-gate.rs:23:13
|
||||
|
|
||||
LL | let _ = ConstDrop;
|
||||
| ^^^^^^^^^- value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
|
||||
= note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
|
||||
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0493`.
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//@ aux-build:minicore.rs
|
||||
//@ compile-flags: --crate-type=lib -Znext-solver
|
||||
//@ revisions: yes no
|
||||
//@[yes] check-pass
|
||||
|
||||
#![feature(no_core, const_trait_impl)]
|
||||
#![cfg_attr(yes, feature(const_destruct))]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
struct ConstDrop;
|
||||
impl const Drop for ConstDrop {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
// Make sure that `ConstDrop` can only be dropped when the `const_drop`
|
||||
// feature gate is enabled. Otherwise, we should error if there is a drop
|
||||
// impl at all.
|
||||
const fn test() {
|
||||
let _ = ConstDrop;
|
||||
//[no]~^ ERROR destructor of `ConstDrop` cannot be evaluated at compile-time
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
//@ known-bug: #110395
|
||||
// FIXME check-pass
|
||||
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_impl, const_destruct)]
|
||||
|
||||
use std::marker::Destruct;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_impl, const_destruct)]
|
||||
|
||||
fn foo(_: impl std::marker::Destruct) {}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue