Skip to content

Rollup of 6 pull requests #139169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Mar 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ impl DefKind {
DefKind::GlobalAsm => DefPathData::GlobalAsm,
DefKind::Impl { .. } => DefPathData::Impl,
DefKind::Closure => DefPathData::Closure,
DefKind::SyntheticCoroutineBody => DefPathData::Closure,
DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody,
}
}

Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_hir/src/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ pub enum DefPathData {
/// An existential `impl Trait` type node.
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
OpaqueTy,
/// A synthetic body for a coroutine's by-move body.
SyntheticCoroutineBody,
}

impl Definitions {
Expand Down Expand Up @@ -415,8 +417,16 @@ impl DefPathData {

ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),

Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
| OpaqueTy => None,
Impl
| ForeignMod
| CrateRoot
| Use
| GlobalAsm
| Closure
| Ctor
| AnonConst
| OpaqueTy
| SyntheticCoroutineBody => None,
}
}

Expand All @@ -441,6 +451,7 @@ impl DefPathData {
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ impl CodegenFnAttrs {
/// * `#[no_mangle]` is present
/// * `#[export_name(...)]` is present
/// * `#[linkage]` is present
///
/// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
pub fn contains_extern_indicator(&self) -> bool {
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
|| self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ impl<'tcx> MonoItem<'tcx> {

// If the function is #[naked] or contains any other attribute that requires exactly-once
// instantiation:
// We emit an unused_attributes lint for this case, which should be kept in sync if possible.
let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id());
if codegen_fn_attrs.contains_extern_indicator()
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_middle/src/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,16 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>),
/// parameter environment.
#[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)]
pub enum SelectionCandidate<'tcx> {
/// A built-in implementation for the `Sized` trait. This is preferred
/// over all other candidates.
SizedCandidate {
has_nested: bool,
},

/// A builtin implementation for some specific traits, used in cases
/// where we cannot rely an ordinary library implementations.
///
/// The most notable examples are `sized`, `Copy` and `Clone`. This is also
/// The most notable examples are `Copy` and `Clone`. This is also
/// used for the `DiscriminantKind` and `Pointee` trait, both of which have
/// an associated type.
BuiltinCandidate {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1930,10 +1930,10 @@ impl<'tcx> TyCtxt<'tcx> {
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
// comp. engine itself.
//
// This call also writes to the value of `source_span` and `expn_that_defined` queries.
// This call also writes to the value of the `source_span` query.
// This is fine because:
// - those queries are `eval_always` so we won't miss their result changing;
// - this write will have happened before these queries are called.
// - that query is `eval_always` so we won't miss its result changing;
// - this write will have happened before that query is called.
let def_id = self.untracked.definitions.write().create_def(parent, data);

// This function modifies `self.definitions` using a side-effect.
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_middle/src/ty/print/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ pub trait Printer<'tcx>: Sized {

match key.disambiguated_data.data {
DefPathData::Closure => {
// FIXME(async_closures): This is somewhat ugly.
// We need to additionally print the `kind` field of a closure if
// We need to additionally print the `kind` field of a coroutine if
// it is desugared from a coroutine-closure.
if let Some(hir::CoroutineKind::Desugared(
_,
Expand All @@ -156,6 +155,10 @@ pub trait Printer<'tcx>: Sized {
// Closures' own generics are only captures, don't print them.
}
}
DefPathData::SyntheticCoroutineBody => {
// Synthetic coroutine bodies have no distinct generics, since like
// closures they're all just internal state of the coroutine.
}
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
// Anon consts doesn't have their own generics, and inline consts' own
// generics are their inferred types, so don't print them.
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,16 +810,16 @@ pub(crate) enum WrapInParentheses {

#[derive(Diagnostic)]
#[diag(parse_array_brackets_instead_of_braces)]
pub(crate) struct ArrayBracketsInsteadOfSpaces {
pub(crate) struct ArrayBracketsInsteadOfBraces {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sub: ArrayBracketsInsteadOfSpacesSugg,
pub sub: ArrayBracketsInsteadOfBracesSugg,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")]
pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
pub(crate) struct ArrayBracketsInsteadOfBracesSugg {
#[suggestion_part(code = "[")]
pub left: Span,
#[suggestion_part(code = "]")]
Expand Down
61 changes: 52 additions & 9 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2200,7 +2200,9 @@ impl<'a> Parser<'a> {
}

fn is_array_like_block(&mut self) -> bool {
self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
&& self
.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
&& self.look_ahead(2, |t| t == &token::Comma)
&& self.look_ahead(3, |t| t.can_begin_expr())
}
Expand All @@ -2212,9 +2214,9 @@ impl<'a> Parser<'a> {
let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) {
Ok(arr) => {
let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfSpaces {
let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfBraces {
span: arr.span,
sub: errors::ArrayBracketsInsteadOfSpacesSugg {
sub: errors::ArrayBracketsInsteadOfBracesSugg {
left: lo,
right: snapshot.prev_token.span,
},
Expand Down Expand Up @@ -2337,7 +2339,8 @@ impl<'a> Parser<'a> {
let capture_clause = self.parse_capture_clause()?;
let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
let decl_hi = self.prev_token.span;
let mut body = match fn_decl.output {
let mut body = match &fn_decl.output {
// No return type.
FnRetTy::Default(_) => {
let restrictions =
self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
Expand All @@ -2349,11 +2352,8 @@ impl<'a> Parser<'a> {
Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?,
}
}
_ => {
// If an explicit return type is given, require a block to appear (RFC 968).
let body_lo = self.token.span;
self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
}
// Explicit return type (`->`) needs block `-> T { }`.
FnRetTy::Ty(ty) => self.parse_closure_block_body(ty.span)?,
};

match coroutine_kind {
Expand Down Expand Up @@ -2405,6 +2405,49 @@ impl<'a> Parser<'a> {
Ok(closure)
}

/// If an explicit return type is given, require a block to appear (RFC 968).
fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, P<Expr>> {
if self.may_recover()
&& self.token.can_begin_expr()
&& !matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
&& !self.token.is_whole_block()
{
let snapshot = self.create_snapshot_for_diagnostic();
let restrictions =
self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
let tok = self.token.clone();
match self.parse_expr_res(restrictions, AttrWrapper::empty()) {
Ok((expr, _)) => {
let descr = super::token_descr(&tok);
let mut diag = self
.dcx()
.struct_span_err(tok.span, format!("expected `{{`, found {descr}"));
diag.span_label(
ret_span,
"explicit return type requires closure body to be enclosed in braces",
);
diag.multipart_suggestion_verbose(
"wrap the expression in curly braces",
vec![
(expr.span.shrink_to_lo(), "{ ".to_string()),
(expr.span.shrink_to_hi(), " }".to_string()),
],
Applicability::MachineApplicable,
);
diag.emit();
return Ok(expr);
}
Err(diag) => {
diag.cancel();
self.restore_snapshot(snapshot);
}
}
}

let body_lo = self.token.span;
self.parse_expr_block(None, body_lo, BlockCheckMode::Default)
}

/// Parses an optional `move` or `use` prefix to a closure-like construct.
fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
if self.eat_keyword(exp!(Move)) {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ passes_inline_ignored_constants =
.warn = {-passes_previously_accepted}
.note = {-passes_see_issue(issue: "65833")}

passes_inline_ignored_for_exported =
`#[inline]` is ignored on externally exported functions
.help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`

passes_inline_ignored_function_prototype =
`#[inline]` is ignored on function prototypes

Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
});
}
}

// `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
if let Some(did) = hir_id.as_owner()
&& self.tcx.def_kind(did).has_codegen_attrs()
&& !matches!(attr.meta_item_list().as_deref(), Some([item]) if item.has_name(sym::never))
{
let attrs = self.tcx.codegen_fn_attrs(did);
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
if attrs.contains_extern_indicator() {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
errors::InlineIgnoredForExported {},
);
}
}
}

/// Checks that `#[coverage(..)]` is applied to a function/closure/method,
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,11 @@ pub(crate) struct OnlyHasEffectOn {
pub target_name: String,
}

#[derive(LintDiagnostic)]
#[diag(passes_inline_ignored_for_exported)]
#[help]
pub(crate) struct InlineIgnoredForExported {}

#[derive(Diagnostic)]
#[diag(passes_object_lifetime_err)]
pub(crate) struct ObjectLifetimeErr {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_query_system/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub struct MarkFrame<'a> {
parent: Option<&'a MarkFrame<'a>>,
}

#[derive(Debug)]
pub(super) enum DepNodeColor {
Red,
Green(DepNodeIndex),
Expand Down Expand Up @@ -909,7 +910,7 @@ impl<D: Deps> DepGraphData<D> {
self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);

if node_index.is_some() {
debug!("managed to MARK dependency {dep_dep_node:?} as green",);
debug!("managed to MARK dependency {dep_dep_node:?} as green");
return Some(());
}
}
Expand All @@ -930,7 +931,7 @@ impl<D: Deps> DepGraphData<D> {
return Some(());
}
Some(DepNodeColor::Red) => {
debug!("dependency {dep_dep_node:?} was red after forcing",);
debug!("dependency {dep_dep_node:?} was red after forcing");
return None;
}
None => {}
Expand All @@ -950,7 +951,7 @@ impl<D: Deps> DepGraphData<D> {
// invalid state will not be persisted to the
// incremental compilation cache because of
// compilation errors being present.
debug!("dependency {dep_dep_node:?} resulted in compilation error",);
debug!("dependency {dep_dep_node:?} resulted in compilation error");
return None;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
hir::definitions::DefPathData::Ctor => "c",
hir::definitions::DefPathData::AnonConst => "k",
hir::definitions::DefPathData::OpaqueTy => "i",
hir::definitions::DefPathData::SyntheticCoroutineBody => "s",
hir::definitions::DefPathData::CrateRoot
| hir::definitions::DefPathData::Use
| hir::definitions::DefPathData::GlobalAsm
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_symbol_mangling/src/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ pub(super) fn mangle<'tcx>(
loop {
let key = tcx.def_key(ty_def_id);
match key.disambiguated_data.data {
DefPathData::TypeNs(_) | DefPathData::ValueNs(_) | DefPathData::Closure => {
DefPathData::TypeNs(_)
| DefPathData::ValueNs(_)
| DefPathData::Closure
| DefPathData::SyntheticCoroutineBody => {
instance_ty = tcx.type_of(ty_def_id).instantiate_identity();
debug!(?instance_ty);
break;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
DefPathData::Ctor => 'c',
DefPathData::AnonConst => 'k',
DefPathData::OpaqueTy => 'i',
DefPathData::SyntheticCoroutineBody => 's',

// These should never show up as `path_append` arguments.
DefPathData::CrateRoot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// `Pointee` is automatically implemented for every type.
candidates.vec.push(BuiltinCandidate { has_nested: false });
} else if tcx.is_lang_item(def_id, LangItem::Sized) {
// Sized is never implementable by end-users, it is
// always automatically computed.
let sized_conditions = self.sized_conditions(obligation);
self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
self.assemble_builtin_sized_candidate(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::Unsize) {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::Destruct) {
Expand Down Expand Up @@ -1061,6 +1058,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Assembles the trait which are built-in to the language itself:
/// `Copy`, `Clone` and `Sized`.
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_builtin_sized_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
match self.sized_conditions(obligation) {
BuiltinImplConditions::Where(nested) => {
candidates
.vec
.push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() });
}
BuiltinImplConditions::None => {}
BuiltinImplConditions::Ambiguous => {
candidates.ambiguous = true;
}
}
}

/// Assembles the trait which are built-in to the language itself:
/// e.g. `Copy` and `Clone`.
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_builtin_bound_candidates(
&mut self,
conditions: BuiltinImplConditions<'tcx>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
candidate: SelectionCandidate<'tcx>,
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
let mut impl_src = match candidate {
SizedCandidate { has_nested } => {
let data = self.confirm_builtin_candidate(obligation, has_nested);
ImplSource::Builtin(BuiltinImplSource::Misc, data)
}

BuiltinCandidate { has_nested } => {
let data = self.confirm_builtin_candidate(obligation, has_nested);
ImplSource::Builtin(BuiltinImplSource::Misc, data)
Expand Down
Loading
Loading