Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 54d024e

Browse files
committedMay 5, 2025·
Auto merge of #140650 - tgross35:rollup-0mp4h1s, r=tgross35
Rollup of 4 pull requests Successful merges: - #135734 (Correct `extract_if` sample equivalent.) - #140307 (Refactor rustc_on_unimplemented's filter parser) - #140644 (Revert "Avoid unused clones in Cloned<I> and Copied<I>") - #140648 (Update `compiler-builtins` to 0.1.157) r? `@ghost` `@rustbot` modify labels: rollup
2 parents cd55868 + 512dab0 commit 54d024e

File tree

14 files changed

+546
-367
lines changed

14 files changed

+546
-367
lines changed
 

‎Cargo.lock

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4502,7 +4502,6 @@ dependencies = [
45024502
"itertools",
45034503
"rustc_abi",
45044504
"rustc_ast",
4505-
"rustc_attr_parsing",
45064505
"rustc_data_structures",
45074506
"rustc_errors",
45084507
"rustc_fluent_macro",

‎compiler/rustc_trait_selection/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ edition = "2024"
88
itertools = "0.12"
99
rustc_abi = { path = "../rustc_abi" }
1010
rustc_ast = { path = "../rustc_ast" }
11-
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
1211
rustc_data_structures = { path = "../rustc_data_structures" }
1312
rustc_errors = { path = "../rustc_errors" }
1413
rustc_fluent_macro = { path = "../rustc_fluent_macro" }

‎compiler/rustc_trait_selection/messages.ftl

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,6 @@ trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement
148148
trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
149149
trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement
150150
151-
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
152-
.label = empty on-clause here
153-
154151
trait_selection_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
155152
156153
trait_selection_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
@@ -187,9 +184,6 @@ trait_selection_inherent_projection_normalization_overflow = overflow evaluating
187184
trait_selection_invalid_format_specifier = invalid format specifier
188185
.help = no format specifier are supported in this position
189186
190-
trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
191-
.label = invalid on-clause here
192-
193187
trait_selection_label_bad = {$bad_kind ->
194188
*[other] cannot infer type
195189
[more_info] cannot infer {$prefix_kind ->
@@ -237,10 +231,6 @@ trait_selection_negative_positive_conflict = found both positive and negative im
237231
.positive_implementation_here = positive implementation here
238232
.positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`
239233
240-
trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
241-
.label = expected value here
242-
.note = eg `#[rustc_on_unimplemented(message="foo")]`
243-
244234
trait_selection_nothing = {""}
245235
246236
trait_selection_oc_cant_coerce_force_inline =
@@ -339,6 +329,22 @@ trait_selection_ril_introduced_by = requirement introduced by this return type
339329
trait_selection_ril_introduced_here = `'static` requirement introduced here
340330
trait_selection_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
341331
332+
trait_selection_rustc_on_unimplemented_empty_on_clause = empty `on`-clause in `#[rustc_on_unimplemented]`
333+
.label = empty `on`-clause here
334+
trait_selection_rustc_on_unimplemented_expected_identifier = expected an identifier inside this `on`-clause
335+
.label = expected an identifier here, not `{$path}`
336+
trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not = expected a single predicate in `not(..)`
337+
.label = unexpected quantity of predicates here
338+
trait_selection_rustc_on_unimplemented_invalid_flag = invalid flag in `on`-clause
339+
.label = expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`
340+
trait_selection_rustc_on_unimplemented_invalid_predicate = this predicate is invalid
341+
.label = expected one of `any`, `all` or `not` here, not `{$invalid_pred}`
342+
trait_selection_rustc_on_unimplemented_missing_value = this attribute must have a value
343+
.label = expected value here
344+
.note = e.g. `#[rustc_on_unimplemented(message="foo")]`
345+
trait_selection_rustc_on_unimplemented_unsupported_literal_in_on = literals inside `on`-clauses are not supported
346+
.label = unexpected literal here
347+
342348
trait_selection_source_kind_closure_return =
343349
try giving this closure an explicit return type
344350

‎compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::path::PathBuf;
44
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
55
use rustc_errors::codes::*;
66
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
7+
use rustc_hir as hir;
78
use rustc_hir::def_id::{DefId, LocalDefId};
89
use rustc_hir::{AttrArgs, Attribute};
910
use rustc_macros::LintDiagnostic;
@@ -13,17 +14,16 @@ use rustc_middle::ty::{self, GenericArgsRef, GenericParamDef, GenericParamDefKin
1314
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
1415
use rustc_span::{Span, Symbol, sym};
1516
use tracing::{debug, info};
16-
use {rustc_attr_parsing as attr, rustc_hir as hir};
1717

1818
use super::{ObligationCauseCode, PredicateObligation};
1919
use crate::error_reporting::TypeErrCtxt;
20-
use crate::error_reporting::traits::on_unimplemented_condition::{Condition, ConditionOptions};
20+
use crate::error_reporting::traits::on_unimplemented_condition::{
21+
ConditionOptions, OnUnimplementedCondition,
22+
};
2123
use crate::error_reporting::traits::on_unimplemented_format::{
2224
Ctx, FormatArgs, FormatString, FormatWarning,
2325
};
24-
use crate::errors::{
25-
EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
26-
};
26+
use crate::errors::{InvalidOnClause, NoValueInOnUnimplemented};
2727
use crate::infer::InferCtxtExt;
2828

2929
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
@@ -306,21 +306,21 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
306306
#[derive(Clone, Debug)]
307307
pub struct OnUnimplementedFormatString {
308308
/// Symbol of the format string, i.e. `"content"`
309-
pub symbol: Symbol,
309+
symbol: Symbol,
310310
///The span of the format string, i.e. `"content"`
311-
pub span: Span,
312-
pub is_diagnostic_namespace_variant: bool,
311+
span: Span,
312+
is_diagnostic_namespace_variant: bool,
313313
}
314314

315315
#[derive(Debug)]
316316
pub struct OnUnimplementedDirective {
317-
pub condition: Option<Condition>,
318-
pub subcommands: Vec<OnUnimplementedDirective>,
319-
pub message: Option<(Span, OnUnimplementedFormatString)>,
320-
pub label: Option<(Span, OnUnimplementedFormatString)>,
321-
pub notes: Vec<OnUnimplementedFormatString>,
322-
pub parent_label: Option<OnUnimplementedFormatString>,
323-
pub append_const_msg: Option<AppendConstMessage>,
317+
condition: Option<OnUnimplementedCondition>,
318+
subcommands: Vec<OnUnimplementedDirective>,
319+
message: Option<(Span, OnUnimplementedFormatString)>,
320+
label: Option<(Span, OnUnimplementedFormatString)>,
321+
notes: Vec<OnUnimplementedFormatString>,
322+
parent_label: Option<OnUnimplementedFormatString>,
323+
append_const_msg: Option<AppendConstMessage>,
324324
}
325325

326326
/// For the `#[rustc_on_unimplemented]` attribute
@@ -427,18 +427,12 @@ impl<'tcx> OnUnimplementedDirective {
427427
} else {
428428
let cond = item_iter
429429
.next()
430-
.ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))?
431-
.meta_item_or_bool()
432-
.ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
433-
attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| {
434-
if let Some(value) = cfg.value
435-
&& let Err(guar) = parse_value(value, cfg.span)
436-
{
437-
errored = Some(guar);
438-
}
439-
true
440-
});
441-
Some(Condition { inner: cond.clone() })
430+
.ok_or_else(|| tcx.dcx().emit_err(InvalidOnClause::Empty { span }))?;
431+
432+
match OnUnimplementedCondition::parse(cond) {
433+
Ok(condition) => Some(condition),
434+
Err(e) => return Err(tcx.dcx().emit_err(e)),
435+
}
442436
};
443437

