Skip to content

Commit 8da6239

Browse files
committed
Auto merge of #142443 - matthiaskrgr:rollup-l1l6d0v, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #128425 (Make `missing_fragment_specifier` an unconditional error) - #135927 (retpoline and retpoline-external-thunk flags (target modifiers) to enable retpoline-related target features) - #140770 (add `extern "custom"` functions) - #142176 (tests: Split dont-shuffle-bswaps along opt-levels and arches) - #142248 (Add supported asm types for LoongArch32) - #142267 (assert more in release in `rustc_ast_lowering`) - #142274 (Update the stdarch submodule) - #142276 (Update dependencies in `library/Cargo.lock`) - #142308 (Upgrade `object`, `addr2line`, and `unwinding` in the standard library) Failed merges: - #140920 (Extract some shared code from codegen backend target feature handling) r? `@ghost` `@rustbot` modify labels: rollup try-job: aarch64-apple try-job: x86_64-msvc-1 try-job: x86_64-gnu try-job: dist-i586-gnu-i586-i686-musl try-job: test-various
2 parents 0d6ab20 + 71490ff commit 8da6239

File tree

91 files changed

+1444
-529
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+1444
-529
lines changed

compiler/rustc_abi/src/canon_abi.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub enum CanonAbi {
2828
Rust,
2929
RustCold,
3030

31+
/// An ABI that rustc does not know how to call or define.
32+
Custom,
33+
3134
/// ABIs relevant to 32-bit Arm targets
3235
Arm(ArmCall),
3336
/// ABI relevant to GPUs: the entry point for a GPU kernel
@@ -57,6 +60,7 @@ impl fmt::Display for CanonAbi {
5760
CanonAbi::C => ExternAbi::C { unwind: false },
5861
CanonAbi::Rust => ExternAbi::Rust,
5962
CanonAbi::RustCold => ExternAbi::RustCold,
63+
CanonAbi::Custom => ExternAbi::Custom,
6064
CanonAbi::Arm(arm_call) => match arm_call {
6165
ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false },
6266
ArmCall::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall,

compiler/rustc_abi/src/extern_abi.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ pub enum ExternAbi {
4040
/// Even normally-compatible Rust types can become ABI-incompatible with this ABI!
4141
Unadjusted,
4242

43+
/// An ABI that rustc does not know how to call or define. Functions with this ABI can
44+
/// only be created using `#[naked]` functions or `extern "custom"` blocks, and can only
45+
/// be called from inline assembly.
46+
Custom,
47+
4348
/// UEFI ABI, usually an alias of C, but sometimes an arch-specific alias
4449
/// and only valid on platforms that have a UEFI standard
4550
EfiApi,
@@ -141,6 +146,7 @@ abi_impls! {
141146
AvrNonBlockingInterrupt =><= "avr-non-blocking-interrupt",
142147
Cdecl { unwind: false } =><= "cdecl",
143148
Cdecl { unwind: true } =><= "cdecl-unwind",
149+
Custom =><= "custom",
144150
EfiApi =><= "efiapi",
145151
Fastcall { unwind: false } =><= "fastcall",
146152
Fastcall { unwind: true } =><= "fastcall-unwind",

compiler/rustc_ast/src/ast.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3542,6 +3542,38 @@ impl FnHeader {
35423542
|| matches!(constness, Const::Yes(_))
35433543
|| !matches!(ext, Extern::None)
35443544
}
3545+
3546+
/// Return a span encompassing the header, or none if all options are default.
3547+
pub fn span(&self) -> Option<Span> {
3548+
fn append(a: &mut Option<Span>, b: Span) {
3549+
*a = match a {
3550+
None => Some(b),
3551+
Some(x) => Some(x.to(b)),
3552+
}
3553+
}
3554+
3555+
let mut full_span = None;
3556+
3557+
match self.safety {
3558+
Safety::Unsafe(span) | Safety::Safe(span) => append(&mut full_span, span),
3559+
Safety::Default => {}
3560+
};
3561+
3562+
if let Some(coroutine_kind) = self.coroutine_kind {
3563+
append(&mut full_span, coroutine_kind.span());
3564+
}
3565+
3566+
if let Const::Yes(span) = self.constness {
3567+
append(&mut full_span, span);
3568+
}
3569+
3570+
match self.ext {
3571+
Extern::Implicit(span) | Extern::Explicit(_, span) => append(&mut full_span, span),
3572+
Extern::None => {}
3573+
}
3574+
3575+
full_span
3576+
}
35453577
}
35463578

35473579
impl Default for FnHeader {

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
6363

6464
for (def_id, info) in lctx.children {
6565
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
66-
debug_assert!(
66+
assert!(
6767
matches!(owner, hir::MaybeOwner::Phantom),
6868
"duplicate copy of {def_id:?} in lctx.children"
6969
);
@@ -78,7 +78,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
7878
match node {
7979
AstOwner::NonOwner => {}
8080
AstOwner::Crate(c) => {
81-
debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
81+
assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
8282
self.with_lctx(CRATE_NODE_ID, |lctx| {
8383
let module = lctx.lower_mod(&c.items, &c.spans);
8484
// FIXME(jdonszelman): is dummy span ever a problem here?
@@ -1160,7 +1160,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11601160
) -> hir::BodyId {
11611161
let body = hir::Body { params, value: self.arena.alloc(value) };
11621162
let id = body.id();
1163-
debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
1163+
assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
11641164
self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
11651165
id
11661166
}
@@ -1673,8 +1673,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
16731673
itctx: ImplTraitContext,
16741674
f: impl FnOnce(&mut Self) -> T,
16751675
) -> (&'hir hir::Generics<'hir>, T) {
1676-
debug_assert!(self.impl_trait_defs.is_empty());
1677-
debug_assert!(self.impl_trait_bounds.is_empty());
1676+
assert!(self.impl_trait_defs.is_empty());
1677+
assert!(self.impl_trait_bounds.is_empty());
16781678

16791679
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
16801680
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
523523
span: Span,
524524
) -> LocalDefId {
525525
let parent = self.current_hir_id_owner.def_id;
526-
debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
526+
assert_ne!(node_id, ast::DUMMY_NODE_ID);
527527
assert!(
528528
self.opt_local_def_id(node_id).is_none(),
529529
"adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",
@@ -607,10 +607,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
607607
}
608608

609609
let item = f(self);
610-
debug_assert_eq!(owner_id, item.def_id());
610+
assert_eq!(owner_id, item.def_id());
611611
// `f` should have consumed all the elements in these vectors when constructing `item`.
612-
debug_assert!(self.impl_trait_defs.is_empty());
613-
debug_assert!(self.impl_trait_bounds.is_empty());
612+
assert!(self.impl_trait_defs.is_empty());
613+
assert!(self.impl_trait_bounds.is_empty());
614614
let info = self.make_owner_info(item);
615615

616616
self.attrs = current_attrs;
@@ -918,7 +918,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
918918
} else {
919919
let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span), id);
920920

921-
debug_assert_eq!(id.owner, self.current_hir_id_owner);
921+
assert_eq!(id.owner, self.current_hir_id_owner);
922922
let ret = self.arena.alloc_from_iter(lowered_attrs);
923923

924924
// this is possible if an item contained syntactical attribute,
@@ -956,10 +956,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
956956
}
957957

958958
fn alias_attrs(&mut self, id: HirId, target_id: HirId) {
959-
debug_assert_eq!(id.owner, self.current_hir_id_owner);
960-
debug_assert_eq!(target_id.owner, self.current_hir_id_owner);
959+
assert_eq!(id.owner, self.current_hir_id_owner);
960+
assert_eq!(target_id.owner, self.current_hir_id_owner);
961961
if let Some(&a) = self.attrs.get(&target_id.local_id) {
962-
debug_assert!(!a.is_empty());
962+
assert!(!a.is_empty());
963963
self.attrs.insert(id.local_id, a);
964964
}
965965
}
@@ -1438,7 +1438,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14381438
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
14391439
self.resolver.get_lifetime_res(t.id)
14401440
{
1441-
debug_assert_eq!(start.plus(1), end);
1441+
assert_eq!(start.plus(1), end);
14421442
start
14431443
} else {
14441444
self.next_node_id()
@@ -1846,16 +1846,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
18461846
let res = match res {
18471847
LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param),
18481848
LifetimeRes::Fresh { param, .. } => {
1849-
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
1849+
assert_eq!(ident.name, kw::UnderscoreLifetime);
18501850
let param = self.local_def_id(param);
18511851
hir::LifetimeKind::Param(param)
18521852
}
18531853
LifetimeRes::Infer => {
1854-
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
1854+
assert_eq!(ident.name, kw::UnderscoreLifetime);
18551855
hir::LifetimeKind::Infer
18561856
}
18571857
LifetimeRes::Static { .. } => {
1858-
debug_assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime));
1858+
assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime));
18591859
hir::LifetimeKind::Static
18601860
}
18611861
LifetimeRes::Error => hir::LifetimeKind::Error,
@@ -2285,7 +2285,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22852285
) -> hir::Stmt<'hir> {
22862286
let hir_id = self.next_id();
22872287
if let Some(a) = attrs {
2288-
debug_assert!(!a.is_empty());
2288+
assert!(!a.is_empty());
22892289
self.attrs.insert(hir_id.local_id, a);
22902290
}
22912291
let local = hir::LetStmt {

compiler/rustc_ast_lowering/src/stability.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,5 +134,8 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
134134
feature: sym::cmse_nonsecure_entry,
135135
explain: GateReason::Experimental,
136136
}),
137+
ExternAbi::Custom => {
138+
Err(UnstableAbi { abi, feature: sym::abi_custom, explain: GateReason::Experimental })
139+
}
137140
}
138141
}

