Skip to content

Commit 2a0d374

Browse files
committed
Add attr externally_constructed indicates pub struct with private fields could be constructed externally
1 parent e9e6e2e commit 2a0d374

File tree

7 files changed

+76
-2
lines changed

7 files changed

+76
-2
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
432432
ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
433433
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
434434
ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
435+
gated!(
436+
externally_constructed, Normal, template!(Word), WarnFollowing,
437+
EncodeCrossCrate::Yes, externally_constructed_attr, experimental!(mark_externally_constructed)
438+
),
435439

436440
// Limits:
437441
ungated!(

compiler/rustc_feature/src/unstable.rs

+3
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,9 @@ declare_features! (
463463
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
464464
/// Allows defining `extern type`s.
465465
(unstable, extern_types, "1.23.0", Some(43467)),
466+
/// Allows `#[externally_constructed]` on pub structs with private fields,
467+
/// indicates they will be contructed externally during dead code analysis.
468+
(unstable, externally_constructed_attr, "CURRENT_RUSTC_VERSION", Some(126634)),
466469
/// Allow using 128-bit (quad precision) floating point numbers.
467470
(unstable, f128, "1.78.0", Some(116909)),
468471
/// Allow using 16-bit (half precision) floating point numbers.

compiler/rustc_passes/src/dead.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -930,8 +930,11 @@ fn create_and_seed_worklist(
930930
// checks impls, impl-items and pub structs with all public fields later
931931
match tcx.def_kind(id) {
932932
DefKind::Impl { .. } => false,
933-
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
934-
DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
933+
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn
934+
=> !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
935+
DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id())
936+
|| has_allow_dead_code_or_lang_attr(tcx, id).is_some()
937+
|| tcx.has_attr(id, sym::externally_constructed),
935938
_ => true
936939
})
937940
.map(|id| (id, ComesFromAllowExpect::No))

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,8 @@ symbols! {
809809
extern_types,
810810
external,
811811
external_doc,
812+
externally_constructed,
813+
externally_constructed_attr,
812814
f,
813815
f128,
814816
f128_nan,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//@ check-pass
2+
#![feature(externally_constructed_attr)]
3+
4+
#[repr(C)]
5+
#[externally_constructed]
6+
pub struct Foo {
7+
pub i: i16,
8+
align: i16
9+
}
10+
11+
mod ffi {
12+
use super::*;
13+
14+
extern "C" {
15+
pub fn DomPromise_AddRef(promise: *const Promise);
16+
pub fn DomPromise_Release(promise: *const Promise);
17+
}
18+
}
19+
20+
#[repr(C)]
21+
#[externally_constructed]
22+
pub struct Promise {
23+
private: [u8; 0],
24+
__nosync: ::std::marker::PhantomData<::std::rc::Rc<u8>>,
25+
}
26+
27+
pub unsafe trait RefCounted {
28+
unsafe fn addref(&self);
29+
unsafe fn release(&self);
30+
}
31+
32+
unsafe impl RefCounted for Promise {
33+
unsafe fn addref(&self) {
34+
ffi::DomPromise_AddRef(self)
35+
}
36+
unsafe fn release(&self) {
37+
ffi::DomPromise_Release(self)
38+
}
39+
}
40+
41+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[repr(C)]
2+
#[externally_constructed] //~ ERROR the `#[mark_externally_constructed]` attribute is an experimental feature
3+
pub struct Foo {
4+
pub i: i16,
5+
align: i16
6+
}
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0658]: the `#[mark_externally_constructed]` attribute is an experimental feature
2+
--> $DIR/feature-gate-externally_constructed_attr.rs:2:1
3+
|
4+
LL | #[externally_constructed]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #126634 <https://github.com/rust-lang/rust/issues/126634> for more information
8+
= help: add `#![feature(externally_constructed_attr)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)