Skip to content

Rollup of 10 pull requests #142878

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 23 commits into from
Jun 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1d41c2c
Merge unboxed trait object error suggestion into regular dyn incompat…
oli-obk Jun 13, 2025
6d04085
Add a warning to LateContext::get_def_path
blyxyas Jun 16, 2025
6809ec1
Factor out seen_comma variable
camsteffen Jun 20, 2025
26a6b55
Recover from semicolon field separator
camsteffen Jun 20, 2025
8e9552a
Add a few inline directives in rustc_serialize.
cjgillot Jun 21, 2025
b1d1812
Implement DesugaringKind::FormatLiteral
mejrs Jun 16, 2025
29ce695
Stop dbg! macro yapping about format modifiers
mejrs Jun 17, 2025
2ddbe39
remove allow(dead_code) leftovers from serial/parallel compiler
klensy Jun 22, 2025
d092dc9
remove few from bootstrap too
klensy Jun 22, 2025
fdb76e2
Turn a comment that looks like a docstring into a docstring
ada4a Jun 19, 2025
b24df42
Port `#[must_use]` to new attribute parsing infrastructure
JonathanBrouwer Jun 22, 2025
75674e2
cranelift: fix target feature name type: "fxsr"
marxin Jun 22, 2025
90524da
Document why tidy checks if `eslint` is installed via `npm`
yotamofek Jun 22, 2025
3714263
Rollup merge of #142458 - oli-obk:dyn-incompat, r=compiler-errors
GuillaumeGomez Jun 22, 2025
cab65ef
Rollup merge of #142593 - blyxyas:improve-docs-itty-bitty-change, r=c…
GuillaumeGomez Jun 22, 2025
7bed341
Rollup merge of #142594 - mejrs:new_desugaring, r=chenyukang
GuillaumeGomez Jun 22, 2025
a9a0753
Rollup merge of #142740 - ada4a:is-destruct-assignment-desugaring, r=…
GuillaumeGomez Jun 22, 2025
2681bb0
Rollup merge of #142780 - JonathanBrouwer:must_use_new_attr, r=jdonsz…
GuillaumeGomez Jun 22, 2025
194e58c
Rollup merge of #142798 - camsteffen:recover-semi, r=compiler-errors
GuillaumeGomez Jun 22, 2025
0f89e61
Rollup merge of #142856 - cjgillot:inline-serialize, r=petrochenkov
GuillaumeGomez Jun 22, 2025
f1fa46d
Rollup merge of #142868 - klensy:dc, r=oli-obk
GuillaumeGomez Jun 22, 2025
1474a0f
Rollup merge of #142874 - marxin:cranelift-typo-fix, r=bjorn3
GuillaumeGomez Jun 22, 2025
8da1a62
Rollup merge of #142877 - yotamofek:pr/rustdoc/comment-eslint-install…
GuillaumeGomez Jun 22, 2025
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
8 changes: 8 additions & 0 deletions compiler/rustc_ast/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ pub struct FormatArgs {
///
/// Generally only useful for lints that care about the raw bytes the user wrote.
pub uncooked_fmt_str: (LitKind, Symbol),
/// Was the format literal written in the source?
/// - `format!("boo")` => true,
/// - `format!(concat!("b", "o", "o"))` => false,
/// - `format!(include_str!("boo.txt"))` => false,
///
/// If it wasn't written in the source then we have to be careful with spans pointing into it
/// and suggestions about rewriting it.
pub is_source_literal: bool,
}

/// A piece of a format template string.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,7 @@ macro_rules! common_visitor_and_walkers {

