From 59408add4d67e7e04fa1dcf378e4e1cc71c6ff48 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 29 Oct 2024 20:08:55 +0000 Subject: [PATCH 1/5] Implement ~const Destruct in new solver --- .../src/check_consts/qualifs.rs | 81 ++++++++++--------- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 6 +- compiler/rustc_middle/src/ty/adt.rs | 12 ++- compiler/rustc_middle/src/ty/context.rs | 5 ++ .../src/solve/assembly/structural_traits.rs | 74 ++++++++++++++++- .../src/solve/effect_goals.rs | 27 ++++++- compiler/rustc_type_ir/src/inherent.rs | 4 +- compiler/rustc_type_ir/src/interner.rs | 1 + compiler/rustc_type_ir/src/lang_items.rs | 1 + compiler/rustc_type_ir/src/solve/mod.rs | 7 ++ tests/ui/consts/promoted_const_call.stderr | 25 ++---- .../const-traits/const-drop.precise.stderr | 8 +- .../const-traits/const-drop.stock.stderr | 10 ++- .../effects/auxiliary/minicore.rs | 6 +- .../effects/minicore-drop-fail.rs | 37 +++++++++ .../effects/minicore-drop-fail.stderr | 36 +++++++++ 16 files changed, 266 insertions(+), 74 deletions(-) create mode 100644 tests/ui/traits/const-traits/effects/minicore-drop-fail.rs create mode 100644 tests/ui/traits/const-traits/effects/minicore-drop-fail.stderr diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index bc416acc58d7b..b965ad7bd8715 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -2,11 +2,14 @@ //! //! See the `Qualif` trait for more info. +// FIXME(const_trait_impl): This API should be really reworked. It's dangerously general for +// having basically only two use-cases that act in different ways. + use rustc_errors::ErrorGuaranteed; use rustc_hir::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::*; -use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty}; +use rustc_middle::ty::{self, AdtDef, Ty}; use rustc_middle::{bug, mir}; use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; use tracing::instrument; @@ -59,19 +62,9 @@ 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 this `Qualif` is inherent to the given struct or enum. - /// - /// By default, `Qualif`s propagate into ADTs in a structural way: An ADT only becomes - /// qualified if part of it is assigned a value with that `Qualif`. However, some ADTs *always* - /// have a certain `Qualif`, regardless of whether their fields have it. For example, a type - /// with a custom `Drop` impl is inherently `NeedsDrop`. - /// - /// Returning `true` for `in_adt_inherently` but `false` for `in_any_value_of_ty` is unsound. - fn in_adt_inherently<'tcx>( - cx: &ConstCx<'_, 'tcx>, - adt: AdtDef<'tcx>, - args: GenericArgsRef<'tcx>, - ) -> bool; + /// Returns `true` if the `Qualif` is not structural, i.e. that we should not recurse + /// into the operand. + fn is_non_structural<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool; /// Returns `true` if this `Qualif` behaves sructurally for pointers and references: /// the pointer/reference qualifies if and only if the pointee qualifies. @@ -101,6 +94,11 @@ impl Qualif for HasMutInterior { return false; } + // Avoid selecting for `UnsafeCell` either. + if ty.ty_adt_def().is_some_and(|adt| adt.is_unsafe_cell()) { + return true; + } + // We do not use `ty.is_freeze` here, because that requires revealing opaque types, which // requires borrowck, which in turn will invoke mir_const_qualifs again, causing a cycle error. // Instead we invoke an obligation context manually, and provide the opaque type inference settings @@ -129,11 +127,7 @@ impl Qualif for HasMutInterior { !errors.is_empty() } - fn in_adt_inherently<'tcx>( - _cx: &ConstCx<'_, 'tcx>, - adt: AdtDef<'tcx>, - _: GenericArgsRef<'tcx>, - ) -> bool { + fn is_non_structural<'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() @@ -144,6 +138,7 @@ impl Qualif for HasMutInterior { } } +// FIXME(const_trait_impl): Get rid of this! /// Constant containing an ADT that implements `Drop`. /// 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 @@ -163,11 +158,7 @@ impl Qualif for NeedsDrop { ty.needs_drop(cx.tcx, cx.typing_env) } - fn in_adt_inherently<'tcx>( - cx: &ConstCx<'_, 'tcx>, - adt: AdtDef<'tcx>, - _: GenericArgsRef<'tcx>, - ) -> bool { + fn is_non_structural<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool { adt.has_dtor(cx.tcx) } @@ -196,16 +187,32 @@ impl Qualif for NeedsNonConstDrop { return false; } - // FIXME(const_trait_impl): Reimplement const drop checking. - NeedsDrop::in_any_value_of_ty(cx, ty) + 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.param_env)); + let ocx = ObligationCtxt::new(&infcx); + ocx.register_obligation(Obligation::new( + cx.tcx, + ObligationCause::misc(cx.body.span, cx.def_id()), + cx.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) + } } - fn in_adt_inherently<'tcx>( - cx: &ConstCx<'_, 'tcx>, - adt: AdtDef<'tcx>, - _: GenericArgsRef<'tcx>, - ) -> bool { - adt.has_non_const_dtor(cx.tcx) + fn is_non_structural<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool { + // Even a `const` dtor may have `~const` bounds that may need to + // be satisfied, so this becomes non-structural as soon as the + // ADT gets a destructor at all. + adt.has_dtor(cx.tcx) } fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { @@ -261,14 +268,10 @@ where Rvalue::Aggregate(kind, operands) => { // Return early if we know that the struct or enum being constructed is always // qualified. - if let AggregateKind::Adt(adt_did, _, args, ..) = **kind { + if let AggregateKind::Adt(adt_did, ..) = **kind { let def = cx.tcx.adt_def(adt_did); - if Q::in_adt_inherently(cx, def, args) { - return true; - } - // Don't do any value-based reasoning for unions. - if def.is_union() && Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)) { - return true; + if def.is_union() || Q::is_non_structural(cx, def) { + return Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index ce6ce0381a91b..47af8c681da00 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -269,13 +269,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } Adjust::Deref(None) => { - // FIXME(effects): We *could* enforce `&T: ~const Deref` here. + // FIXME(const_trait_impl): We *could* enforce `&T: ~const Deref` here. } Adjust::Pointer(_pointer_coercion) => { - // FIXME(effects): We should probably enforce these. + // FIXME(const_trait_impl): We should probably enforce these. } Adjust::ReborrowPin(_mutability) => { - // FIXME(effects): We could enforce these; they correspond to + // FIXME(const_trait_impl): We could enforce these; they correspond to // `&mut T: DerefMut` tho, so it's kinda moot. } Adjust::Borrow(_) => { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 79d56702be256..447cbc8932ee5 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -18,6 +18,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_query_system::ich::StableHashingContext; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; +use rustc_type_ir::solve::AdtDestructorKind; use tracing::{debug, info, trace}; use super::{ @@ -232,6 +233,13 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { fn is_fundamental(self) -> bool { self.is_fundamental() } + + fn destructor(self, tcx: TyCtxt<'tcx>) -> Option { + Some(match self.destructor(tcx)?.constness { + hir::Constness::Const => AdtDestructorKind::Const, + hir::Constness::NotConst => AdtDestructorKind::NotConst, + }) + } } #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)] @@ -402,10 +410,6 @@ impl<'tcx> AdtDef<'tcx> { self.destructor(tcx).is_some() } - pub fn has_non_const_dtor(self, tcx: TyCtxt<'tcx>) -> bool { - matches!(self.destructor(tcx), Some(Destructor { constness: hir::Constness::NotConst, .. })) - } - /// Asserts this is a struct or union and returns its unique variant. pub fn non_enum_variant(self) -> &'tcx VariantDef { assert!(self.is_struct() || self.is_union()); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 55c29825fbcb7..4a0d50c153c8a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -384,6 +384,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_conditionally_const(def_id) } + fn alias_has_const_conditions(self, def_id: DefId) -> bool { + self.is_conditionally_const(def_id) + } + fn const_conditions( self, def_id: DefId, @@ -663,6 +667,7 @@ bidirectional_lang_item_map! { CoroutineYield, Destruct, DiscriminantKind, + Drop, DynMetadata, Fn, FnMut, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index a56febec48c45..05ce61bc0678f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -12,7 +12,7 @@ use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::instrument; use crate::delegate::SolverDelegate; -use crate::solve::{EvalCtxt, Goal, NoSolution}; +use crate::solve::{AdtDestructorKind, EvalCtxt, Goal, NoSolution}; // Calculates the constituent types of a type for `auto trait` purposes. #[instrument(level = "trace", skip(ecx), ret)] @@ -703,6 +703,78 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable( } } +pub(in crate::solve) fn const_conditions_for_destruct( + cx: I, + self_ty: I::Ty, +) -> Result>, NoSolution> { + let destruct_def_id = cx.require_lang_item(TraitSolverLangItem::Destruct); + + match self_ty.kind() { + // An ADT is `~const Destruct` only if all of the fields are, + // *and* if there is a `Drop` impl, that `Drop` impl is also `~const`. + ty::Adt(adt_def, args) => { + let mut const_conditions: Vec<_> = adt_def + .all_field_tys(cx) + .iter_instantiated(cx, args) + .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty])) + .collect(); + match adt_def.destructor(cx) { + // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`. + Some(AdtDestructorKind::NotConst) => return Err(NoSolution), + // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold. + Some(AdtDestructorKind::Const) => { + let drop_def_id = cx.require_lang_item(TraitSolverLangItem::Drop); + let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]); + const_conditions.push(drop_trait_ref); + } + // No `Drop` impl, no need to require anything else. + None => {} + } + Ok(const_conditions) + } + + ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => { + Ok(vec![ty::TraitRef::new(cx, destruct_def_id, [ty])]) + } + + ty::Tuple(tys) => Ok(tys + .iter() + .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty])) + .collect()), + + // Trivially implement `~const Destruct` + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Str + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Never + | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_)) + | ty::Error(_) => Ok(vec![]), + + // Coroutines and closures could implement `~const Drop`, + // but they don't really need to right now. + ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(_, _) => Err(NoSolution), + + ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => { + Err(NoSolution) + } + + ty::Bound(..) + | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + panic!("unexpected type `{self_ty:?}`") + } + } +} + /// Assemble a list of predicates that would be present on a theoretical /// user impl for an object type. These predicates must be checked any time /// we assemble a built-in object candidate for an object type, since they diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 603a68eb890cb..81b5199002b23 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -84,6 +84,10 @@ where let cx = ecx.cx(); let mut candidates = vec![]; + if !ecx.cx().alias_has_const_conditions(alias_ty.def_id) { + return vec![]; + } + for clause in elaborate::elaborate( cx, cx.explicit_implied_const_bounds(alias_ty.def_id) @@ -338,10 +342,27 @@ where } fn consider_builtin_destruct_candidate( - _ecx: &mut EvalCtxt<'_, D>, - _goal: Goal, + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, ) -> Result, NoSolution> { - Err(NoSolution) + let cx = ecx.cx(); + + let self_ty = goal.predicate.self_ty(); + let const_conditions = structural_traits::const_conditions_for_destruct(cx, self_ty)?; + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.add_goals( + GoalSource::Misc, + const_conditions.into_iter().map(|trait_ref| { + goal.with( + cx, + ty::Binder::dummy(trait_ref) + .to_host_effect_clause(cx, goal.predicate.constness), + ) + }), + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_builtin_transmute_candidate( diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 5af1aa2f8faa9..f7e0570bdd555 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -11,7 +11,7 @@ use rustc_ast_ir::Mutability; use crate::elaborate::Elaboratable; use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::relate::Relate; -use crate::solve::Reveal; +use crate::solve::{AdtDestructorKind, Reveal}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{self as ty, CollectAndApply, Interner, UpcastFrom}; @@ -537,6 +537,8 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { fn sized_constraint(self, interner: I) -> Option>; fn is_fundamental(self) -> bool; + + fn destructor(self, interner: I) -> Option; } pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 93b9c2e289249..0ae688848ebfc 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -225,6 +225,7 @@ pub trait Interner: fn impl_is_const(self, def_id: Self::DefId) -> bool; fn fn_is_const(self, def_id: Self::DefId) -> bool; + fn alias_has_const_conditions(self, def_id: Self::DefId) -> bool; fn const_conditions( self, def_id: Self::DefId, diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs index df43346065d40..eeb80bc3ab420 100644 --- a/compiler/rustc_type_ir/src/lang_items.rs +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -19,6 +19,7 @@ pub enum TraitSolverLangItem { CoroutineYield, Destruct, DiscriminantKind, + Drop, DynMetadata, Fn, FnMut, diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index fe4558730513a..13081f3154be9 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -326,3 +326,10 @@ impl MaybeCause { } } } + +/// Indicates that a `impl Drop for Adt` is `const` or not. +#[derive(Debug)] +pub enum AdtDestructorKind { + NotConst, + Const, +} diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr index bcb9dfb704b1d..7a96b6e770582 100644 --- a/tests/ui/consts/promoted_const_call.stderr +++ b/tests/ui/consts/promoted_const_call.stderr @@ -7,25 +7,13 @@ LL | impl const Drop for Panic { fn drop(&mut self) { panic!(); } } = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:10:26 - | -LL | let _: &'static _ = &id(&Panic); - | ---------- ^^^^^^^^^^ creates a temporary value 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[E0716]: temporary value dropped while borrowed +error[E0493]: destructor of `Panic` cannot be evaluated at compile-time --> $DIR/promoted_const_call.rs:10:30 | LL | let _: &'static _ = &id(&Panic); - | ---------- ^^^^^ - temporary value is freed at the end of this statement - | | | - | | creates a temporary value which is freed while still in use - | type annotation requires that borrow lasts for `'static` + | ^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call.rs:16:26 @@ -69,6 +57,7 @@ LL | let _: &'static _ = &&(Panic, 0).1; LL | } | - temporary value is freed at the end of this statement -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0716`. +Some errors have detailed explanations: E0493, E0716. +For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/const-drop.precise.stderr b/tests/ui/traits/const-traits/const-drop.precise.stderr index ed90b234761ad..4f673187d499f 100644 --- a/tests/ui/traits/const-traits/const-drop.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop.precise.stderr @@ -72,6 +72,12 @@ note: required by a bound in `t::ConstDropWithBound` LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); | ^^^^^ required by this bound in `ConstDropWithBound` +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 + error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/const-drop.rs:18:32 | @@ -84,7 +90,7 @@ error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied LL | T::foo(); | ^^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors Some errors have detailed explanations: E0277, E0493. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-drop.stock.stderr b/tests/ui/traits/const-traits/const-drop.stock.stderr index 2b46b048e9095..51a66396c4b42 100644 --- a/tests/ui/traits/const-traits/const-drop.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop.stock.stderr @@ -72,6 +72,14 @@ note: required by a bound in `t::ConstDropWithBound` LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); | ^^^^^ required by this bound in `ConstDropWithBound` +error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time + --> $DIR/const-drop.rs:23:13 + | +LL | let _ = S(&mut c); + | ^^^^^^^^^- 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 | @@ -86,7 +94,7 @@ error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied LL | T::foo(); | ^^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors Some errors have detailed explanations: E0277, E0493. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs index 209a111c24366..498e698ef1c1f 100644 --- a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs +++ b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs @@ -444,12 +444,12 @@ impl Deref for Ref<'_, T> { #[lang = "clone"] #[rustc_trivial_field_reads] -// FIXME: #[const_trait] +#[const_trait] pub trait Clone: Sized { fn clone(&self) -> Self; fn clone_from(&mut self, source: &Self) where - // FIXME: Self: ~const Destruct, + Self: ~const Destruct, { *self = source.clone() } @@ -458,7 +458,7 @@ pub trait Clone: Sized { #[lang = "structural_peq"] pub trait StructuralPartialEq {} -// FIXME: const fn drop(_: T) {} +pub const fn drop(_: T) {} #[rustc_intrinsic_must_be_overridden] #[rustc_intrinsic] diff --git a/tests/ui/traits/const-traits/effects/minicore-drop-fail.rs b/tests/ui/traits/const-traits/effects/minicore-drop-fail.rs new file mode 100644 index 0000000000000..57c39d2c1a157 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore-drop-fail.rs @@ -0,0 +1,37 @@ +//@ aux-build:minicore.rs +//@ compile-flags: --crate-type=lib -Znext-solver + +#![feature(no_core, const_trait_impl)] +#![no_std] +#![no_core] + +extern crate minicore; +use minicore::*; + +struct Contains(T); + +struct NotDropImpl; +impl Drop for NotDropImpl { + fn drop(&mut self) {} +} + +#[const_trait] trait Foo {} +impl Foo for () {} + +struct Conditional(T); +impl const Drop for Conditional where T: ~const Foo { + fn drop(&mut self) {} +} + +const fn test() { + let _ = NotDropImpl; + //~^ ERROR destructor of `NotDropImpl` cannot be evaluated at compile-time + let _ = Contains(NotDropImpl); + //~^ ERROR destructor of `Contains` cannot be evaluated at compile-time + let _ = Conditional(()); + //~^ ERROR destructor of `Conditional<()>` cannot be evaluated at compile-time +} + +const fn drop_arbitrary(_: T) { + //~^ ERROR destructor of `T` cannot be evaluated at compile-time +} diff --git a/tests/ui/traits/const-traits/effects/minicore-drop-fail.stderr b/tests/ui/traits/const-traits/effects/minicore-drop-fail.stderr new file mode 100644 index 0000000000000..12d1877a18aba --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore-drop-fail.stderr @@ -0,0 +1,36 @@ +error[E0493]: destructor of `NotDropImpl` cannot be evaluated at compile-time + --> $DIR/minicore-drop-fail.rs:27:13 + | +LL | let _ = NotDropImpl; + | ^^^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `Contains` cannot be evaluated at compile-time + --> $DIR/minicore-drop-fail.rs:29:13 + | +LL | let _ = Contains(NotDropImpl); + | ^^^^^^^^^^^^^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `Conditional<()>` cannot be evaluated at compile-time + --> $DIR/minicore-drop-fail.rs:31:13 + | +LL | let _ = Conditional(()); + | ^^^^^^^^^^^^^^^- 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/minicore-drop-fail.rs:35:28 + | +LL | const fn drop_arbitrary(_: T) { + | ^ the destructor for this type cannot be evaluated in constant functions +LL | +LL | } + | - value is dropped here + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0493`. From b75c1c3dd64d6846d670adca10ebd3735b48dc6a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 12 Nov 2024 17:44:31 +0000 Subject: [PATCH 2/5] More comments, reverse polarity of structural check --- .../src/check_consts/qualifs.rs | 76 ++++++++++--------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index b965ad7bd8715..df19ff2c16a76 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -62,16 +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 not structural, i.e. that we should not recurse - /// into the operand. - fn is_non_structural<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool; - - /// Returns `true` if this `Qualif` behaves sructurally for pointers and references: - /// the pointer/reference qualifies if and only if the pointee qualifies. + /// 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. /// - /// (This is currently `false` for all our instances, but that may change in the future. Also, - /// by keeping it abstract, the handling of `Deref` in `in_place` becomes more clear.) - fn deref_structural<'tcx>(cx: &ConstCx<'_, 'tcx>) -> bool; + /// 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; } /// Constant containing interior mutability (`UnsafeCell`). @@ -127,18 +123,13 @@ impl Qualif for HasMutInterior { !errors.is_empty() } - fn is_non_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool { + fn is_structural_in_adt<'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() - } - - fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { - false + !adt.is_unsafe_cell() } } -// FIXME(const_trait_impl): Get rid of this! /// Constant containing an ADT that implements `Drop`. /// 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 @@ -158,12 +149,8 @@ impl Qualif for NeedsDrop { ty.needs_drop(cx.tcx, cx.typing_env) } - fn is_non_structural<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool { - adt.has_dtor(cx.tcx) - } - - fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { - false + fn is_structural_in_adt<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool { + !adt.has_dtor(cx.tcx) } } @@ -187,14 +174,20 @@ impl Qualif for NeedsNonConstDrop { return false; } + // We check that the type is `~const Destruct` since that will verify that + // the type is both `~const Drop` (if a drop impl exists for the adt), *and* + // 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.param_env)); + 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.param_env, + 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, @@ -208,15 +201,18 @@ impl Qualif for NeedsNonConstDrop { } } - fn is_non_structural<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool { - // Even a `const` dtor may have `~const` bounds that may need to - // be satisfied, so this becomes non-structural as soon as the - // ADT gets a destructor at all. - adt.has_dtor(cx.tcx) - } - - fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { - false + fn is_structural_in_adt<'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` + // 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 + // did recurse on the components of the operand, we may not be even dropping + // the same values that were present before the custom destructor was invoked. + !adt.has_dtor(cx.tcx) } } @@ -270,7 +266,12 @@ where // qualified. if let AggregateKind::Adt(adt_did, ..) = **kind { let def = cx.tcx.adt_def(adt_did); - if def.is_union() || Q::is_non_structural(cx, def) { + // Don't do any value-based reasoning for unions. + // Also, if the ADT is not structural in its fields, + // 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) { return Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)); } } @@ -308,7 +309,12 @@ where return false; } - if matches!(elem, ProjectionElem::Deref) && !Q::deref_structural(cx) { + // This is currently unconditionally true for all qualifs, since we do + // not recurse into the pointer of a deref projection, but that may change + // in the future. If that changes, each qualif should be required to + // specify whether it operates structurally for deref projections, just like + // we do for `Qualif::is_structural_in_adt`. + if matches!(elem, ProjectionElem::Deref) { // We have to assume that this qualifies. return true; } From 20882608529a969bd878ad787cf0038716c021df Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 19 Nov 2024 17:08:52 +0000 Subject: [PATCH 3/5] Gate const drop behind const_destruct feature, and fix const_precise_live_drops post-drop-elaboration check --- .../src/check_consts/check.rs | 44 +++++++------ .../rustc_const_eval/src/check_consts/ops.rs | 38 ++++++++++-- .../src/check_consts/post_drop_elaboration.rs | 62 ++++++++++--------- .../src/check_consts/qualifs.rs | 57 ++++++++--------- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/marker.rs | 2 +- .../ui/consts/const-block-const-bound.stderr | 25 +++++++- .../control-flow/drop-fail.precise.stderr | 10 ++- tests/ui/consts/control-flow/drop-fail.rs | 1 + .../control-flow/drop-fail.stock.stderr | 8 +-- tests/ui/consts/drop_zst.stderr | 2 + tests/ui/consts/fn_trait_refs.stderr | 54 +++++++++++++++- tests/ui/consts/promoted_const_call2.stderr | 4 +- .../qualif-indirect-mutation-fail.stderr | 25 ++++++++ .../ui/impl-trait/normalize-tait-in-const.rs | 2 +- .../const-traits/const-drop-bound.stderr | 49 ++++++++++++++- .../const-traits/const-drop-fail-2.stderr | 24 ++++++- .../const-drop-fail.precise.stderr | 4 +- .../ui/traits/const-traits/const-drop-fail.rs | 2 +- .../const-traits/const-drop.precise.stderr | 8 ++- tests/ui/traits/const-traits/const-drop.rs | 2 +- .../effects/auxiliary/minicore.rs | 3 +- .../effects/minicore-drop-fail.rs | 2 +- ...nicore-drop-without-feature-gate.no.stderr | 15 +++++ .../minicore-drop-without-feature-gate.rs | 25 ++++++++ tests/ui/traits/const-traits/issue-92111.rs | 2 +- tests/ui/traits/next-solver/destruct.rs | 2 +- 28 files changed, 366 insertions(+), 109 deletions(-) create mode 100644 tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.no.stderr create mode 100644 tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.rs diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 1129b5caec54e..a088a210e2640 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -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>(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), diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 8ba6b89aad4d5..c8d6358161fca 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -461,15 +461,41 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm { pub(crate) struct LiveDrop<'tcx> { pub dropped_at: Option, 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, + ) + } } } diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index f6eb130fbd385..c3a9aad642129 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -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; - - 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 ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty; + + 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; - } - - // Drop elaboration is not precise enough to accept code like - // `tests/ui/consts/control-flow/drop-pass.rs`; e.g., when an `Option>` 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 mut err_span = terminator.source_info.span; + + 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(_) diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index df19ff2c16a76..29fd3aa7d4de2 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -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`). @@ -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)); } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e3dc73c14014f..b9a75fedcbefd 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -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. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a2d9859645ff6..c7c29abc3cbbe 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -610,6 +610,7 @@ symbols! { const_compare_raw_pointers, const_constructor, const_deallocate, + const_destruct, const_eval_limit, const_eval_select, const_evaluatable_checked, diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index c8ea52a1fb0b4..bd1a8a02dbf47 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -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)] diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index 5e24959146b83..3b8f6b6359123 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -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 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(x: T) {} + | ^^^^^^^^ + | + = note: see issue #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(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`. diff --git a/tests/ui/consts/control-flow/drop-fail.precise.stderr b/tests/ui/consts/control-flow/drop-fail.precise.stderr index 93b5f257efb77..32afc51c3ee34 100644 --- a/tests/ui/consts/control-flow/drop-fail.precise.stderr +++ b/tests/ui/consts/control-flow/drop-fail.precise.stderr @@ -1,14 +1,20 @@ error[E0493]: destructor of `Option>` 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>` 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 diff --git a/tests/ui/consts/control-flow/drop-fail.rs b/tests/ui/consts/control-flow/drop-fail.rs index 25afe5d08d970..2b73e37b23d03 100644 --- a/tests/ui/consts/control-flow/drop-fail.rs +++ b/tests/ui/consts/control-flow/drop-fail.rs @@ -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. diff --git a/tests/ui/consts/control-flow/drop-fail.stock.stderr b/tests/ui/consts/control-flow/drop-fail.stock.stderr index 2cc8568026eb5..8fe60fd736765 100644 --- a/tests/ui/consts/control-flow/drop-fail.stock.stderr +++ b/tests/ui/consts/control-flow/drop-fail.stock.stderr @@ -1,5 +1,5 @@ error[E0493]: destructor of `Option>` 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,)` 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>` cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:29:9 + --> $DIR/drop-fail.rs:30:9 | LL | let x: Result<_, Vec> = 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>` 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 diff --git a/tests/ui/consts/drop_zst.stderr b/tests/ui/consts/drop_zst.stderr index e3c6785290d76..4d1af7ef93540 100644 --- a/tests/ui/consts/drop_zst.stderr +++ b/tests/ui/consts/drop_zst.stderr @@ -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 diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index a686bc23c0f41..15d3ae98c7e2b 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -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 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 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 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 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 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(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`. diff --git a/tests/ui/consts/promoted_const_call2.stderr b/tests/ui/consts/promoted_const_call2.stderr index 177f7aed17df2..bdb43385d2032 100644 --- a/tests/ui/consts/promoted_const_call2.stderr +++ b/tests/ui/consts/promoted_const_call2.stderr @@ -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 diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.stderr b/tests/ui/consts/qualif-indirect-mutation-fail.stderr index 433dfba2257d0..f706b7cf699d0 100644 --- a/tests/ui/consts/qualif-indirect-mutation-fail.stderr +++ b/tests/ui/consts/qualif-indirect-mutation-fail.stderr @@ -3,6 +3,9 @@ error[E0493]: destructor of `Option` 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` 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)` cannot be evaluated at compi | LL | let mut a: (u32, Option) = (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` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:34:9 | LL | let x: Option = 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` 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` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:50:9 | LL | let mut y: Option = 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` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:47:9 | LL | let mut x: Option = None; | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:60:9 | LL | let y: Option = 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` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:57:9 | LL | let x: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here error: aborting due to 11 previous errors diff --git a/tests/ui/impl-trait/normalize-tait-in-const.rs b/tests/ui/impl-trait/normalize-tait-in-const.rs index 134b202d65582..1fd543b72e7cc 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.rs +++ b/tests/ui/impl-trait/normalize-tait-in-const.rs @@ -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; diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr index 3f71864543337..530b23975ad00 100644 --- a/tests/ui/traits/const-traits/const-drop-bound.stderr +++ b/tests/ui/traits/const-traits/const-drop-bound.stderr @@ -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 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(res: Result) -> Option where E: ~const Destruct { + | ^^^^^^^^ + | + = note: see issue #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 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 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`. diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stderr index fde106599c236..83c72efb7eb4d 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stderr @@ -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 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) {} + | ^^^^^^^^ + | + = note: see issue #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) {} | | | 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`. diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr index 859fdfae81aef..91ca60b750d81 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr @@ -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) {} - | ^ 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 diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs index 5a98c32e83887..c61afc0e17a3b 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.rs +++ b/tests/ui/traits/const-traits/const-drop-fail.rs @@ -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}; diff --git a/tests/ui/traits/const-traits/const-drop.precise.stderr b/tests/ui/traits/const-traits/const-drop.precise.stderr index 4f673187d499f..51a66396c4b42 100644 --- a/tests/ui/traits/const-traits/const-drop.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop.precise.stderr @@ -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) {} - | ^ 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 diff --git a/tests/ui/traits/const-traits/const-drop.rs b/tests/ui/traits/const-traits/const-drop.rs index 5bd81fb3ab631..8bf1dd68b5c0a 100644 --- a/tests/ui/traits/const-traits/const-drop.rs +++ b/tests/ui/traits/const-traits/const-drop.rs @@ -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))] diff --git a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs index 498e698ef1c1f..660fb43259408 100644 --- a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs +++ b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs @@ -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] diff --git a/tests/ui/traits/const-traits/effects/minicore-drop-fail.rs b/tests/ui/traits/const-traits/effects/minicore-drop-fail.rs index 57c39d2c1a157..274e5db21c4f6 100644 --- a/tests/ui/traits/const-traits/effects/minicore-drop-fail.rs +++ b/tests/ui/traits/const-traits/effects/minicore-drop-fail.rs @@ -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] diff --git a/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.no.stderr b/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.no.stderr new file mode 100644 index 0000000000000..a6dcc38816a12 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.no.stderr @@ -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 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`. diff --git a/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.rs b/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.rs new file mode 100644 index 0000000000000..06014ad1291aa --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.rs @@ -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 +} diff --git a/tests/ui/traits/const-traits/issue-92111.rs b/tests/ui/traits/const-traits/issue-92111.rs index 64fa32156c39a..64bf0f20e91d6 100644 --- a/tests/ui/traits/const-traits/issue-92111.rs +++ b/tests/ui/traits/const-traits/issue-92111.rs @@ -3,7 +3,7 @@ //@ known-bug: #110395 // FIXME check-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_destruct)] use std::marker::Destruct; diff --git a/tests/ui/traits/next-solver/destruct.rs b/tests/ui/traits/next-solver/destruct.rs index f595cb30db846..fd14132124c4b 100644 --- a/tests/ui/traits/next-solver/destruct.rs +++ b/tests/ui/traits/next-solver/destruct.rs @@ -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) {} From af0d566e76a709caa2a89123202f583cbcc877e2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 19 Nov 2024 17:18:54 +0000 Subject: [PATCH 4/5] Deduplicate checking drop terminator --- .../src/check_consts/check.rs | 75 ++++++++++--------- .../rustc_const_eval/src/check_consts/ops.rs | 2 +- .../src/check_consts/post_drop_elaboration.rs | 57 +++----------- .../src/check_consts/qualifs.rs | 9 +-- compiler/rustc_const_eval/src/errors.rs | 2 +- library/core/src/marker.rs | 2 +- .../ui/consts/const-block-const-bound.stderr | 4 +- tests/ui/consts/fn_trait_refs.stderr | 10 +-- .../const-traits/const-drop-bound.stderr | 8 +- .../const-traits/const-drop-fail-2.stderr | 4 +- ...nicore-drop-without-feature-gate.no.stderr | 2 +- .../minicore-drop-without-feature-gate.rs | 1 + 12 files changed, 69 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index a088a210e2640..9f21c8644876f 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -324,14 +324,6 @@ 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>(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`"); @@ -429,6 +421,43 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { true } + + pub fn check_drop_terminator( + &mut self, + dropped_place: Place<'tcx>, + location: Location, + terminator_span: Span, + ) { + let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty; + + 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; + } + + let mut err_span = self.span; + 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 { + qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place) + }; + + self.check_op_spanned( + ops::LiveDrop { + dropped_at: terminator_span, + dropped_ty: ty_of_dropped_place, + needs_non_const_drop, + }, + err_span, + ); + } } impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { @@ -874,35 +903,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { return; } - let mut err_span = self.span; - let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty; - - 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; - } - - 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 { - qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place) - }; - - 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, - ); + self.check_drop_terminator(*dropped_place, location, terminator.source_info.span); } TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm), diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index c8d6358161fca..ab81e60a33f23 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -459,7 +459,7 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm { #[derive(Debug)] pub(crate) struct LiveDrop<'tcx> { - pub dropped_at: Option, + pub dropped_at: Span, pub dropped_ty: Ty<'tcx>, pub needs_non_const_drop: bool, } diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index c3a9aad642129..951e19b470bab 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -5,11 +5,7 @@ use rustc_span::symbol::sym; use tracing::trace; use super::ConstCx; -use super::check::Qualifs; -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 @@ -46,23 +42,16 @@ pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { return; } - let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() }; + // 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. + let mut visitor = CheckLiveDrops { checker: Checker::new(&ccx) }; visitor.visit_body(body); } struct CheckLiveDrops<'mir, 'tcx> { - ccx: &'mir ConstCx<'mir, 'tcx>, - qualifs: Qualifs<'mir, 'tcx>, -} - -// So we can access `body` and `tcx`. -impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { - type Target = ConstCx<'mir, 'tcx>; - - fn deref(&self) -> &Self::Target { - self.ccx - } + checker: Checker<'mir, 'tcx>, } impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { @@ -82,38 +71,10 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { match &terminator.kind { mir::TerminatorKind::Drop { place: dropped_place, .. } => { - let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty; - - 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; - } - - let mut err_span = terminator.source_info.span; - - 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, + self.checker.check_drop_terminator( + *dropped_place, + location, + terminator.source_info.span, ); } diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 29fd3aa7d4de2..accce883e39dd 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -306,11 +306,10 @@ where return false; } - // This is currently unconditionally true for all qualifs, since we do - // not recurse into the pointer of a deref projection, but that may change - // in the future. If that changes, each qualif should be required to - // specify whether it operates structurally for deref projections, just like - // we do for `Qualif::is_structural_in_adt`. + // `Deref` currently unconditionally "qualifies" if `in_any_value_of_ty` returns true, + // i.e., we treat all qualifs as non-structural for deref projections. Generally, + // we can say very little about `*ptr` even if we know that `ptr` satisfies all + // sorts of properties. if matches!(elem, ProjectionElem::Deref) { // We have to assume that this qualifies. return true; diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 604e5ed61a35b..80236ee05b7ff 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -411,7 +411,7 @@ pub struct LiveDrop<'tcx> { pub kind: ConstContext, pub dropped_ty: Ty<'tcx>, #[label(const_eval_dropped_at_label)] - pub dropped_at: Option, + pub dropped_at: Span, } #[derive(Diagnostic)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index bd1a8a02dbf47..acbad07746bb9 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -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_destruct", issue = "10")] +#[unstable(feature = "const_destruct", issue = "133214")] #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[rustc_deny_explicit_impl(implement_via_object = false)] diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index 3b8f6b6359123..9dd6a96686f36 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -4,7 +4,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | use std::marker::Destruct; | ^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -14,7 +14,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | const fn f(x: T) {} | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 15d3ae98c7e2b..c84e604793621 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -4,7 +4,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | use std::marker::Destruct; | ^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -14,7 +14,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -24,7 +24,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -34,7 +34,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -44,7 +44,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr index 530b23975ad00..9abfa630e4def 100644 --- a/tests/ui/traits/const-traits/const-drop-bound.stderr +++ b/tests/ui/traits/const-traits/const-drop-bound.stderr @@ -4,7 +4,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | use std::marker::Destruct; | ^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -14,7 +14,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | const fn foo(res: Result) -> Option where E: ~const Destruct { | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -24,7 +24,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | T: ~const Destruct, | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -34,7 +34,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | E: ~const Destruct, | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stderr index 83c72efb7eb4d..d871f4d425d5d 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stderr @@ -4,7 +4,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | use std::marker::{Destruct, PhantomData}; | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 @@ -14,7 +14,7 @@ error[E0658]: use of unstable library feature `const_destruct` LL | const fn check(_: T) {} | ^^^^^^^^ | - = note: see issue #10 for more information + = note: see issue #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 diff --git a/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.no.stderr b/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.no.stderr index a6dcc38816a12..218f3661e39d4 100644 --- a/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.no.stderr +++ b/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.no.stderr @@ -1,5 +1,5 @@ error[E0493]: destructor of `ConstDrop` cannot be evaluated at compile-time - --> $DIR/minicore-drop-without-feature-gate.rs:23:13 + --> $DIR/minicore-drop-without-feature-gate.rs:24:13 | LL | let _ = ConstDrop; | ^^^^^^^^^- value is dropped here diff --git a/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.rs b/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.rs index 06014ad1291aa..e75bf3db007f0 100644 --- a/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.rs +++ b/tests/ui/traits/const-traits/effects/minicore-drop-without-feature-gate.rs @@ -2,6 +2,7 @@ //@ compile-flags: --crate-type=lib -Znext-solver //@ revisions: yes no //@[yes] check-pass +// gate-test-const_destruct #![feature(no_core, const_trait_impl)] #![cfg_attr(yes, feature(const_destruct))] From 69a38de97755780a5d78c655da2c953ba58ae18f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Nov 2024 23:20:59 +0000 Subject: [PATCH 5/5] Check drop is trivial before checking ty needs drop --- .../src/check_consts/qualifs.rs | 7 +- compiler/rustc_feature/src/unstable.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 5 +- tests/ui/consts/const-block-const-bound.rs | 2 +- .../ui/consts/const-block-const-bound.stderr | 25 +--- tests/ui/consts/fn_trait_refs.rs | 1 + tests/ui/consts/fn_trait_refs.stderr | 118 +++++------------- .../traits/const-traits/const-drop-bound.rs | 2 +- .../const-traits/const-drop-bound.stderr | 45 +------ .../traits/const-traits/const-drop-fail-2.rs | 2 +- .../const-traits/const-drop-fail-2.stderr | 24 +--- .../effects/auxiliary/minicore.rs | 4 +- 12 files changed, 57 insertions(+), 180 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index accce883e39dd..39eb1a7db78ba 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -175,6 +175,11 @@ impl Qualif for NeedsNonConstDrop { return false; } + // If this doesn't need drop at all, then don't select `~const Destruct`. + if !ty.needs_drop(cx.tcx, cx.typing_env) { + return false; + } + // We check that the type is `~const Destruct` since that will verify that // the type is both `~const Drop` (if a drop impl exists for the adt), *and* // that the components of this type are also `~const Destruct`. This @@ -203,7 +208,7 @@ impl Qualif for NeedsNonConstDrop { // in its value since: // 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` + // While this could be 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 diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index b9a75fedcbefd..b376b0d652fac 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -426,7 +426,7 @@ 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 + /// Allows using `~const Destruct` bounds and calling drop impls in const contexts. (unstable, const_destruct, "CURRENT_RUSTC_VERSION", Some(133214)), /// Allows `for _ in _` loops in const contexts. (unstable, const_for, "1.56.0", Some(87575)), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4a0d50c153c8a..1bd19a6031a3c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -4,7 +4,7 @@ pub mod tls; -use std::assert_matches::assert_matches; +use std::assert_matches::{assert_matches, debug_assert_matches}; use std::borrow::Borrow; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; @@ -377,14 +377,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } fn impl_is_const(self, def_id: DefId) -> bool { + debug_assert_matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }); self.is_conditionally_const(def_id) } fn fn_is_const(self, def_id: DefId) -> bool { + debug_assert_matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn); self.is_conditionally_const(def_id) } fn alias_has_const_conditions(self, def_id: DefId) -> bool { + debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::OpaqueTy); self.is_conditionally_const(def_id) } diff --git a/tests/ui/consts/const-block-const-bound.rs b/tests/ui/consts/const-block-const-bound.rs index 933eb6cfc0afb..596aac09b3114 100644 --- a/tests/ui/consts/const-block-const-bound.rs +++ b/tests/ui/consts/const-block-const-bound.rs @@ -1,7 +1,7 @@ //@ known-bug: #103507 #![allow(unused)] -#![feature(const_trait_impl, negative_impls)] +#![feature(const_trait_impl, negative_impls, const_destruct)] use std::marker::Destruct; diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index 9dd6a96686f36..5e24959146b83 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -1,23 +1,3 @@ -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 #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/const-block-const-bound.rs:8:22 - | -LL | const fn f(x: T) {} - | ^^^^^^^^ - | - = note: see issue #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: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-block-const-bound.rs:8:15 | @@ -40,7 +20,6 @@ LL | const fn f(x: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0493, E0658. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/fn_trait_refs.rs b/tests/ui/consts/fn_trait_refs.rs index 4defe4dedc784..af233efd738a2 100644 --- a/tests/ui/consts/fn_trait_refs.rs +++ b/tests/ui/consts/fn_trait_refs.rs @@ -5,6 +5,7 @@ #![feature(unboxed_closures)] #![feature(const_trait_impl)] #![feature(const_cmp)] +#![feature(const_destruct)] use std::marker::Destruct; diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index c84e604793621..dc601fbe48897 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -1,53 +1,3 @@ -error[E0658]: use of unstable library feature `const_destruct` - --> $DIR/fn_trait_refs.rs:9:5 - | -LL | use std::marker::Destruct; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/fn_trait_refs.rs:13:31 - | -LL | T: ~const Fn<()> + ~const Destruct, - | ^^^^^^^^ - | - = note: see issue #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/fn_trait_refs.rs:20:34 - | -LL | T: ~const FnMut<()> + ~const Destruct, - | ^^^^^^^^ - | - = note: see issue #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/fn_trait_refs.rs:34:31 - | -LL | T: ~const Fn<()> + ~const Destruct, - | ^^^^^^^^ - | - = note: see issue #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/fn_trait_refs.rs:48:34 - | -LL | T: ~const FnMut<()> + ~const Destruct, - | ^^^^^^^^ - | - = note: see issue #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[E0635]: unknown feature `const_fn_trait_ref_impls` --> $DIR/fn_trait_refs.rs:3:12 | @@ -61,19 +11,19 @@ LL | #![feature(const_cmp)] | ^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:13:8 + --> $DIR/fn_trait_refs.rs:14:8 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:13:24 + --> $DIR/fn_trait_refs.rs:14:24 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:13:8 + --> $DIR/fn_trait_refs.rs:14:8 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ @@ -81,7 +31,7 @@ LL | T: ~const Fn<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:13:8 + --> $DIR/fn_trait_refs.rs:14:8 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ @@ -89,7 +39,7 @@ LL | T: ~const Fn<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:13:24 + --> $DIR/fn_trait_refs.rs:14:24 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ @@ -97,19 +47,19 @@ LL | T: ~const Fn<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:20:8 + --> $DIR/fn_trait_refs.rs:21:8 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:20:27 + --> $DIR/fn_trait_refs.rs:21:27 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:20:8 + --> $DIR/fn_trait_refs.rs:21:8 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ @@ -117,7 +67,7 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:20:8 + --> $DIR/fn_trait_refs.rs:21:8 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ @@ -125,7 +75,7 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:20:27 + --> $DIR/fn_trait_refs.rs:21:27 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ @@ -133,13 +83,13 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:27:8 + --> $DIR/fn_trait_refs.rs:28:8 | LL | T: ~const FnOnce<()>, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:27:8 + --> $DIR/fn_trait_refs.rs:28:8 | LL | T: ~const FnOnce<()>, | ^^^^^^ @@ -147,7 +97,7 @@ LL | T: ~const FnOnce<()>, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:27:8 + --> $DIR/fn_trait_refs.rs:28:8 | LL | T: ~const FnOnce<()>, | ^^^^^^ @@ -155,19 +105,19 @@ LL | T: ~const FnOnce<()>, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:34:8 + --> $DIR/fn_trait_refs.rs:35:8 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:34:24 + --> $DIR/fn_trait_refs.rs:35:24 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:34:8 + --> $DIR/fn_trait_refs.rs:35:8 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ @@ -175,7 +125,7 @@ LL | T: ~const Fn<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:34:8 + --> $DIR/fn_trait_refs.rs:35:8 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ @@ -183,7 +133,7 @@ LL | T: ~const Fn<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:34:24 + --> $DIR/fn_trait_refs.rs:35:24 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ @@ -191,19 +141,19 @@ LL | T: ~const Fn<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:48:8 + --> $DIR/fn_trait_refs.rs:49:8 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:48:27 + --> $DIR/fn_trait_refs.rs:49:27 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:48:8 + --> $DIR/fn_trait_refs.rs:49:8 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ @@ -211,7 +161,7 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:48:8 + --> $DIR/fn_trait_refs.rs:49:8 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ @@ -219,7 +169,7 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:48:27 + --> $DIR/fn_trait_refs.rs:49:27 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^ @@ -227,7 +177,7 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0015]: cannot call non-const operator in constants - --> $DIR/fn_trait_refs.rs:70:17 + --> $DIR/fn_trait_refs.rs:71:17 | LL | assert!(test_one == (1, 1, 1)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -235,7 +185,7 @@ LL | assert!(test_one == (1, 1, 1)); = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const operator in constants - --> $DIR/fn_trait_refs.rs:73:17 + --> $DIR/fn_trait_refs.rs:74:17 | LL | assert!(test_two == (2, 2)); | ^^^^^^^^^^^^^^^^^^ @@ -243,7 +193,7 @@ LL | assert!(test_two == (2, 2)); = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:15:5 + --> $DIR/fn_trait_refs.rs:16:5 | LL | f() | ^^^ @@ -255,7 +205,7 @@ LL | T: ~const Fn<()> + ~const Destruct + ~const Fn(), | +++++++++++++ error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/fn_trait_refs.rs:11:23 + --> $DIR/fn_trait_refs.rs:12:23 | LL | const fn tester_fn(f: T) -> T::Output | ^ the destructor for this type cannot be evaluated in constant functions @@ -264,7 +214,7 @@ LL | } | - value is dropped here error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:22:5 + --> $DIR/fn_trait_refs.rs:23:5 | LL | f() | ^^^ @@ -276,7 +226,7 @@ LL | T: ~const FnMut<()> + ~const Destruct + ~const FnMut(), | ++++++++++++++++ error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/fn_trait_refs.rs:18:27 + --> $DIR/fn_trait_refs.rs:19:27 | LL | const fn tester_fn_mut(mut f: T) -> T::Output | ^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -285,7 +235,7 @@ LL | } | - value is dropped here error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:29:5 + --> $DIR/fn_trait_refs.rs:30:5 | LL | f() | ^^^ @@ -297,7 +247,7 @@ LL | T: ~const FnOnce<()> + ~const FnOnce(), | +++++++++++++++++ error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/fn_trait_refs.rs:32:21 + --> $DIR/fn_trait_refs.rs:33:21 | LL | const fn test_fn(mut f: T) -> (T::Output, T::Output, T::Output) | ^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -306,7 +256,7 @@ LL | } | - value is dropped here error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/fn_trait_refs.rs:46:25 + --> $DIR/fn_trait_refs.rs:47:25 | LL | const fn test_fn_mut(mut f: T) -> (T::Output, T::Output) | ^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -314,7 +264,7 @@ LL | const fn test_fn_mut(mut f: T) -> (T::Output, T::Output) LL | } | - value is dropped here -error: aborting due to 39 previous errors +error: aborting due to 34 previous errors -Some errors have detailed explanations: E0015, E0493, E0635, E0658. +Some errors have detailed explanations: E0015, E0493, E0635. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-drop-bound.rs b/tests/ui/traits/const-traits/const-drop-bound.rs index b0790f86ef54f..398fb39064055 100644 --- a/tests/ui/traits/const-traits/const-drop-bound.rs +++ b/tests/ui/traits/const-traits/const-drop-bound.rs @@ -2,7 +2,7 @@ // FIXME check-pass #![feature(const_trait_impl)] -#![feature(const_precise_live_drops)] +#![feature(const_precise_live_drops, const_destruct)] use std::marker::Destruct; diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr index 9abfa630e4def..eba39f859af52 100644 --- a/tests/ui/traits/const-traits/const-drop-bound.stderr +++ b/tests/ui/traits/const-traits/const-drop-bound.stderr @@ -1,43 +1,3 @@ -error[E0658]: use of unstable library feature `const_destruct` - --> $DIR/const-drop-bound.rs:7:5 - | -LL | use std::marker::Destruct; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/const-drop-bound.rs:9:68 - | -LL | const fn foo(res: Result) -> Option where E: ~const Destruct { - | ^^^^^^^^ - | - = note: see issue #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/const-drop-bound.rs:20:15 - | -LL | T: ~const Destruct, - | ^^^^^^^^ - | - = note: see issue #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/const-drop-bound.rs:21:15 - | -LL | E: ~const Destruct, - | ^^^^^^^^ - | - = note: see issue #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: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-drop-bound.rs:9:61 | @@ -88,7 +48,6 @@ LL | Err(_e) => None, | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 11 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0493, E0658. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.rs b/tests/ui/traits/const-traits/const-drop-fail-2.rs index 5d7bafa38871f..ed4faa95bd049 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.rs +++ b/tests/ui/traits/const-traits/const-drop-fail-2.rs @@ -1,5 +1,5 @@ //@ known-bug: #110395 -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_destruct)] // #![cfg_attr(precise, feature(const_precise_live_drops))] use std::marker::{Destruct, PhantomData}; diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stderr index d871f4d425d5d..fde106599c236 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stderr @@ -1,23 +1,3 @@ -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 #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[E0658]: use of unstable library feature `const_destruct` - --> $DIR/const-drop-fail-2.rs:20:26 - | -LL | const fn check(_: T) {} - | ^^^^^^^^ - | - = note: see issue #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: const `impl` for trait `Drop` which is not marked with `#[const_trait]` --> $DIR/const-drop-fail-2.rs:39:25 | @@ -55,7 +35,7 @@ LL | const fn check(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0493, E0658. +Some errors have detailed explanations: E0277, E0493. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs index 660fb43259408..aaa61e21155f4 100644 --- a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs +++ b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs @@ -12,7 +12,7 @@ fundamental, marker_trait_attr, const_trait_impl, - const_destruct, + const_destruct )] #![allow(internal_features, incomplete_features)] #![no_std] @@ -450,7 +450,7 @@ pub trait Clone: Sized { fn clone(&self) -> Self; fn clone_from(&mut self, source: &Self) where - Self: ~const Destruct, + Self: ~const Destruct, { *self = source.clone() }