Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
70dd3bc
Remove rustc_on_unimplemented's `append_const_msg`
mejrs Mar 31, 2026
8c04367
Refactor `get_standard_error_message`
mejrs Mar 31, 2026
b6bdfed
Avoid needless clone.
mejrs Mar 31, 2026
62db1eb
Improve shadowed private field diagnostics
chenyukang Mar 31, 2026
257d655
extend note for private field to more diagnostics
chenyukang Mar 31, 2026
86f99d2
extend note for private field to method call
chenyukang Mar 31, 2026
ce46df2
Sort shadowed field notes by source order
chenyukang Apr 2, 2026
98d259b
add min_adt_const_params gate tests
zedddie Mar 8, 2026
72fbd1c
implement `min_adt_const_params` feature
zedddie Mar 9, 2026
ae899cc
Clarify private field autoderef notes
chenyukang Apr 2, 2026
707c0d0
Add comment to borrow-checker
theemathas Apr 3, 2026
a2f7f3c
ty_utils: lower tuples to `ScalableVector` repr
davidtwco Feb 19, 2026
4fbcb03
cg_llvm: `sve_tuple_{create,get,set}` intrinsics
davidtwco Feb 19, 2026
a24ee03
cg_llvm/debuginfo: scalable vectors
davidtwco Feb 26, 2026
957320c
cg_llvm: `sve_cast` intrinsic
davidtwco Feb 28, 2026
c3d9f99
Remove an unused `StableHash` impl.
nnethercote Apr 3, 2026
2bf76b4
Add a regression test for an escaping late-bound region ICE during ca…
jakubadamw Apr 3, 2026
6dd94d6
Add a regression test for an index-out-of-bounds ICE on `partial_cmp`
jakubadamw Apr 3, 2026
fedb021
Add a regression test for an ICE when using `impl Trait` with a const…
jakubadamw Apr 3, 2026
6d6e0ae
Rollup merge of #153286 - davidtwco:sve-intrinsics, r=Amanieu
matthiaskrgr Apr 3, 2026
a4d278d
Rollup merge of #153592 - zedddie:adt_const_params_restricted_privacy…
matthiaskrgr Apr 3, 2026
ce74af2
Rollup merge of #154675 - chenyukang:yukang-fix-149546-private-field-…
matthiaskrgr Apr 3, 2026
dd46057
Rollup merge of #154653 - mejrs:append_const_msg, r=JonathanBrouwer
matthiaskrgr Apr 3, 2026
ad8468c
Rollup merge of #154743 - nnethercote:rm-two-unused-HashStable-impls,…
matthiaskrgr Apr 3, 2026
70b05be
Rollup merge of #154752 - theemathas:comment, r=lcnr
matthiaskrgr Apr 3, 2026
7a68d3f
Rollup merge of #154764 - jakubadamw:issue-113870-114056-118278, r=ja…
matthiaskrgr Apr 3, 2026
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
24 changes: 9 additions & 15 deletions compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::ops::Range;
use rustc_errors::E0232;
use rustc_hir::AttrPath;
use rustc_hir::attrs::diagnostic::{
AppendConstMessage, Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg,
Name, NameValue, OnUnimplementedCondition, Piece, Predicate,
Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, NameValue,
OnUnimplementedCondition, Piece, Predicate,
};
use rustc_hir::lints::{AttributeLintKind, FormatWarning};
use rustc_macros::Diagnostic;
Expand Down Expand Up @@ -92,7 +92,6 @@ fn parse_directive_items<'p, S: Stage>(
let mut notes = ThinVec::new();
let mut parent_label = None;
let mut subcommands = ThinVec::new();
let mut append_const_msg = None;

for item in items {
let span = item.span();
Expand Down Expand Up @@ -131,7 +130,6 @@ fn parse_directive_items<'p, S: Stage>(
let Some(ret) = (||{
Some($($code)*)
})() else {

malformed!()
};
ret
Expand Down Expand Up @@ -159,8 +157,13 @@ fn parse_directive_items<'p, S: Stage>(
let item: &MetaItemParser = or_malformed!(item.meta_item()?);
let name = or_malformed!(item.ident()?).name;

// Some things like `message = "message"` must have a value.
// But with things like `append_const_msg` that is optional.
// Currently, as of April 2026, all arguments of all diagnostic attrs
// must have a value, like `message = "message"`. Thus in a well-formed
// diagnostic attribute this is never `None`.
//
// But we don't assert its presence yet because we don't want to mention it
// if someone does something like `#[diagnostic::on_unimplemented(doesnt_exist)]`.
// That happens in the big `match` below.
let value: Option<Ident> = match item.args().name_value() {
Some(nv) => Some(or_malformed!(nv.value_as_ident()?)),
None => None,
Expand Down Expand Up @@ -223,14 +226,6 @@ fn parse_directive_items<'p, S: Stage>(
let value = or_malformed!(value?);
notes.push(parse_format(value))
}

(Mode::RustcOnUnimplemented, sym::append_const_msg) => {
append_const_msg = if let Some(msg) = value {
Some(AppendConstMessage::Custom(msg.name, item.span()))
} else {
Some(AppendConstMessage::Default)
}
}
(Mode::RustcOnUnimplemented, sym::parent_label) => {
let value = or_malformed!(value?);
if parent_label.is_none() {
Expand Down Expand Up @@ -290,7 +285,6 @@ fn parse_directive_items<'p, S: Stage>(
label,
notes,
parent_label,
append_const_msg,
})
}