// FIXME: visit the template exhaustively.
pub fn walk_format_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, fmt: &$($lt)? $($mut)? FormatArgs) -> V::Result {
let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt;
let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _, is_source_literal: _ } = fmt;
let args = $(${ignore($mut)} arguments.all_args_mut())? $(${ignore($lt)} arguments.all_args())? ;
for FormatArgument { kind, expr } in args {
match kind {
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_ast_lowering/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_ast::*;
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_session::config::FmtDebug;
use rustc_span::{Ident, Span, Symbol, sym};
use rustc_span::{DesugaringKind, Ident, Span, Symbol, sym};

use super::LoweringContext;

Expand All @@ -14,6 +14,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
// format_args!() had any arguments _before_ flattening/inlining.
let allow_const = fmt.arguments.all_args().is_empty();
let mut fmt = Cow::Borrowed(fmt);

let sp = self.mark_span_with_reason(
DesugaringKind::FormatLiteral { source: fmt.is_source_literal },
sp,
sp.ctxt().outer_expn_data().allow_internal_unstable,
);

if self.tcx.sess.opts.unstable_opts.flatten_format_args {
fmt = flatten_format_args(fmt);
fmt = self.inline_literals(fmt);
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ pub enum AttributeKind {
/// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
MayDangle(Span),

/// Represents `#[must_use]`.
MustUse {
span: Span,
/// must_use can optionally have a reason: `#[must_use = "reason this must be used"]`
reason: Option<Symbol>,
},

/// Represents `#[optimize(size|speed)]`
Optimize(OptimizeAttr, Span),

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub(crate) mod confusables;
pub(crate) mod deprecation;
pub(crate) mod inline;
pub(crate) mod lint_helpers;
pub(crate) mod must_use;
pub(crate) mod repr;
pub(crate) mod semantics;
pub(crate) mod stability;
Expand Down
40 changes: 40 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/must_use.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Symbol, sym};

use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;

pub(crate) struct MustUseParser;

impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
const PATH: &[Symbol] = &[sym::must_use];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
Some(AttributeKind::MustUse {
span: cx.attr_span,
reason: match args {
ArgParser::NoArgs => None,
ArgParser::NameValue(name_value) => name_value.value_as_str(),
ArgParser::List(_) => {
let suggestions =
<Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "must_use");
cx.emit_err(session_diagnostics::MustUseIllFormedAttributeInput {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
),
span: cx.attr_span,
});
return None;
}
},
})
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::deprecation::DeprecationParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
use crate::attributes::must_use::MustUseParser;
use crate::attributes::repr::{AlignParser, ReprParser};
use crate::attributes::semantics::MayDangleParser;
use crate::attributes::stability::{
Expand Down Expand Up @@ -112,6 +113,7 @@ attribute_parsers!(
Single<DeprecationParser>,
Single<InlineParser>,
Single<MayDangleParser>,
Single<MustUseParser>,
Single<OptimizeParser>,
Single<PubTransparentParser>,
Single<RustcForceInlineParser>,
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,15 @@ pub(crate) struct IllFormedAttributeInput {
pub suggestions: DiagArgValue,
}

#[derive(Diagnostic)]
#[diag(attr_parsing_ill_formed_attribute_input)]
pub(crate) struct MustUseIllFormedAttributeInput {
#[primary_span]
pub span: Span,
pub num_suggestions: usize,
pub suggestions: DiagArgValue,
}

#[derive(Diagnostic)]
#[diag(attr_parsing_stability_outside_std, code = E0734)]
pub(crate) struct StabilityOutsideStd {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ fn make_format_args(
template,
arguments: args,
uncooked_fmt_str,
is_source_literal,
}))
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" {
// x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
vec![sym::fsxr, sym::sse, sym::sse2, Symbol::intern("x87")]
vec![sym::fxsr, sym::sse, sym::sse2, Symbol::intern("x87")]
} else if sess.target.arch == "aarch64" {
match &*sess.target.os {
"none" => vec![],
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_data_structures/src/sync/lock.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! This module implements a lock which only uses synchronization if `might_be_dyn_thread_safe` is true.
//! It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync` traits.

#![allow(dead_code)]

use std::fmt;

#[derive(Clone, Copy, PartialEq)]
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_data_structures/src/sync/parallel.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! This module defines parallel operations that are implemented in
//! one way for the serial compiler, and another way the parallel compiler.

#![allow(dead_code)]

use std::any::Any;
use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};

Expand Down
66 changes: 0 additions & 66 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,6 @@ fn check_trait_item<'tcx>(
_ => (None, trait_item.span),
};

check_dyn_incompatible_self_trait_by_name(tcx, trait_item);

// Check that an item definition in a subtrait is shadowing a supertrait item.
lint_item_shadowing_supertrait_item(tcx, def_id);

Expand Down Expand Up @@ -832,70 +830,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
}
}

fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
match ty.kind {
hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
[s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
_ => false,
},
_ => false,
}
}