compiler/rustc_ast_passes/messages.ftl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
ast_passes_abi_custom_coroutine =
2+
functions with the `"custom"` ABI cannot be `{$coroutine_kind_str}`
3+
.suggestion = remove the `{$coroutine_kind_str}` keyword from this definiton
4+
5+
ast_passes_abi_custom_invalid_signature =
6+
invalid signature for `extern "custom"` function
7+
.note = functions with the `"custom"` ABI cannot have any parameters or return type
8+
.suggestion = remove the parameters and return type
9+
10+
ast_passes_abi_custom_safe_foreign_function =
11+
foreign functions with the `"custom"` ABI cannot be safe
12+
.suggestion = remove the `safe` keyword from this definition
13+
14+
ast_passes_abi_custom_safe_function =
15+
functions with the `"custom"` ABI must be unsafe
16+
.suggestion = add the `unsafe` keyword to this definition
17+
118
ast_passes_assoc_const_without_body =
219
associated constant in `impl` without body
320
.suggestion = provide a definition for the constant

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
1919
use std::mem;
2020
use std::ops::{Deref, DerefMut};
21+
use std::str::FromStr;
2122

2223
use itertools::{Either, Itertools};
2324
use rustc_abi::ExternAbi;
@@ -81,6 +82,7 @@ struct AstValidator<'a> {
8182

