Skip to content

Commit b6db00e

Browse files
committed
Auto merge of #157492 - JonathanBrouwer:rollup-dC3NNN3, r=JonathanBrouwer
Rollup of 12 pull requests Successful merges: - #157467 (stdarch subtree update) - #155453 (apply Cortex-A53 errata 843419 mitigation to the AArch64 Linux targets) - #156798 (delegation: do not always generate first argument) - #157016 (add `extern "tail"` calling convention) - #157450 (mark `Encode`, `Decode`, `Mark` impls as `#[inline]`) - #148183 (rustdoc: Test & document `test_harness` code block attribute) - #157190 (Silence recursive RUSTC_LOG_FORMAT_JSON messages) - #157470 (Avoid ICE when emitting TargetMachine config errors) - #157474 (Forbid optimize(none) with inline(always) or inline.) - #157475 (Add a smoke test for the optimize attribute.) - #157479 (Warn when `#[macro_use]` or `#[macro_escape]` is used on the crate root) - #157486 (Remove unused attributes from issue-29485.rs.) Failed merges: - #157485 (Rename `errors.rs` file to `diagnostics.rs`)
2 parents ac6f3a3 + 0a37e80 commit b6db00e

120 files changed

Lines changed: 6988 additions & 1802 deletions

File tree

Some content is hidden

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