Expand Down
16 changes: 0 additions & 16 deletions compiler/rustc_hir/src/attrs/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ pub struct Directive {
pub label: Option<(Span, FormatString)>,
pub notes: ThinVec<FormatString>,
pub parent_label: Option<FormatString>,
pub append_const_msg: Option<AppendConstMessage>,
}

impl Directive {
Expand Down Expand Up @@ -63,7 +62,6 @@ impl Directive {
let mut label = None;
let mut notes = Vec::new();
let mut parent_label = None;
let mut append_const_msg = None;
info!(
"evaluate_directive({:?}, trait_ref={:?}, options={:?}, args ={:?})",
self, trait_name, condition_options, args
Expand Down Expand Up @@ -91,16 +89,13 @@ impl Directive {
if let Some(ref parent_label_) = command.parent_label {
parent_label = Some(parent_label_.clone());
}

append_const_msg = command.append_const_msg;
}

OnUnimplementedNote {
label: label.map(|l| l.1.format(args)),
message: message.map(|m| m.1.format(args)),
notes: notes.into_iter().map(|n| n.format(args)).collect(),
parent_label: parent_label.map(|e_s| e_s.format(args)),
append_const_msg,
}
}
}
Expand All @@ -111,17 +106,6 @@ pub struct OnUnimplementedNote {
pub label: Option<String>,
pub notes: Vec<String>,
pub parent_label: Option<String>,
// If none, should fall back to a generic message
pub append_const_msg: Option<AppendConstMessage>,
}

/// Append a message for `[const] Trait` errors.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)]
pub enum AppendConstMessage {
#[default]
Default,
Custom(Symbol, Span),
}

/// Like [std::fmt::Arguments] this is a string that has been parsed into "pieces",
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,6 @@ symbols! {
anon_assoc,
anonymous_lifetime_in_impl_trait,
any,
append_const_msg,
apx_target_feature,
arbitrary_enum_discriminant,
arbitrary_self_types,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_errors::{
Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, msg,
pluralize, struct_span_code_err,
};
use rustc_hir::attrs::diagnostic::{AppendConstMessage, OnUnimplementedNote};
use rustc_hir::attrs::diagnostic::OnUnimplementedNote;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{self as hir, LangItem, Node, find_attr};
Expand Down Expand Up @@ -193,10 +193,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
label,
notes,
parent_label,
append_const_msg,
} = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file);

let have_alt_message = message.is_some() || label.is_some();

let message = message.unwrap_or_else(|| self.get_standard_error_message(
main_trait_predicate,
None,
post_message,
&mut long_ty_file,
));
let is_try_conversion = self.is_try_conversion(span, main_trait_predicate.def_id());
let is_question_mark = matches!(
root_obligation.cause.code().peel_derives(),
Expand All @@ -210,16 +216,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let question_mark_message = "the question mark operation (`?`) implicitly \
performs a conversion on the error value \
using the `From` trait";
let (message, notes, append_const_msg) = if is_try_conversion {
let (message, notes) = if is_try_conversion {
let ty = self.tcx.short_string(
main_trait_predicate.skip_binder().self_ty(),
&mut long_ty_file,
);
// We have a `-> Result<_, E1>` and `gives_E2()?`.
(
Some(format!("`?` couldn't convert the error to `{ty}`")),
format!("`?` couldn't convert the error to `{ty}`"),
vec![question_mark_message.to_owned()],
Some(AppendConstMessage::Default),
)
} else if is_question_mark {
let main_trait_predicate =
Expand All @@ -228,26 +233,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// trait object: `-> Result<_, Box<dyn Error>` and `gives_E()?` when
// `E: Error` isn't met.
(
Some(format!(
format!(
"`?` couldn't convert the error: `{main_trait_predicate}` is \
not satisfied",
)),
),
vec![question_mark_message.to_owned()],
Some(AppendConstMessage::Default),
)
} else {
(message, notes, append_const_msg)
(message, notes)
};

let default_err_msg = || self.get_standard_error_message(
main_trait_predicate,
message,
None,
append_const_msg,
post_message,
&mut long_ty_file,
);

let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(
main_trait_predicate.def_id(),
LangItem::TransmuteTrait,
Expand All @@ -271,15 +266,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
}
GetSafeTransmuteErrorAndReason::Default => {
(default_err_msg(), None)
(message, None)
}
GetSafeTransmuteErrorAndReason::Error {
err_msg,
safe_transmute_explanation,
} => (err_msg, safe_transmute_explanation),
}
} else {
(default_err_msg(), None)
(message, None)
};