444438
let mut message = None;
@@ -724,7 +718,7 @@ impl<'tcx> OnUnimplementedDirective {
724718
result
725719
}
726720

727-
pub fn evaluate(
721+
pub(crate) fn evaluate(
728722
&self,
729723
tcx: TyCtxt<'tcx>,
730724
trait_ref: ty::TraitRef<'tcx>,
@@ -744,7 +738,7 @@ impl<'tcx> OnUnimplementedDirective {
744738
for command in self.subcommands.iter().chain(Some(self)).rev() {
745739
debug!(?command);
746740
if let Some(ref condition) = command.condition
747-
&& !condition.matches_predicate(tcx, condition_options)
741+
&& !condition.matches_predicate(condition_options)
748742
{
749743
debug!("evaluate: skipping {:?} due to condition", command);
750744
continue;
Lines changed: 258 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,251 @@
1-
use rustc_ast::MetaItemInner;
2-
use rustc_attr_parsing as attr;
3-
use rustc_middle::ty::{self, TyCtxt};
1+
use rustc_ast::{MetaItemInner, MetaItemKind, MetaItemLit};
42
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
5-
use rustc_span::{DesugaringKind, Span, Symbol, kw, sym};
3+
use rustc_span::{DesugaringKind, Ident, Span, Symbol, kw, sym};
64

7-
/// A predicate in an attribute using on, all, any,
8-
/// similar to a cfg predicate.
5+
use crate::errors::InvalidOnClause;
6+
7+
/// Represents the `on` filter in `#[rustc_on_unimplemented]`.
98
#[derive(Debug)]
10-
pub struct Condition {
11-
pub inner: MetaItemInner,
9+
pub(crate) struct OnUnimplementedCondition {
10+
span: Span,
11+
pred: Predicate,
1212
}
1313

14-
impl Condition {
15-
pub fn span(&self) -> Span {
16-
self.inner.span()
14+
impl OnUnimplementedCondition {
15+
pub(crate) fn span(&self) -> Span {
16+
self.span
17+
}
18+
19+
pub(crate) fn matches_predicate(&self, options: &ConditionOptions) -> bool {
20+
self.pred.eval(&mut |p| match p {
21+
FlagOrNv::Flag(b) => options.has_flag(*b),
22+
FlagOrNv::NameValue(NameValue { name, value }) => {
23+
let value = value.format(&options.generic_args);
24+
options.contains(*name, value)
25+
}
26+
})
27+
}
28+
29+
pub(crate) fn parse(input: &MetaItemInner) -> Result<Self, InvalidOnClause> {
30+
let span = input.span();
31+
let pred = Predicate::parse(input)?;
32+
Ok(OnUnimplementedCondition { span, pred })
1733
}
34+
}
1835

19-
pub fn matches_predicate<'tcx>(&self, tcx: TyCtxt<'tcx>, options: &ConditionOptions) -> bool {
20-
attr::eval_condition(&self.inner, tcx.sess, Some(tcx.features()), &mut |cfg| {
21-
let value = cfg.value.map(|v| {
22-
// `with_no_visible_paths` is also used when generating the options,
23-
// so we need to match it here.
24-
ty::print::with_no_visible_paths!({
25-
Parser::new(v.as_str(), None, None, false, ParseMode::Format)
26-
.map(|p| match p {
27-
Piece::Lit(s) => s.to_owned(),
28-
Piece::NextArgument(a) => match a.position {
29-
Position::ArgumentNamed(arg) => {
30-
let s = Symbol::intern(arg);
31-
match options.generic_args.iter().find(|(k, _)| *k == s) {
32-
Some((_, val)) => val.to_string(),
33-
None => format!("{{{arg}}}"),
34-
}
35-
}
36-
Position::ArgumentImplicitlyIs(_) => String::from("{}"),
37-
Position::ArgumentIs(idx) => format!("{{{idx}}}"),
38-
},
39-
})
40-
.collect()
41-
})
36+
/// Predicate(s) in `#[rustc_on_unimplemented]`'s `on` filter. See [`OnUnimplementedCondition`].
37+
///
38+
/// It is similar to the predicate in the `cfg` attribute,
39+
/// and may contain nested predicates.
40+
#[derive(Debug)]
41+
enum Predicate {
42+
/// A condition like `on(crate_local)`.
43+
Flag(Flag),
44+
/// A match, like `on(Rhs = "Whatever")`.
45+
Match(NameValue),
46+
/// Negation, like `on(not($pred))`.
47+
Not(Box<Predicate>),
48+
/// True if all predicates are true, like `on(all($a, $b, $c))`.
49+
All(Vec<Predicate>),
50+
/// True if any predicate is true, like `on(any($a, $b, $c))`.
51+
Any(Vec<Predicate>),
52+
}
53+
54+
impl Predicate {
55+
fn parse(input: &MetaItemInner) -> Result<Self, InvalidOnClause> {
56+
let meta_item = match input {
57+
MetaItemInner::MetaItem(meta_item) => meta_item,
58+
MetaItemInner::Lit(lit) => {
59+
return Err(InvalidOnClause::UnsupportedLiteral { span: lit.span });
60+
}
61+
};
62+
63+
let Some(predicate) = meta_item.ident() else {
64+
return Err(InvalidOnClause::ExpectedIdentifier {
65+
span: meta_item.path.span,
66+
path: meta_item.path.clone(),
4267
});
68+
};
4369

44-
options.contains(cfg.name, &value)
45-
})
70+
match meta_item.kind {
71+
MetaItemKind::List(ref mis) => match predicate.name {
72+
sym::any => Ok(Predicate::Any(Predicate::parse_sequence(mis)?)),
73+
sym::all => Ok(Predicate::All(Predicate::parse_sequence(mis)?)),
74+
sym::not => match &**mis {
75+
[one] => Ok(Predicate::Not(Box::new(Predicate::parse(one)?))),
76+
[first, .., last] => Err(InvalidOnClause::ExpectedOnePredInNot {
77+
span: first.span().to(last.span()),
78+
}),
79+
[] => Err(InvalidOnClause::ExpectedOnePredInNot { span: meta_item.span }),
80+
},
81+
invalid_pred => {
82+
Err(InvalidOnClause::InvalidPredicate { span: predicate.span, invalid_pred })
83+
}
84+
},
85+
MetaItemKind::NameValue(MetaItemLit { symbol, .. }) => {
86+
let name = Name::parse(predicate);
87+
let value = FilterFormatString::parse(symbol);
88+
let kv = NameValue { name, value };
89+
Ok(Predicate::Match(kv))
90+
}
91+
MetaItemKind::Word => {
92+
let flag = Flag::parse(predicate)?;
93+
Ok(Predicate::Flag(flag))
94+
}
95+
}
96+
}
97+
98+
fn parse_sequence(sequence: &[MetaItemInner]) -> Result<Vec<Self>, InvalidOnClause> {
99+
sequence.iter().map(Predicate::parse).collect()
100+
}
101+
102+
fn eval(&self, eval: &mut impl FnMut(FlagOrNv<'_>) -> bool) -> bool {
103+
match self {
104+
Predicate::Flag(flag) => eval(FlagOrNv::Flag(flag)),
105+
Predicate::Match(nv) => eval(FlagOrNv::NameValue(nv)),
106+
Predicate::Not(not) => !not.eval(eval),
107+
Predicate::All(preds) => preds.into_iter().all(|pred| pred.eval(eval)),
108+
Predicate::Any(preds) => preds.into_iter().any(|pred| pred.eval(eval)),
109+
}
46110
}
47111
}
48112

49-
/// Used with `Condition::matches_predicate` to test whether the condition applies
113+
/// Represents a `MetaWord` in an `on`-filter.
114+
#[derive(Debug, Clone, Copy)]
115+
enum Flag {
116+
/// Whether the code causing the trait bound to not be fulfilled
117+
/// is part of the user's crate.
118+
CrateLocal,
119+
/// Whether the obligation is user-specified rather than derived.
120+
Direct,
121+
/// Whether we are in some kind of desugaring like
122+
/// `?` or `try { .. }`.
123+
FromDesugaring,
124+
}
125+
126+
impl Flag {
127+
fn parse(Ident { name, span }: Ident) -> Result<Self, InvalidOnClause> {
128+
match name {
129+
sym::crate_local => Ok(Flag::CrateLocal),
130+
sym::direct => Ok(Flag::Direct),
131+
sym::from_desugaring => Ok(Flag::FromDesugaring),
132+
invalid_flag => Err(InvalidOnClause::InvalidFlag { invalid_flag, span }),
133+
}
134+
}
135+
}
136+
137+
/// A `MetaNameValueStr` in an `on`-filter.
138+
///
139+
/// For example, `#[rustc_on_unimplemented(on(name = "value", message = "hello"))]`.
140+
#[derive(Debug, Clone)]
141+
struct NameValue {
142+
name: Name,
143+
/// Something like `"&str"` or `"alloc::string::String"`,
144+
/// in which case it just contains a single string piece.
145+
/// But if it is something like `"&[{A}]"` then it must be formatted later.
146+
value: FilterFormatString,
147+
}
148+
149+
/// The valid names of the `on` filter.
150+
#[derive(Debug, Clone, Copy)]
151+
enum Name {
152+
Cause,
153+
FromDesugaring,
154+
SelfUpper,
155+
GenericArg(Symbol),
156+
}
157+
158+
impl Name {
159+
fn parse(Ident { name, .. }: Ident) -> Self {
160+
match name {
161+
sym::_Self | kw::SelfUpper => Name::SelfUpper,
162+
sym::from_desugaring => Name::FromDesugaring,
163+
sym::cause => Name::Cause,
164+
// FIXME(mejrs) Perhaps we should start checking that
165+
// this actually is a valid generic parameter?
166+
generic => Name::GenericArg(generic),
167+
}
168+
}
169+
}
170+
171+
#[derive(Debug, Clone)]
172+
enum FlagOrNv<'p> {
173+
Flag(&'p Flag),
174+
NameValue(&'p NameValue),
175+
}
176+
177+
/// Represents a value inside an `on` filter.
178+
///
179+
/// For example, `#[rustc_on_unimplemented(on(name = "value", message = "hello"))]`.
180+
/// If it is a simple literal like this then `pieces` will be `[LitOrArg::Lit("value")]`.
181+
/// The `Arg` variant is used when it contains formatting like
182+
/// `#[rustc_on_unimplemented(on(Self = "&[{A}]", message = "hello"))]`.
183+
#[derive(Debug, Clone)]
184+
struct FilterFormatString {
185+
pieces: Vec<LitOrArg>,
186+
}
187+
188+
#[derive(Debug, Clone)]
189+
enum LitOrArg {
190+
Lit(String),
191+
Arg(String),
192+
}
193+
194+
impl FilterFormatString {
195+
fn parse(input: Symbol) -> Self {
196+
let pieces = Parser::new(input.as_str(), None, None, false, ParseMode::Format)
197+
.map(|p| match p {
198+
Piece::Lit(s) => LitOrArg::Lit(s.to_owned()),
199+
// We just ignore formatspecs here
200+
Piece::NextArgument(a) => match a.position {
201+
// In `TypeErrCtxt::on_unimplemented_note` we substitute `"{integral}"` even
202+
// if the integer type has been resolved, to allow targeting all integers.
203+
// `"{integer}"` and `"{float}"` come from numerics that haven't been inferred yet,
204+
// from the `Display` impl of `InferTy` to be precise.
205+
//
206+
// Don't try to format these later!
207+
Position::ArgumentNamed(arg @ "integer" | arg @ "integral" | arg @ "float") => {
208+
LitOrArg::Lit(format!("{{{arg}}}"))
209+
}
210+
211+
// FIXME(mejrs) We should check if these correspond to a generic of the trait.
212+
Position::ArgumentNamed(arg) => LitOrArg::Arg(arg.to_owned()),
213+
214+
// FIXME(mejrs) These should really be warnings/errors
215+
Position::ArgumentImplicitlyIs(_) => LitOrArg::Lit(String::from("{}")),
216+
Position::ArgumentIs(idx) => LitOrArg::Lit(format!("{{{idx}}}")),
217+
},
218+
})
219+
.collect();
220+
Self { pieces }
221+
}
222+
223+
fn format(&self, generic_args: &[(Symbol, String)]) -> String {
224+
let mut ret = String::new();
225+
226+
for piece in &self.pieces {
227+
match piece {
228+
LitOrArg::Lit(s) => ret.push_str(s),
229+
LitOrArg::Arg(arg) => {
230+
let s = Symbol::intern(arg);
231+
match generic_args.iter().find(|(k, _)| *k == s) {
232+
Some((_, val)) => ret.push_str(val),
233+
None => {
234+
// FIXME(mejrs) If we start checking as mentioned in
235+
// FilterFormatString::parse then this shouldn't happen
236+
let _ = std::fmt::write(&mut ret, format_args!("{{{s}}}"));
237+
}
238+
}
239+
}
240+
}
241+
}
242+
243+
ret
244+
}
245+
}
246+
247+
/// Used with `OnUnimplementedCondition::matches_predicate` to evaluate the
248+
/// [`OnUnimplementedCondition`].
50249
///
51250
/// For example, given a
52251
/// ```rust,ignore (just an example)
@@ -85,36 +284,34 @@ impl Condition {
85284
/// }
86285
/// ```
87286
#[derive(Debug)]
88-
pub struct ConditionOptions {
287+
pub(crate) struct ConditionOptions {
89288
/// All the self types that may apply.
90-
/// for example
91-
pub self_types: Vec<String>,
289+
pub(crate) self_types: Vec<String>,
92290
// The kind of compiler desugaring.
93-
pub from_desugaring: Option<DesugaringKind>,
94-
/// Match on a variant of [rustc_infer::traits::ObligationCauseCode]
95-
pub cause: Option<String>,
96-
pub crate_local: bool,
291+
pub(crate) from_desugaring: Option<DesugaringKind>,
292+
/// Match on a variant of [rustc_infer::traits::ObligationCauseCode].
293+
pub(crate) cause: Option<String>,
294+
pub(crate) crate_local: bool,
97295
/// Is the obligation "directly" user-specified, rather than derived?
98-
pub direct: bool,
99-
// A list of the generic arguments and their reified types
100-
pub generic_args: Vec<(Symbol, String)>,
296+
pub(crate) direct: bool,
297+
// A list of the generic arguments and their reified types.
298+
pub(crate) generic_args: Vec<(Symbol, String)>,
101299
}
102300

103301
impl ConditionOptions {
104-
pub fn contains(&self, key: Symbol, value: &Option<String>) -> bool {
105-
match (key, value) {
106-
(sym::_Self | kw::SelfUpper, Some(value)) => self.self_types.contains(&value),
107-
// from_desugaring as a flag
108-
(sym::from_desugaring, None) => self.from_desugaring.is_some(),
109-
// from_desugaring as key == value
110-
(sym::from_desugaring, Some(v)) if let Some(ds) = self.from_desugaring => ds.matches(v),
111-
(sym::cause, Some(value)) => self.cause.as_deref() == Some(value),
112-
(sym::crate_local, None) => self.crate_local,
113-
(sym::direct, None) => self.direct,
114-
(other, Some(value)) => {
115-
self.generic_args.iter().any(|(k, v)| *k == other && v == value)
116-
}
117-
_ => false,
302+
fn has_flag(&self, name: Flag) -> bool {
303+
match name {
304+
Flag::CrateLocal => self.crate_local,
305+
Flag::Direct => self.direct,
306+
Flag::FromDesugaring => self.from_desugaring.is_some(),
307+
}
308+
}
309+
fn contains(&self, name: Name, value: String) -> bool {
310+
match name {
311+
Name::SelfUpper => self.self_types.contains(&value),
312+
Name::FromDesugaring => self.from_desugaring.is_some_and(|ds| ds.matches(&value)),
313+
Name::Cause => self.cause == Some(value),
314+
Name::GenericArg(arg) => self.generic_args.contains(&(arg, value)),
118315
}
119316
}
120317
}

‎compiler/rustc_trait_selection/src/errors.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::path::PathBuf;
22

3+
use rustc_ast::Path;
34
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
45
use rustc_errors::codes::*;
56
use rustc_errors::{
@@ -31,23 +32,50 @@ pub struct UnableToConstructConstantValue<'a> {
3132
}
3233

3334
#[derive(Diagnostic)]
34-
#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = E0232)]
35-
pub struct EmptyOnClauseInOnUnimplemented {
36-
#[primary_span]
37-
#[label]
38-
pub span: Span,
39-
}
40-
41-
#[derive(Diagnostic)]
42-
#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = E0232)]
43-
pub struct InvalidOnClauseInOnUnimplemented {
44-
#[primary_span]
45-
#[label]
46-
pub span: Span,
35+
pub enum InvalidOnClause {
36+
#[diag(trait_selection_rustc_on_unimplemented_empty_on_clause, code = E0232)]
37+
Empty {
38+
#[primary_span]
39+
#[label]
40+
span: Span,
41+
},
42+
#[diag(trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not, code = E0232)]
43+
ExpectedOnePredInNot {
44+
#[primary_span]
45+
#[label]
46+
span: Span,
47+
},
48+
#[diag(trait_selection_rustc_on_unimplemented_unsupported_literal_in_on, code = E0232)]
49+
UnsupportedLiteral {
50+
#[primary_span]
51+
#[label]
52+
span: Span,
53+
},
54+
#[diag(trait_selection_rustc_on_unimplemented_expected_identifier, code = E0232)]
55+
ExpectedIdentifier {
56+
#[primary_span]
57+
#[label]
58+
span: Span,
59+
path: Path,
60+
},
61+
#[diag(trait_selection_rustc_on_unimplemented_invalid_predicate, code = E0232)]
62+
InvalidPredicate {
63+
#[primary_span]
64+
#[label]
65+
span: Span,
66+
invalid_pred: Symbol,
67+
},
68+
#[diag(trait_selection_rustc_on_unimplemented_invalid_flag, code = E0232)]
69+
InvalidFlag {
70+
#[primary_span]
71+
#[label]
72+
span: Span,
73+
invalid_flag: Symbol,
74+
},
4775
}
4876

4977
#[derive(Diagnostic)]
50-
#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = E0232)]
78+
#[diag(trait_selection_rustc_on_unimplemented_missing_value, code = E0232)]
5179
#[note]
5280
pub struct NoValueInOnUnimplemented {
5381
#[primary_span]

‎library/Cargo.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change

‎library/alloc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ bench = false
1616

1717
[dependencies]
1818
core = { path = "../core", public = true }
19-
compiler_builtins = { version = "=0.1.156", features = ['rustc-dep-of-std'] }
19+
compiler_builtins = { version = "=0.1.157", features = ['rustc-dep-of-std'] }
2020

2121
[features]
2222
compiler-builtins-mem = ['compiler_builtins/mem']

‎library/alloc/src/vec/mod.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3666,21 +3666,27 @@ impl<T, A: Allocator> Vec<T, A> {
36663666
/// Using this method is equivalent to the following code:
36673667
///
36683668
/// ```
3669-
/// # use std::cmp::min;
3670-
/// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
3671-
/// # let mut vec = vec![1, 2, 3, 4, 5, 6];
3672-
/// # let range = 1..4;
3669+
/// # let some_predicate = |x: &mut i32| { *x % 2 == 1 };
3670+
/// # let mut vec = vec![0, 1, 2, 3, 4, 5, 6];
3671+
/// # let mut vec2 = vec.clone();
3672+
/// # let range = 1..5;
36733673
/// let mut i = range.start;
3674-
/// while i < min(vec.len(), range.end) {
3674+
/// let end_items = vec.len() - range.end;
3675+
/// # let mut extracted = vec![];
3676+
///
3677+
/// while i < vec.len() - end_items {
36753678
/// if some_predicate(&mut vec[i]) {
36763679
/// let val = vec.remove(i);
3680+
/// # extracted.push(val);
36773681
/// // your code here
36783682
/// } else {
36793683
/// i += 1;
36803684
/// }
36813685
/// }
36823686
///
3683-
/// # assert_eq!(vec, vec![1, 4, 5]);
3687+
/// # let extracted2: Vec<_> = vec2.extract_if(range, some_predicate).collect();
3688+
/// # assert_eq!(vec, vec2);
3689+
/// # assert_eq!(extracted, extracted2);
36843690
/// ```
36853691
///
36863692
/// But `extract_if` is easier to use. `extract_if` is also more efficient,

‎library/core/src/iter/adapters/cloned.rs

Lines changed: 2 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use core::num::NonZero;
22

3-
use crate::cmp::Ordering;
43
use crate::iter::adapters::zip::try_get_unchecked;
54
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
65
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
@@ -42,31 +41,13 @@ where
4241
self.it.next().cloned()
4342
}
4443

45-
#[inline]
4644
fn size_hint(&self) -> (usize, Option<usize>) {
4745
self.it.size_hint()
4846
}
4947

50-
#[inline]
51-
fn count(self) -> usize {
52-
self.it.count()
53-
}
54-
55-
fn last(self) -> Option<T> {
56-
self.it.last().cloned()
57-
}
58-
59-
#[inline]
60-
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
61-
self.it.advance_by(n)
62-
}
63-
64-
fn nth(&mut self, n: usize) -> Option<T> {
65-
self.it.nth(n).cloned()
66-
}
67-
6848
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
6949
where
50+
Self: Sized,
7051
F: FnMut(B, Self::Item) -> R,
7152
R: Try<Output = B>,
7253
{
@@ -80,58 +61,6 @@ where
8061
self.it.map(T::clone).fold(init, f)
8162
}
8263

83-
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
84-
where
85-
P: FnMut(&Self::Item) -> bool,
86-
{
87-
self.it.find(move |x| predicate(&x)).cloned()
88-
}
89-
90-
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
91-
where
92-
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
93-
{
94-
self.it.max_by(move |&x, &y| compare(x, y)).cloned()
95-
}
96-
97-
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
98-
where
99-
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
100-
{
101-
self.it.min_by(move |&x, &y| compare(x, y)).cloned()
102-
}
103-
104-
fn cmp<O>(self, other: O) -> Ordering
105-
where
106-
O: IntoIterator<Item = Self::Item>,
107-
Self::Item: Ord,
108-
{
109-
self.it.cmp_by(other, |x, y| x.cmp(&y))
110-
}
111-
112-
fn partial_cmp<O>(self, other: O) -> Option<Ordering>
113-
where
114-
O: IntoIterator,
115-
Self::Item: PartialOrd<O::Item>,
116-
{
117-
self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
118-
}
119-
120-
fn eq<O>(self, other: O) -> bool
121-
where
122-
O: IntoIterator,
123-
Self::Item: PartialEq<O::Item>,
124-
{
125-
self.it.eq_by(other, |x, y| x == &y)
126-
}
127-
128-
fn is_sorted_by<F>(self, mut compare: F) -> bool
129-
where
130-
F: FnMut(&Self::Item, &Self::Item) -> bool,
131-
{
132-
self.it.is_sorted_by(move |&x, &y| compare(x, y))
133-
}
134-
13564
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
13665
where
13766
Self: TrustedRandomAccessNoCoerce,
@@ -152,13 +81,9 @@ where
15281
self.it.next_back().cloned()
15382
}
15483

155-
#[inline]
156-
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
157-
self.it.advance_back_by(n)
158-
}
159-
16084
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
16185
where
86+
Self: Sized,
16287
F: FnMut(B, Self::Item) -> R,
16388
R: Try<Output = B>,
16489
{
@@ -171,13 +96,6 @@ where
17196
{
17297
self.it.map(T::clone).rfold(init, f)
17398
}
174-
175-
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
176-
where
177-
P: FnMut(&Self::Item) -> bool,
178-
{
179-
self.it.rfind(move |x| predicate(&x)).cloned()
180-
}
18199
}
182100

183101
#[stable(feature = "iter_cloned", since = "1.1.0")]
@@ -186,12 +104,10 @@ where
186104
I: ExactSizeIterator<Item = &'a T>,
187105
T: Clone,
188106
{
189-
#[inline]
190107
fn len(&self) -> usize {
191108
self.it.len()
192109
}
193110

194-
#[inline]
195111
fn is_empty(&self) -> bool {
196112
self.it.is_empty()
197113
}

‎library/core/src/iter/adapters/copied.rs

Lines changed: 18 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::cmp::Ordering;
21
use crate::iter::adapters::zip::try_get_unchecked;
32
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
43
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
@@ -49,35 +48,20 @@ where
4948

5049
fn next_chunk<const N: usize>(
5150
&mut self,
52-
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
51+
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
52+
where
53+
Self: Sized,
54+
{
5355
<I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
5456
}
5557

56-
#[inline]
5758
fn size_hint(&self) -> (usize, Option<usize>) {
5859
self.it.size_hint()
5960
}
6061

61-
#[inline]
62-
fn count(self) -> usize {
63-
self.it.count()
64-
}
65-
66-
fn last(self) -> Option<T> {
67-
self.it.last().copied()
68-
}
69-
70-
#[inline]
71-
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
72-
self.it.advance_by(n)
73-
}
74-
75-
fn nth(&mut self, n: usize) -> Option<T> {
76-
self.it.nth(n).copied()
77-
}
78-
7962
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
8063
where
64+
Self: Sized,
8165
F: FnMut(B, Self::Item) -> R,
8266
R: Try<Output = B>,
8367
{
@@ -91,56 +75,21 @@ where
9175
self.it.fold(init, copy_fold(f))
9276
}
9377

94-
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
95-
where
96-
P: FnMut(&Self::Item) -> bool,
97-
{
98-
self.it.find(move |x| predicate(&x)).copied()
99-
}
100-
101-
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
102-
where
103-
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
104-
{
105-
self.it.max_by(move |&x, &y| compare(x, y)).copied()
106-
}
107-
108-
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
109-
where
110-
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
111-
{
112-
self.it.min_by(move |&x, &y| compare(x, y)).copied()
113-
}
114-
115-
fn cmp<O>(self, other: O) -> Ordering
116-
where
117-
O: IntoIterator<Item = Self::Item>,
118-
Self::Item: Ord,
119-
{
120-
self.it.cmp_by(other, |x, y| x.cmp(&y))
78+
fn nth(&mut self, n: usize) -> Option<T> {
79+
self.it.nth(n).copied()
12180
}
12281

123-
fn partial_cmp<O>(self, other: O) -> Option<Ordering>
124-
where
125-
O: IntoIterator,
126-
Self::Item: PartialOrd<O::Item>,
127-
{
128-
self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
82+
fn last(self) -> Option<T> {
83+
self.it.last().copied()
12984
}
13085

131-
fn eq<O>(self, other: O) -> bool
132-
where
133-
O: IntoIterator,
134-
Self::Item: PartialEq<O::Item>,
135-
{
136-
self.it.eq_by(other, |x, y| x == &y)
86+
fn count(self) -> usize {
87+
self.it.count()
13788
}
13889

139-
fn is_sorted_by<F>(self, mut compare: F) -> bool
140-
where
141-
F: FnMut(&Self::Item, &Self::Item) -> bool,
142-
{
143-
self.it.is_sorted_by(move |&x, &y| compare(x, y))
90+
#[inline]
91+
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
92+
self.it.advance_by(n)
14493
}
14594

14695
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
@@ -163,13 +112,9 @@ where
163112
self.it.next_back().copied()
164113
}
165114

166-
#[inline]
167-
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
168-
self.it.advance_back_by(n)
169-
}
170-
171115
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
172116
where
117+
Self: Sized,
173118
F: FnMut(B, Self::Item) -> R,
174119
R: Try<Output = B>,
175120
{
@@ -183,11 +128,9 @@ where
183128
self.it.rfold(init, copy_fold(f))
184129
}
185130

186-
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
187-
where
188-
P: FnMut(&Self::Item) -> bool,
189-
{
190-
self.it.rfind(move |x| predicate(&x)).copied()
131+
#[inline]
132+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
133+
self.it.advance_back_by(n)
191134
}
192135
}
193136

@@ -197,12 +140,10 @@ where
197140
I: ExactSizeIterator<Item = &'a T>,
198141
T: Copy,
199142
{
200-
#[inline]
201143
fn len(&self) -> usize {
202144
self.it.len()
203145
}
204146

205-
#[inline]
206147
fn is_empty(&self) -> bool {
207148
self.it.is_empty()
208149
}

‎library/std/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
1818
panic_unwind = { path = "../panic_unwind", optional = true }
1919
panic_abort = { path = "../panic_abort" }
2020
core = { path = "../core", public = true }
21-
compiler_builtins = { version = "=0.1.156" }
21+
compiler_builtins = { version = "=0.1.157" }
2222
unwind = { path = "../unwind" }
2323
hashbrown = { version = "0.15", default-features = false, features = [
2424
'rustc-dep-of-std',
Lines changed: 88 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,109 @@
1-
// ignore-tidy-linelength
2-
1+
#![crate_type = "lib"]
32
#![feature(rustc_attrs)]
4-
53
#![allow(unused)]
64

75
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
8-
trait Foo<Bar, Baz, Quux>
9-
{}
6+
trait Foo<Bar, Baz, Quux> {}
107

11-
#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
8+
#[rustc_on_unimplemented = "a collection of type `{Self}` cannot \
9+
be built from an iterator over elements of type `{A}`"]
1210
trait MyFromIterator<A> {
1311
/// Builds a container with elements from an external iterator.
14-
fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
12+
fn my_from_iter<T: Iterator<Item = A>>(iterator: T) -> Self;
1513
}
1614

1715
#[rustc_on_unimplemented]
1816
//~^ ERROR malformed `rustc_on_unimplemented` attribute
19-
trait BadAnnotation1
20-
{}
17+
trait NoContent {}
2118

2219
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
2320
//~^ ERROR cannot find parameter C on this trait
24-
trait BadAnnotation2<A,B>
25-
{}
21+
trait ParameterNotPresent<A, B> {}
2622

2723
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
2824
//~^ ERROR positional format arguments are not allowed here
29-
trait BadAnnotation3<A,B>
30-
{}
25+
trait NoPositionalArgs<A, B> {}
3126

32-
#[rustc_on_unimplemented(lorem="")]
33-
//~^ ERROR this attribute must have a valid
34-
trait BadAnnotation4 {}
27+
#[rustc_on_unimplemented(lorem = "")]
28+
//~^ ERROR this attribute must have a value
29+
//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]`
30+
//~^^^ NOTE expected value here
31+
trait EmptyMessage {}
3532

3633
#[rustc_on_unimplemented(lorem(ipsum(dolor)))]
37-
//~^ ERROR this attribute must have a valid
38-
trait BadAnnotation5 {}
39-
40-
#[rustc_on_unimplemented(message="x", message="y")]
41-
//~^ ERROR this attribute must have a valid
42-
trait BadAnnotation6 {}
43-
44-
#[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
45-
//~^ ERROR this attribute must have a valid
46-
trait BadAnnotation7 {}
47-
48-
#[rustc_on_unimplemented(on(), message="y")]
34+
//~^ ERROR this attribute must have a value
35+
//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]`
36+
//~^^^ NOTE expected value here
37+
trait Invalid {}
38+
39+
#[rustc_on_unimplemented(message = "x", message = "y")]
40+
//~^ ERROR this attribute must have a value
41+
//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]`
42+
//~^^^ NOTE expected value here
43+
trait DuplicateMessage {}
44+
45+
#[rustc_on_unimplemented(message = "x", on(desugared, message = "y"))]
46+
//~^ ERROR this attribute must have a value
47+
//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]`
48+
//~^^^ NOTE expected value here
49+
trait OnInWrongPosition {}
50+
51+
#[rustc_on_unimplemented(on(), message = "y")]
4952
//~^ ERROR empty `on`-clause
50-
trait BadAnnotation8 {}
51-
52-
#[rustc_on_unimplemented(on="x", message="y")]
53-
//~^ ERROR this attribute must have a valid
54-
trait BadAnnotation9 {}
55-
56-
#[rustc_on_unimplemented(on(x="y"), message="y")]
57-
trait BadAnnotation10 {}
58-
59-
#[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
60-
//~^ ERROR this attribute must have a valid
61-
trait BadAnnotation11 {}
62-
63-
pub fn main() {
64-
}
53+
//~^^ NOTE empty `on`-clause here
54+
trait EmptyOn {}
55+
56+
#[rustc_on_unimplemented(on = "x", message = "y")]
57+
//~^ ERROR this attribute must have a value
58+
//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]`
59+
//~^^^ NOTE expected value here
60+
trait ExpectedPredicateInOn {}
61+
62+
#[rustc_on_unimplemented(on(x = "y"), message = "y")]
63+
trait OnWithoutDirectives {}
64+
65+
#[rustc_on_unimplemented(on(from_desugaring, on(from_desugaring, message = "x")), message = "y")]
66+
//~^ ERROR this attribute must have a value
67+
//~^^ NOTE e.g. `#[rustc_on_unimplemented(message="foo")]`
68+
//~^^^ NOTE expected value here
69+
trait NestedOn {}
70+
71+
#[rustc_on_unimplemented(on("y", message = "y"))]
72+
//~^ ERROR literals inside `on`-clauses are not supported
73+
//~^^ NOTE unexpected literal here
74+
trait UnsupportedLiteral {}
75+
76+
#[rustc_on_unimplemented(on(42, message = "y"))]
77+
//~^ ERROR literals inside `on`-clauses are not supported
78+
//~^^ NOTE unexpected literal here
79+
trait UnsupportedLiteral2 {}
80+
81+
#[rustc_on_unimplemented(on(not(a, b), message = "y"))]
82+
//~^ ERROR expected a single predicate in `not(..)` [E0232]
83+
//~^^ NOTE unexpected quantity of predicates here
84+
trait ExpectedOnePattern {}
85+
86+
#[rustc_on_unimplemented(on(not(), message = "y"))]
87+
//~^ ERROR expected a single predicate in `not(..)` [E0232]
88+
//~^^ NOTE unexpected quantity of predicates here
89+
trait ExpectedOnePattern2 {}
90+
91+
#[rustc_on_unimplemented(on(thing::What, message = "y"))]
92+
//~^ ERROR expected an identifier inside this `on`-clause
93+
//~^^ NOTE expected an identifier here, not `thing::What`
94+
trait KeyMustBeIdentifier {}
95+
96+
#[rustc_on_unimplemented(on(thing::What = "value", message = "y"))]
97+
//~^ ERROR expected an identifier inside this `on`-clause
98+
//~^^ NOTE expected an identifier here, not `thing::What`
99+
trait KeyMustBeIdentifier2 {}
100+
101+
#[rustc_on_unimplemented(on(aaaaaaaaaaaaaa(a, b), message = "y"))]
102+
//~^ ERROR this predicate is invalid
103+
//~^^ NOTE expected one of `any`, `all` or `not` here, not `aaaaaaaaaaaaaa`
104+
trait InvalidPredicate {}
105+
106+
#[rustc_on_unimplemented(on(something, message = "y"))]
107+
//~^ ERROR invalid flag in `on`-clause
108+
//~^^ NOTE expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something`
109+
trait InvalidFlag {}
Lines changed: 83 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: malformed `rustc_on_unimplemented` attribute input
2-
--> $DIR/bad-annotation.rs:17:1
2+
--> $DIR/bad-annotation.rs:15:1
33
|
44
LL | #[rustc_on_unimplemented]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,72 +12,120 @@ LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*
1212
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1313

1414
error[E0230]: cannot find parameter C on this trait
15-
--> $DIR/bad-annotation.rs:22:90
15+
--> $DIR/bad-annotation.rs:19:90
1616
|
1717
LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
1818
| ^
1919

2020
error[E0231]: positional format arguments are not allowed here
21-
--> $DIR/bad-annotation.rs:27:90
21+
--> $DIR/bad-annotation.rs:23:90
2222
|
2323
LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
2424
| ^
2525

26-
error[E0232]: this attribute must have a valid value
27-
--> $DIR/bad-annotation.rs:32:26
26+
error[E0232]: this attribute must have a value
27+
--> $DIR/bad-annotation.rs:27:26
2828
|
29-
LL | #[rustc_on_unimplemented(lorem="")]
30-
| ^^^^^^^^ expected value here
29+
LL | #[rustc_on_unimplemented(lorem = "")]
30+
| ^^^^^^^^^^ expected value here
3131
|
32-
= note: eg `#[rustc_on_unimplemented(message="foo")]`
32+
= note: e.g. `#[rustc_on_unimplemented(message="foo")]`
3333

34-
error[E0232]: this attribute must have a valid value
35-
--> $DIR/bad-annotation.rs:36:26
34+
error[E0232]: this attribute must have a value
35+
--> $DIR/bad-annotation.rs:33:26
3636
|
3737
LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
3838
| ^^^^^^^^^^^^^^^^^^^ expected value here
3939
|
40-
= note: eg `#[rustc_on_unimplemented(message="foo")]`
40+
= note: e.g. `#[rustc_on_unimplemented(message="foo")]`
4141

42-
error[E0232]: this attribute must have a valid value
43-
--> $DIR/bad-annotation.rs:40:39
42+
error[E0232]: this attribute must have a value
43+
--> $DIR/bad-annotation.rs:39:41
4444
|
45-
LL | #[rustc_on_unimplemented(message="x", message="y")]
46-
| ^^^^^^^^^^^ expected value here
45+
LL | #[rustc_on_unimplemented(message = "x", message = "y")]
46+
| ^^^^^^^^^^^^^ expected value here
4747
|
48-
= note: eg `#[rustc_on_unimplemented(message="foo")]`
48+
= note: e.g. `#[rustc_on_unimplemented(message="foo")]`
4949

50-
error[E0232]: this attribute must have a valid value
51-
--> $DIR/bad-annotation.rs:44:39
50+
error[E0232]: this attribute must have a value
51+
--> $DIR/bad-annotation.rs:45:41
5252
|
53-
LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
54-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
53+
LL | #[rustc_on_unimplemented(message = "x", on(desugared, message = "y"))]
54+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
5555
|
56-
= note: eg `#[rustc_on_unimplemented(message="foo")]`
56+
= note: e.g. `#[rustc_on_unimplemented(message="foo")]`
5757

5858
error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]`
59-
--> $DIR/bad-annotation.rs:48:26
59+
--> $DIR/bad-annotation.rs:51:26
60+
|
61+
LL | #[rustc_on_unimplemented(on(), message = "y")]
62+
| ^^^^ empty `on`-clause here
63+
64+
error[E0232]: this attribute must have a value
65+
--> $DIR/bad-annotation.rs:56:26
66+
|
67+
LL | #[rustc_on_unimplemented(on = "x", message = "y")]
68+
| ^^^^^^^^ expected value here
69+
|
70+
= note: e.g. `#[rustc_on_unimplemented(message="foo")]`
71+
72+
error[E0232]: this attribute must have a value
73+
--> $DIR/bad-annotation.rs:65:46
74+
|
75+
LL | #[rustc_on_unimplemented(on(from_desugaring, on(from_desugaring, message = "x")), message = "y")]
76+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
77+
|
78+
= note: e.g. `#[rustc_on_unimplemented(message="foo")]`
79+
80+
error[E0232]: literals inside `on`-clauses are not supported
81+
--> $DIR/bad-annotation.rs:71:29
6082
|
61-
LL | #[rustc_on_unimplemented(on(), message="y")]
62-
| ^^^^ empty on-clause here
83+
LL | #[rustc_on_unimplemented(on("y", message = "y"))]
84+
| ^^^ unexpected literal here
6385

64-
error[E0232]: this attribute must have a valid value
65-
--> $DIR/bad-annotation.rs:52:26
86+
error[E0232]: literals inside `on`-clauses are not supported
87+
--> $DIR/bad-annotation.rs:76:29
6688
|
67-
LL | #[rustc_on_unimplemented(on="x", message="y")]
68-
| ^^^^^^ expected value here
89+
LL | #[rustc_on_unimplemented(on(42, message = "y"))]
90+
| ^^ unexpected literal here
91+
92+
error[E0232]: expected a single predicate in `not(..)`
93+
--> $DIR/bad-annotation.rs:81:33
6994
|
70-
= note: eg `#[rustc_on_unimplemented(message="foo")]`
95+
LL | #[rustc_on_unimplemented(on(not(a, b), message = "y"))]
96+
| ^^^^ unexpected quantity of predicates here
7197

72-
error[E0232]: this attribute must have a valid value
73-
--> $DIR/bad-annotation.rs:59:40
98+
error[E0232]: expected a single predicate in `not(..)`
99+
--> $DIR/bad-annotation.rs:86:29
74100
|
75-
LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
76-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
101+
LL | #[rustc_on_unimplemented(on(not(), message = "y"))]
102+
| ^^^^^ unexpected quantity of predicates here
103+
104+
error[E0232]: expected an identifier inside this `on`-clause
105+
--> $DIR/bad-annotation.rs:91:29
106+
|
107+
LL | #[rustc_on_unimplemented(on(thing::What, message = "y"))]
108+
| ^^^^^^^^^^^ expected an identifier here, not `thing::What`
109+
110+
error[E0232]: expected an identifier inside this `on`-clause
111+
--> $DIR/bad-annotation.rs:96:29
112+
|
113+
LL | #[rustc_on_unimplemented(on(thing::What = "value", message = "y"))]
114+
| ^^^^^^^^^^^ expected an identifier here, not `thing::What`
115+
116+
error[E0232]: this predicate is invalid
117+
--> $DIR/bad-annotation.rs:101:29
118+
|
119+
LL | #[rustc_on_unimplemented(on(aaaaaaaaaaaaaa(a, b), message = "y"))]
120+
| ^^^^^^^^^^^^^^ expected one of `any`, `all` or `not` here, not `aaaaaaaaaaaaaa`
121+
122+
error[E0232]: invalid flag in `on`-clause
123+
--> $DIR/bad-annotation.rs:106:29
77124
|
78-
= note: eg `#[rustc_on_unimplemented(message="foo")]`
125+
LL | #[rustc_on_unimplemented(on(something, message = "y"))]
126+
| ^^^^^^^^^ expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something`
79127

80-
error: aborting due to 10 previous errors
128+
error: aborting due to 18 previous errors
81129

82130
Some errors have detailed explanations: E0230, E0231, E0232.
83131
For more information about an error, try `rustc --explain E0230`.

0 commit comments

Comments
 (0)
Please sign in to comment.