Skip to content

Commit e5385a8

Browse files
committed
Require const blocks to only use const stable things
1 parent 7523dd0 commit e5385a8

16 files changed

Lines changed: 239 additions & 36 deletions

File tree

compiler/rustc_ast_lowering/src/asm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
207207
}
208208
}
209209
InlineAsmOperand::Const { anon_const } => hir::InlineAsmOperand::Const {
210-
anon_const: self.lower_const_block(anon_const),
210+
anon_const: self.lower_const_block(anon_const, &[]),
211211
},
212212
InlineAsmOperand::Sym { sym } => {
213213
let static_def_id = self

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
105105

106106
let kind = match &e.kind {
107107
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
108-
ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_const_block(c)),
108+
ExprKind::ConstBlock(c) => {
109+
hir::ExprKind::ConstBlock(self.lower_const_block(c, attrs))
110+
}
109111
ExprKind::Repeat(expr, count) => {
110112
let expr = self.lower_expr(expr);
111113
let count = self.lower_array_length_to_const_arg(count);
@@ -394,12 +396,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
394396
})
395397
}
396398

397-
pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
399+
pub(crate) fn lower_const_block(
400+
&mut self,
401+
c: &AnonConst,
402+
attrs: &'hir [hir::Attribute],
403+
) -> hir::ConstBlock {
398404
self.with_new_scopes(c.value.span, |this| {
399405
let def_id = this.local_def_id(c.id);
406+
let hir_id = this.lower_node_id(c.id);
407+
if !attrs.is_empty() {
408+
this.attrs.insert(hir_id.local_id, attrs);
409+
}
400410
hir::ConstBlock {
401411
def_id,
402-
hir_id: this.lower_node_id(c.id),
412+
hir_id,
403413
body: this.lower_const_body(c.value.span, Some(&c.value)),
404414
}
405415
})

compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
6363
Allow(Target::Method(MethodKind::Inherent)),
6464
Allow(Target::Method(MethodKind::Trait { body: true })),
6565
Allow(Target::Method(MethodKind::TraitImpl)),
66+
Allow(Target::Expression), // FIXME: should only allow inline consts
6667
]);
6768
const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
6869

compiler/rustc_attr_parsing/src/attributes/stability.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
256256
Allow(Target::AssocConst),
257257
Allow(Target::Trait),
258258
Allow(Target::Static),
259+
Allow(Target::Expression), // FIXME: we really only want to allow inline consts
259260
Allow(Target::Crate),
260261
Allow(Target::MacroDef), // FIXME(oli-obk): remove this and eliminate the manual check for it
261262
]);

compiler/rustc_const_eval/src/check_consts/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
5454
pub fn enforce_recursive_const_stability(&self) -> bool {
5555
// We can skip this if neither `staged_api` nor `-Zforce-unstable-if-unmarked` are enabled,
5656
// since in such crates `lookup_const_stability` will always be `None`.
57-
self.const_kind == Some(hir::ConstContext::ConstFn)
58-
&& (self.tcx.features().staged_api()
59-
|| self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked)
57+
matches!(
58+
self.const_kind,
59+
Some(hir::ConstContext::ConstFn | hir::ConstContext::Const { inline: true })
60+
) && (self.tcx.features().staged_api()
61+
|| self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked)
6062
&& is_fn_or_trait_safe_to_expose_on_stable(self.tcx, self.def_id().to_def_id())
6163
}
6264

compiler/rustc_passes/src/errors.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,18 @@ pub(crate) struct MissingConstErr {
10571057
pub fn_sig_span: Span,
10581058
}
10591059

1060+
#[derive(Diagnostic)]
1061+
#[diag(
1062+
"const stability of inline consts must match const stability of containing item"
1063+
)]
1064+
pub(crate) struct UnstableInlineConstInConst {
1065+
#[primary_span]
1066+
#[help("did you mean to use `rustc_allow_const_fn_unstable`?")]
1067+
pub span: Span,
1068+
#[note("stability marker of containing item defined here")]
1069+
pub parent_span: Option<Span>,
1070+
}
1071+
10601072
#[derive(Diagnostic)]
10611073
#[diag(
10621074
"attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`"

compiler/rustc_passes/src/stability.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,12 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
334334

335335
macro_rules! find_attr_span {
336336
($name:ident) => {{
337-
let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
337+
find_attr_span!($name, def_id)
338+
}};
339+
($name:ident, $id: expr) => {{
340+
let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id($id));
338341
find_attr!(attrs, AttributeKind::$name { span, .. } => *span)
339-
}}
342+
}};
340343
}
341344

342345
if stab.is_none()
@@ -398,6 +401,16 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
398401
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
399402
}
400403

404+
if let DefKind::InlineConst = self.tcx.def_kind(def_id)
405+
&& const_stab.is_some()
406+
&& let parent = self.tcx.local_parent(def_id)
407+
&& self.tcx.lookup_const_stability(parent) != const_stab
408+
&& let Some(span) = find_attr_span!(RustcConstStability)
409+
{
410+
let parent_span = find_attr_span!(RustcConstStability, parent);
411+
self.tcx.dcx().emit_err(errors::UnstableInlineConstInConst { span, parent_span });
412+
}
413+
401414
// If this is marked const *stable*, it must also be regular-stable.
402415
if let Some(const_stab) = const_stab
403416
&& let Some(fn_sig) = fn_sig
@@ -478,6 +491,11 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
478491
intravisit::walk_item(self, i)
479492
}
480493