8283
/// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
8384
extern_mod_safety: Option<Safety>,
85+
extern_mod_abi: Option<ExternAbi>,
8486

8587
lint_node_id: NodeId,
8688

@@ -121,10 +123,17 @@ impl<'a> AstValidator<'a> {
121123
self.outer_trait_or_trait_impl = old;
122124
}
123125

124-
fn with_in_extern_mod(&mut self, extern_mod_safety: Safety, f: impl FnOnce(&mut Self)) {
125-
let old = mem::replace(&mut self.extern_mod_safety, Some(extern_mod_safety));
126+
fn with_in_extern_mod(
127+
&mut self,
128+
extern_mod_safety: Safety,
129+
abi: Option<ExternAbi>,
130+
f: impl FnOnce(&mut Self),
131+
) {
132+
let old_safety = mem::replace(&mut self.extern_mod_safety, Some(extern_mod_safety));
133+
let old_abi = mem::replace(&mut self.extern_mod_abi, abi);
126134
f(self);
127-
self.extern_mod_safety = old;
135+
self.extern_mod_safety = old_safety;
136+
self.extern_mod_abi = old_abi;
128137
}
129138

130139
fn with_tilde_const(
@@ -370,6 +379,65 @@ impl<'a> AstValidator<'a> {
370379
}
371380
}
372381

382+
/// An `extern "custom"` function must be unsafe, and must not have any parameters or return
383+
/// type.
384+
fn check_custom_abi(&self, ctxt: FnCtxt, ident: &Ident, sig: &FnSig) {
385+
let dcx = self.dcx();
386+
387+
// An `extern "custom"` function must be unsafe.
388+
match sig.header.safety {
389+
Safety::Unsafe(_) => { /* all good */ }
390+
Safety::Safe(safe_span) => {
391+
let safe_span =
392+
self.sess.psess.source_map().span_until_non_whitespace(safe_span.to(sig.span));
393+
dcx.emit_err(errors::AbiCustomSafeForeignFunction { span: sig.span, safe_span });
394+
}
395+
Safety::Default => match ctxt {
396+
FnCtxt::Foreign => { /* all good */ }
397+
FnCtxt::Free | FnCtxt::Assoc(_) => {
398+
self.dcx().emit_err(errors::AbiCustomSafeFunction {
399+
span: sig.span,
400+
unsafe_span: sig.span.shrink_to_lo(),
401+
});
402+
}
403+
},
404+
}
405+
406+
// An `extern "custom"` function cannot be `async` and/or `gen`.
407+
if let Some(coroutine_kind) = sig.header.coroutine_kind {
408+
let coroutine_kind_span = self
409+
.sess
410+
.psess
411+
.source_map()
412+
.span_until_non_whitespace(coroutine_kind.span().to(sig.span));
413+
414+
self.dcx().emit_err(errors::AbiCustomCoroutine {
415+
span: sig.span,
416+
coroutine_kind_span,
417+
coroutine_kind_str: coroutine_kind.as_str(),
418+
});
419+
}
420+
421+
// An `extern "custom"` function must not have any parameters or return type.
422+
let mut spans: Vec<_> = sig.decl.inputs.iter().map(|p| p.span).collect();
423+
if let FnRetTy::Ty(ref ret_ty) = sig.decl.output {
424+
spans.push(ret_ty.span);
425+
}
426+
427+
if !spans.is_empty() {
428+
let header_span = sig.header.span().unwrap_or(sig.span.shrink_to_lo());
429+
let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span());
430+
let padding = if header_span.is_empty() { "" } else { " " };
431+
432+
self.dcx().emit_err(errors::AbiCustomInvalidSignature {
433+
spans,
434+
symbol: ident.name,
435+
suggestion_span,
436+
padding,
437+
});
438+
}
439+
}
440+
373441
/// This ensures that items can only be `unsafe` (or unmarked) outside of extern
374442
/// blocks.
375443
///
@@ -1005,7 +1073,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10051073
if abi.is_none() {
10061074
self.handle_missing_abi(*extern_span, item.id);
10071075
}
1008-
self.with_in_extern_mod(*safety, |this| {
1076+
1077+
let extern_abi = abi.and_then(|abi| ExternAbi::from_str(abi.symbol.as_str()).ok());
1078+
self.with_in_extern_mod(*safety, extern_abi, |this| {
10091079
visit::walk_item(this, item);
10101080
});
10111081
self.extern_mod_span = old_item;
@@ -1145,6 +1215,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11451215
self.check_foreign_fn_bodyless(*ident, body.as_deref());
11461216
self.check_foreign_fn_headerless(sig.header);
11471217
self.check_foreign_item_ascii_only(*ident);
1218+
if self.extern_mod_abi == Some(ExternAbi::Custom) {
1219+
self.check_custom_abi(FnCtxt::Foreign, ident, sig);
1220+
}
11481221
}
11491222
ForeignItemKind::TyAlias(box TyAlias {
11501223
defaultness,
@@ -1352,6 +1425,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13521425
self.check_item_safety(span, safety);
13531426
}
13541427

1428+
if let FnKind::Fn(ctxt, _, fun) = fk
1429+
&& let Extern::Explicit(str_lit, _) = fun.sig.header.ext
1430+
&& let Ok(ExternAbi::Custom) = ExternAbi::from_str(str_lit.symbol.as_str())
1431+
{
1432+
self.check_custom_abi(ctxt, &fun.ident, &fun.sig);
1433+
}
1434+
13551435
self.check_c_variadic_type(fk);
13561436

13571437
// Functions cannot both be `const async` or `const gen`
@@ -1703,6 +1783,7 @@ pub fn check_crate(
17031783
outer_impl_trait_span: None,
17041784
disallow_tilde_const: Some(TildeConstReason::Item),
17051785
extern_mod_safety: None,
1786+
extern_mod_abi: None,
17061787
lint_node_id: CRATE_NODE_ID,
17071788
is_sdylib_interface,
17081789
lint_buffer: lints,

0 commit comments

Comments
 (0)