/// Detect when a dyn-incompatible trait is referring to itself in one of its associated items.
///
/// In such cases, suggest using `Self` instead.
fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) {
let (trait_ident, trait_def_id) =
match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(item.hir_id()).def_id) {
hir::Node::Item(item) => match item.kind {
hir::ItemKind::Trait(_, _, ident, ..) => (ident, item.owner_id),
_ => return,
},
_ => return,
};
let mut trait_should_be_self = vec![];
match &item.kind {
hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty))
if could_be_self(trait_def_id.def_id, ty) =>
{
trait_should_be_self.push(ty.span)
}
hir::TraitItemKind::Fn(sig, _) => {
for ty in sig.decl.inputs {
if could_be_self(trait_def_id.def_id, ty) {
trait_should_be_self.push(ty.span);
}
}
match sig.decl.output {
hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => {
trait_should_be_self.push(ty.span);
}
_ => {}
}
}
_ => {}
}
if !trait_should_be_self.is_empty() {
if tcx.is_dyn_compatible(trait_def_id) {
return;
}
let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect();
tcx.dcx()
.struct_span_err(
trait_should_be_self,
"associated item referring to unboxed trait object for its own trait",
)
.with_span_label(trait_ident.span, "in this trait")
.with_multipart_suggestion(
"you might have meant to use `Self` to refer to the implementing type",
sugg,
Applicability::MachineApplicable,
)
.emit();
}
}

fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) {
let item_name = tcx.item_name(trait_item_def_id.to_def_id());
let trait_def_id = tcx.local_parent(trait_item_def_id);
Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_wf_check.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use rustc_hir::def::DefKind;
use rustc_hir::intravisit::{self, Visitor, VisitorExt};
use rustc_hir::{self as hir, AmbigArg, ForeignItem, ForeignItemKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_infer::traits::{ObligationCause, ObligationCauseCode, WellFormedLoc};
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions};
Expand Down Expand Up @@ -107,6 +108,17 @@ fn diagnostic_hir_wf_check<'tcx>(
// over less-specific types (e.g. `Option<MyStruct<u8>>`)
if self.depth >= self.cause_depth {
self.cause = Some(error.obligation.cause);
if let hir::TyKind::TraitObject(..) = ty.kind {
if let DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocFn =
self.tcx.def_kind(self.def_id)
{
self.cause = Some(ObligationCause::new(
ty.span,
self.def_id,
ObligationCauseCode::DynCompatible(ty.span),
));
}
}
self.cause_depth = self.depth
}
}
Expand Down
25 changes: 12 additions & 13 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1110,27 +1110,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

// Returns whether the given expression is a destruct assignment desugaring.
// For example, `(a, b) = (1, &2);`
// Here we try to find the pattern binding of the expression,
// `default_binding_modes` is false only for destruct assignment desugaring.
/// Returns whether the given expression is a destruct assignment desugaring.
/// For example, `(a, b) = (1, &2);`
/// Here we try to find the pattern binding of the expression,
/// `default_binding_modes` is false only for destruct assignment desugaring.
pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool {
if let hir::ExprKind::Path(hir::QPath::Resolved(
_,
hir::Path { res: hir::def::Res::Local(bind_hir_id), .. },
)) = expr.kind
{
let bind = self.tcx.hir_node(*bind_hir_id);
let parent = self.tcx.parent_hir_node(*bind_hir_id);
if let hir::Node::Pat(hir::Pat {
&& let bind = self.tcx.hir_node(*bind_hir_id)
&& let parent = self.tcx.parent_hir_node(*bind_hir_id)
&& let hir::Node::Pat(hir::Pat {
kind: hir::PatKind::Binding(_, _hir_id, _, _), ..
}) = bind
&& let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent
{
return true;
}
&& let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent
{
true
} else {
false
}
false
}

fn explain_self_literal(
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,15 @@ impl<'tcx> LateContext<'tcx> {

/// Gets the absolute path of `def_id` as a vector of `Symbol`.
///
/// Note that this is kinda expensive because it has to
/// travel the tree and pretty-print. Use sparingly.
///
/// If you're trying to match for an item given by its path, use a
/// diagnostic item. If you're only interested in given sections, use more
/// specific functions, such as [`TyCtxt::crate_name`]
///
/// FIXME: It would be great if this could be optimized.
///
/// # Examples
///
/// ```rust,ignore (no context or def id available)
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::iter;

use rustc_ast::util::{classify, parser};
use rustc_ast::{self as ast, ExprKind, HasAttrs as _, StmtKind};
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_errors::{MultiSpan, pluralize};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
Expand Down Expand Up @@ -368,10 +369,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
}

fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> {
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
if let Some(reason) = find_attr!(
cx.tcx.get_all_attrs(def_id),
AttributeKind::MustUse { reason, .. } => reason
) {
// check for #[must_use = "..."]
let reason = attr.value_str();
Some(MustUsePath::Def(span, def_id, reason))
Some(MustUsePath::Def(span, def_id, *reason))
} else {
None
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ pub enum ObligationCauseCode<'tcx> {

RustCall,

DynCompatible(Span),

/// Obligations to prove that a `Drop` or negative auto trait impl is not stronger than
/// the ADT it's being implemented for.
AlwaysApplicableImpl,
Expand Down
Loading
Loading