494+
fn visit_inline_const(&mut self, c: &'tcx rustc_hir::ConstBlock) -> Self::Result {
495+
self.check_compatible_stability(c.def_id);
496+
intravisit::walk_inline_const(self, c)
497+
}
498+
481499
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
482500
self.check_compatible_stability(ti.owner_id.def_id);
483501
self.check_missing_stability(ti.owner_id.def_id);
@@ -601,7 +619,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
601619
let attrs = self.tcx.hir_attrs(item.hir_id());
602620
let stab = find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span));
603621

604-
// FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
605622
let const_stab = find_attr!(attrs, AttributeKind::RustcConstStability{stability, ..} => *stability);
606623

607624
let unstable_feature_stab =

library/alloc/src/boxed/thin.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,12 @@ impl<H> WithHeader<H> {
321321
// of the header, past the padding, so the assigned type makes sense.
322322
// It also ensures that the address at the end of the header is sufficiently
323323
// aligned for T.
324-
let alloc: &<Dyn as Pointee>::Metadata = const {
324+
// We generate the vtable in a const block instead of having the compiler
325+
// generate it for us. The basics to allocate new memory during ctfe are
326+
// unstable, but we can always change the intrinsic logic to support the
327+
// needs of new_unsize_zst in the future.
328+
let alloc: &<Dyn as Pointee>::Metadata = #[rustc_allow_const_fn_unstable(const_heap)]
329+
const {
325330
// FIXME: just call `WithHeader::alloc_layout` with size reset to 0.
326331
// Currently that's blocked on `Layout::extend` not being `const fn`.
327332

library/core/src/any.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,10 @@ impl fmt::Debug for TypeId {
864864
#[stable(feature = "type_name", since = "1.38.0")]
865865
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
866866
pub const fn type_name<T: ?Sized>() -> &'static str {
867-
const { intrinsics::type_name::<T>() }
867+
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
868+
const {
869+
intrinsics::type_name::<T>()
870+
}
868871
}
869872

870873
/// Returns the type name of the pointed-to value as a string slice.
@@ -942,13 +945,18 @@ pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
942945
/// ```
943946
#[must_use]
944947
#[unstable(feature = "try_as_dyn", issue = "144361")]
948+
#[rustc_const_unstable(feature = "try_as_dyn", issue = "144361")]
945949
pub const fn try_as_dyn<
946950
T: Any + 'static,
947951
U: ptr::Pointee<Metadata = ptr::DynMetadata<U>> + ?Sized + 'static,
948952
>(
949953
t: &T,
950954
) -> Option<&U> {
951-
let vtable: Option<ptr::DynMetadata<U>> = const { intrinsics::vtable_for::<T, U>() };
955+
let vtable: Option<ptr::DynMetadata<U>> =
956+
#[rustc_const_unstable(feature = "try_as_dyn", issue = "144361")]
957+
const {
958+
intrinsics::vtable_for::<T, U>()
959+
};
952960
match vtable {
953961
Some(dyn_metadata) => {
954962
let pointer = ptr::from_raw_parts(t, dyn_metadata);
@@ -995,13 +1003,18 @@ pub const fn try_as_dyn<
9951003
/// ```
9961004
#[must_use]
9971005
#[unstable(feature = "try_as_dyn", issue = "144361")]
1006+
#[rustc_const_unstable(feature = "try_as_dyn", issue = "144361")]
9981007
pub const fn try_as_dyn_mut<
9991008
T: Any + 'static,
10001009
U: ptr::Pointee<Metadata = ptr::DynMetadata<U>> + ?Sized + 'static,
10011010
>(
10021011
t: &mut T,
10031012
) -> Option<&mut U> {
1004-
let vtable: Option<ptr::DynMetadata<U>> = const { intrinsics::vtable_for::<T, U>() };
1013+
let vtable: Option<ptr::DynMetadata<U>> =
1014+
#[rustc_const_unstable(feature = "try_as_dyn", issue = "144361")]
1015+
const {
1016+
intrinsics::vtable_for::<T, U>()
1017+
};
10051018
match vtable {
10061019
Some(dyn_metadata) => {
10071020
let pointer = ptr::from_raw_parts_mut(t, dyn_metadata);

library/core/src/intrinsics/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2887,6 +2887,7 @@ pub const fn type_name<T: ?Sized>() -> &'static str;
28872887
#[rustc_nounwind]
28882888
#[unstable(feature = "core_intrinsics", issue = "none")]
28892889
#[rustc_intrinsic]
2890+
#[rustc_intrinsic_const_stable_indirect]
28902891
pub const fn type_id<T: ?Sized + 'static>() -> crate::any::TypeId;
28912892

28922893
/// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the

0 commit comments

Comments
 (0)