compiler/rustc_abi/src/canon_abi.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub enum CanonAbi {
2828
Rust,
2929
RustCold,
3030
RustPreserveNone,
31+
RustTail,
3132

3233
/// An ABI that rustc does not know how to call or define.
3334
Custom,
@@ -59,7 +60,10 @@ pub enum CanonAbi {
5960
impl CanonAbi {
6061
pub fn is_rustic_abi(self) -> bool {
6162
match self {
62-
CanonAbi::Rust | CanonAbi::RustCold | CanonAbi::RustPreserveNone => true,
63+
CanonAbi::Rust
64+
| CanonAbi::RustCold
65+
| CanonAbi::RustPreserveNone
66+
| CanonAbi::RustTail => true,
6367
CanonAbi::C
6468
| CanonAbi::Custom
6569
| CanonAbi::Swift
@@ -81,6 +85,7 @@ impl fmt::Display for CanonAbi {
8185
CanonAbi::Rust => ExternAbi::Rust,
8286
CanonAbi::RustCold => ExternAbi::RustCold,
8387
CanonAbi::RustPreserveNone => ExternAbi::RustPreserveNone,
88+
CanonAbi::RustTail => ExternAbi::RustTail,
8489
CanonAbi::Custom => ExternAbi::Custom,
8590
CanonAbi::Swift => ExternAbi::Swift,
8691
CanonAbi::Arm(arm_call) => match arm_call {

compiler/rustc_abi/src/extern_abi.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ pub enum ExternAbi {
4949
/// forcing callers to save all registers.
5050
RustPreserveNone,
5151

52+
/// Ensures that calls in tail position can always be optimized into a jump.
53+
///
54+
/// This ABI is not stable, and relies on LLVM implementation details.
55+
RustTail,
56+
5257
/// Unstable impl detail that directly uses Rust types to describe the ABI to LLVM.
5358
/// Even normally-compatible Rust types can become ABI-incompatible with this ABI!
5459
Unadjusted,
@@ -205,6 +210,7 @@ abi_impls! {
205210
System { unwind: true } =><= "system-unwind",
206211
SysV64 { unwind: false } =><= "sysv64",
207212
SysV64 { unwind: true } =><= "sysv64-unwind",
213+
RustTail =><= "tail",
208214
Thiscall { unwind: false } =><= "thiscall",
209215
Thiscall { unwind: true } =><= "thiscall-unwind",
210216
Unadjusted =><= "unadjusted",
@@ -280,7 +286,7 @@ impl ExternAbi {
280286
/// - are subject to change between compiler versions
281287
pub fn is_rustic_abi(self) -> bool {
282288
use ExternAbi::*;
283-
matches!(self, Rust | RustCall | RustCold | RustPreserveNone)
289+
matches!(self, Rust | RustCall | RustCold | RustPreserveNone | RustTail)
284290
}
285291

286292
/// Returns whether the ABI supports C variadics. This only controls whether we allow *imports*
@@ -354,6 +360,7 @@ impl ExternAbi {
354360
| Self::SysV64 { .. }
355361
| Self::Win64 { .. }
356362
| Self::RustPreserveNone
363+
| Self::RustTail
357364
| Self::Swift => true,
358365
}
359366
}

compiler/rustc_ast/src/ast.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3908,6 +3908,13 @@ pub struct EiiImpl {
39083908
pub is_default: bool,
39093909
}
39103910

3911+
#[derive(Clone, Encodable, Decodable, Debug, Walkable, PartialEq, Eq)]
3912+
pub enum DelegationSource {
3913+
Single,
3914+
List,
3915+
Glob,
3916+
}
3917+
39113918
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
39123919
pub struct Delegation {
39133920
/// Path resolution id.
@@ -3918,7 +3925,7 @@ pub struct Delegation {
39183925
pub rename: Option<Ident>,
39193926
pub body: Option<Box<Block>>,
39203927
/// The item was expanded from a glob delegation item.
3921-
pub from_glob: bool,
3928+
pub source: DelegationSource,
39223929
}
39233930

39243931
impl Delegation {

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ macro_rules! common_visitor_and_walkers {
431431
Delegation,
432432
DelegationMac,
433433
DelegationSuffixes,
434+
DelegationSource,
434435
DelimArgs,
435436
DelimSpan,
436437
EnumDef,

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,29 @@
3737
//! also be emitted during HIR ty lowering.
3838
3939
use std::iter;
40+
use std::ops::ControlFlow;
4041

4142
use ast::visit::Visitor;
4243
use hir::def::{DefKind, Res};
4344
use hir::{BodyId, HirId};
4445
use rustc_abi::ExternAbi;
4546
use rustc_ast as ast;
47+
use rustc_ast::node_id::NodeMap;
4648
use rustc_ast::*;
4749
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
4850
use rustc_hir::attrs::{AttributeKind, InlineAttr};
4951
use rustc_hir::def_id::{DefId, LocalDefId};
5052
use rustc_hir::{self as hir, FnDeclFlags};
5153
use rustc_middle::span_bug;
52-
use rustc_middle::ty::{Asyncness, TyCtxt};
54+
use rustc_middle::ty::{Asyncness, PerOwnerResolverData, TyCtxt};
5355
use rustc_span::symbol::kw;
5456
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
5557

5658
use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults};
57-
use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee};
59+
use crate::errors::{
60+
CycleInDelegationSignatureResolution, DelegationAttemptedBlockWithDefsDeletion,
61+
DelegationBlockSpecifiedWhenNoParams, UnresolvedDelegationCallee,
62+
};
5863
use crate::{
5964
AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
6065
ResolverAstLoweringExt, index_crate,
@@ -198,10 +203,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
198203

199204
let (param_count, c_variadic) = self.param_count(sig_id);
200205

206+
if !self.check_block_soundness(delegation, sig_id, is_method, param_count) {
207+
return self.generate_delegation_error(span, delegation);
208+
}
209+
201210
let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method);
202211

203212
let (body_id, call_expr_id) =
204-
self.lower_delegation_body(delegation, is_method, param_count, &mut generics, span);
213+
self.lower_delegation_body(delegation, sig_id, param_count, &mut generics, span);
205214

206215
let decl = self.lower_delegation_decl(
207216
sig_id,
@@ -227,6 +236,82 @@ impl<'hir> LoweringContext<'_, 'hir> {
227236
DelegationResults { body_id, sig, ident, generics }
228237
}
229238

239+
fn check_block_soundness(
240+
&self,
241+
delegation: &Delegation,
242+
sig_id: DefId,
243+
is_method: bool,
244+
param_count: usize,
245+
) -> bool {
246+
let Some(block) = delegation.body.as_ref() else { return true };
247+
let should_generate_block = self.should_generate_block(delegation, sig_id, is_method);
248+
249+
// Report an error if user has explicitly specified delegation's target expression
250+
// in a single delegation when reused function has no params.
251+
if param_count == 0 && should_generate_block {
252+
self.dcx().emit_err(DelegationBlockSpecifiedWhenNoParams { span: block.span });
253+
return false;
254+
}
255+
256+
struct DefinitionsFinder<'a> {
257+
all_owners: &'a NodeMap<PerOwnerResolverData<'a>>,
258+
// `self.owner.node_id_to_def_id`
259+
nested_def_ids: &'a NodeMap<LocalDefId>,
260+
}
261+
262+
impl<'a> ast::visit::Visitor<'a> for DefinitionsFinder<'a> {
263+
type Result = ControlFlow<()>;
264+
265+
fn visit_id(&mut self, id: NodeId) -> Self::Result {
266+
/*
267+
(from `tests\ui\delegation\target-expr-removal-defs-inside.rs`):
268+
```rust
269+
reuse impl Trait for S1 {
270+
some::path::<{ fn foo() {} }>::xd();
271+
fn foo() {}
272+
self.0
273+
}
274+
```
275+
276+
Constant from unresolved path will be in `nested_owners`,
277+
`fn foo() {}` will not be in `nested_owners` but will be in `owners`,
278+
both have `LocalDefId`, so we check those two maps.
279+
*/
280+
match self.all_owners.contains_key(&id) || self.nested_def_ids.contains_key(&id) {
281+
true => ControlFlow::Break(()),
282+
false => ControlFlow::Continue(()),
283+
}
284+
}
285+
}
286+
287+
let mut collector = DefinitionsFinder {
288+
all_owners: &self.resolver.owners,
289+
nested_def_ids: &self.owner.node_id_to_def_id,
290+
};
291+
292+
let contains_defs = collector.visit_block(block).is_break();
293+
294+
// If there are definitions inside and we can't delete target expression, so report an error.
295+
// FIXME(fn_delegation): support deletion of target expression with defs inside.
296+
if !should_generate_block && contains_defs {
297+
self.dcx().emit_err(DelegationAttemptedBlockWithDefsDeletion { span: block.span });
298+
return false;
299+
}
300+
301+
true
302+
}
303+
304+
fn should_generate_block(
305+
&self,
306+
delegation: &Delegation,
307+
sig_id: DefId,
308+
is_method: bool,
309+
) -> bool {
310+
is_method
311+
|| matches!(self.tcx.def_kind(sig_id), DefKind::Fn)
312+
|| matches!(delegation.source, DelegationSource::Single)
313+
}
314+
230315
fn add_attrs_if_needed(&mut self, span: Span, sig_id: DefId) {
231316
let new_attrs =
232317
self.create_new_attrs(ATTRS_ADDITIONS, span, sig_id, self.attrs.get(&PARENT_ID));
@@ -415,7 +500,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
415500
fn lower_delegation_body(
416501
&mut self,
417502
delegation: &Delegation,
418-
is_method: bool,
503+
sig_id: DefId,
419504
param_count: usize,
420505
generics: &mut GenericsGenerationResults<'hir>,
421506
span: Span,
@@ -428,6 +513,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
428513
let mut args: Vec<hir::Expr<'_>> = Vec::with_capacity(param_count);
429514
let mut stmts: &[hir::Stmt<'hir>] = &[];
430515

516+
let is_method = this.is_method(sig_id, span);
517+
431518
for idx in 0..param_count {
432519
let (param, pat_node_id) = this.generate_param(is_method, idx, span);
433520
parameters.push(param);
@@ -437,6 +524,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
437524

438525
let arg = if let Some(block) = block
439526
&& idx == 0
527+
&& this.should_generate_block(delegation, sig_id, is_method)
440528
{
441529
let mut self_resolver = SelfResolver {
442530
ctxt: this,
@@ -467,17 +555,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
467555
args.push(arg);
468556
}
469557

470-
// If we have no params in signature function but user still wrote some code in
471-
// delegation body, then add this code as first arg, eventually an error will be shown,
472-
// also nested delegations may need to access information about this code (#154332),
473-
// so it is better to leave this code as opposed to bodies of extern functions,
474-
// which are completely erased from existence.
475-
if param_count == 0
476-
&& let Some(block) = block
477-
{
478-
args.push(this.lower_block_expr(&block));
479-
}
480-
481558
let (final_expr, hir_id) =
482559
this.finalize_body_lowering(delegation, stmts, args, generics, span);
483560

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,17 @@ pub(crate) struct CycleInDelegationSignatureResolution {
535535
#[primary_span]
536536
pub span: Span,
537537
}
538+
539+
#[derive(Diagnostic)]
540+
#[diag("delegation's target expression is specified for function with no params")]
541+
pub(crate) struct DelegationBlockSpecifiedWhenNoParams {
542+
#[primary_span]
543+
pub span: Span,
544+
}
545+
546+
#[derive(Diagnostic)]
547+
#[diag("attempted to delete delegation's target expression that contains definitions inside")]
548+
pub(crate) struct DelegationAttemptedBlockWithDefsDeletion {
549+
#[primary_span]
550+
pub span: Span,
551+
}

compiler/rustc_ast_lowering/src/stability.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
100100
feature: sym::rust_preserve_none_cc,
101101
explain: GateReason::Experimental,
102102
}),
103+
ExternAbi::RustTail => {
104+
Err(UnstableAbi { abi, feature: sym::rust_tail_cc, explain: GateReason::Experimental })
105+
}
103106
ExternAbi::RustInvalid => {
104107
Err(UnstableAbi { abi, feature: sym::rustc_attrs, explain: GateReason::ImplDetail })
105108
}

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ impl<'a> AstValidator<'a> {
424424
| CanonAbi::Rust
425425
| CanonAbi::RustCold
426426
| CanonAbi::RustPreserveNone
427+
| CanonAbi::RustTail
427428
| CanonAbi::Swift
428429
| CanonAbi::Arm(_)
429430
| CanonAbi::X86(_) => { /* nothing to check */ }

compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ const MACRO_USE_TEMPLATE: AttributeTemplate = template!(
3535
const MACRO_USE_ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
3636
Allow(Target::Mod),
3737
Allow(Target::ExternCrate),
38-
Allow(Target::Crate),
3938
Error(Target::WherePredicate),
4039
]);
4140

compiler/rustc_codegen_cranelift/src/abi/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ pub(crate) fn conv_to_call_conv(
5555
match c {
5656
CanonAbi::Rust | CanonAbi::RustCold | CanonAbi::C => default_call_conv,
5757

58-
// Cranelift doesn't currently have anything for this.
59-
CanonAbi::RustPreserveNone => default_call_conv,
58+
CanonAbi::RustPreserveNone | CanonAbi::RustTail => {
59+
sess.dcx().fatal(format!("call conv {c:?} is LLVM-specific"))
60+
}
6061

6162
// Functions with this calling convention can only be called from assembly, but it is
6263
// possible to declare an `extern "custom"` block, so the backend still needs a calling
@@ -71,7 +72,7 @@ pub(crate) fn conv_to_call_conv(
7172
},
7273

7374
CanonAbi::Interrupt(_) | CanonAbi::Arm(_) | CanonAbi::Swift => {
74-
sess.dcx().fatal("call conv {c:?} is not yet implemented")
75+
sess.dcx().fatal(format!("call conv {c:?} is not yet implemented"))
7576
}
7677
CanonAbi::GpuKernel => {
7778
unreachable!("tried to use {c:?} call conv which only exists on an unsupported target")

0 commit comments

Comments
 (0)