let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
Expand Down Expand Up @@ -393,7 +388,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if let Some(s) = label {
// If it has a custom `#[rustc_on_unimplemented]`
// error message, let's display it as the label!
err.span_label(span, s.as_str().to_owned());
err.span_label(span, s);
if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_))
// When the self type is a type param We don't need to "the trait
// `std::marker::Sized` is not implemented for `T`" as we will point
Expand Down Expand Up @@ -862,9 +857,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {

let err_msg = self.get_standard_error_message(
trait_ref,
None,
Some(predicate.constness()),
None,
String::new(),
&mut file,
);
Expand Down Expand Up @@ -924,7 +917,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
label,
notes,
parent_label,
append_const_msg: _,
} = note;

if let Some(message) = message {
Expand Down Expand Up @@ -2841,40 +2833,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn get_standard_error_message(
&self,
trait_predicate: ty::PolyTraitPredicate<'tcx>,
message: Option<String>,
predicate_constness: Option<ty::BoundConstness>,
append_const_msg: Option<AppendConstMessage>,
post_message: String,
long_ty_path: &mut Option<PathBuf>,
) -> String {
message
.and_then(|cannot_do_this| {
match (predicate_constness, append_const_msg) {
// do nothing if predicate is not const
(None, _) => Some(cannot_do_this),
// suggested using default post message
(
Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe),
Some(AppendConstMessage::Default),
) => Some(format!("{cannot_do_this} in const contexts")),
// overridden post message
(
Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe),
Some(AppendConstMessage::Custom(custom_msg, _)),
) => Some(format!("{cannot_do_this}{custom_msg}")),
// fallback to generic message
(Some(ty::BoundConstness::Const | ty::BoundConstness::Maybe), None) => None,
}
})
.unwrap_or_else(|| {
format!(
"the trait bound `{}` is not satisfied{post_message}",
self.tcx.short_string(
trait_predicate.print_with_bound_constness(predicate_constness),
long_ty_path,
),
)
})
format!(
"the trait bound `{}` is not satisfied{post_message}",
self.tcx.short_string(
trait_predicate.print_with_bound_constness(predicate_constness),
long_ty_path,
),
)
}

fn select_transmute_obligation_for_reporting(
Expand Down
10 changes: 4 additions & 6 deletions library/core/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,9 @@ use crate::ops::ControlFlow;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "==")]
#[doc(alias = "!=")]
#[rustc_on_unimplemented(
#[diagnostic::on_unimplemented(
message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} == {Rhs}`",
append_const_msg
label = "no implementation for `{Self} == {Rhs}`"
)]
#[rustc_diagnostic_item = "PartialEq"]
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
Expand Down Expand Up @@ -1356,10 +1355,9 @@ pub macro Ord($item:item) {
#[doc(alias = "<")]
#[doc(alias = "<=")]
#[doc(alias = ">=")]
#[rustc_on_unimplemented(
#[diagnostic::on_unimplemented(
message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
append_const_msg
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
)]
#[rustc_diagnostic_item = "PartialOrd"]
#[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6
/// The *successor* operation moves towards values that compare greater.
/// The *predecessor* operation moves towards values that compare lesser.
#[rustc_diagnostic_item = "range_step"]
#[rustc_on_unimplemented(
#[diagnostic::on_unimplemented(
message = "`std::ops::Range<{Self}>` is not an iterator",
label = "`Range<{Self}>` is not an iterator",
note = "`Range` only implements `Iterator` for select types in the standard library, \
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,7 +1054,7 @@ marker_impls! {
#[unstable(feature = "const_destruct", issue = "133214")]
#[rustc_const_unstable(feature = "const_destruct", issue = "133214")]
#[lang = "destruct"]
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
#[diagnostic::on_unimplemented(message = "can't drop `{Self}`")]
#[rustc_deny_explicit_impl]
#[rustc_dyn_incompatible_trait]
pub const trait Destruct: PointeeSized {}
Expand Down
8 changes: 3 additions & 5 deletions library/core/src/ops/arith.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@
on(all(Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",),
on(all(Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",),
message = "cannot add `{Rhs}` to `{Self}`",
label = "no implementation for `{Self} + {Rhs}`",
append_const_msg
label = "no implementation for `{Self} + {Rhs}`"
)]
#[doc(alias = "+")]
pub const trait Add<Rhs = Self> {
Expand Down Expand Up @@ -181,10 +180,9 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128
#[lang = "sub"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
#[rustc_on_unimplemented(
#[diagnostic::on_unimplemented(
message = "cannot subtract `{Rhs}` from `{Self}`",
label = "no implementation for `{Self} - {Rhs}`",
append_const_msg
label = "no implementation for `{Self} - {Rhs}`"
)]
#[doc(alias = "-")]
pub const trait Sub<Rhs = Self> {
Expand Down
2 changes: 1 addition & 1 deletion tests/auxiliary/minicore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub trait MetaSized: PointeeSized {}
pub trait Sized: MetaSized {}

#[lang = "destruct"]
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
#[diagnostic::on_unimplemented(message = "can't drop `{Self}`")]
pub trait Destruct: PointeeSized {}

#[lang = "legacy_receiver"]
Expand Down