1use rustc_ast::{MetaItemInner, MetaItemKind, MetaItemLit};
2use rustc_parse_format::{ParseMode, Parser, Piece, Position};
3use rustc_span::{DesugaringKind, Ident, Span, Symbol, kw, sym};
4
5use crate::errors::InvalidOnClause;
6
7#[derive(#[automatically_derived]
impl ::core::fmt::Debug for OnUnimplementedCondition {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"OnUnimplementedCondition", "span", &self.span, "pred",
&&self.pred)
}
}Debug)]
9pub(crate) struct OnUnimplementedCondition {
10 span: Span,
11 pred: Predicate,
12}
13
14impl 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(
30 input: &MetaItemInner,
31 generics: &[Symbol],
32 ) -> Result<Self, InvalidOnClause> {
33 let span = input.span();
34 let pred = Predicate::parse(input, generics)?;
35 Ok(OnUnimplementedCondition { span, pred })
36 }
37}
38
39#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Predicate {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Predicate::Flag(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Flag",
&__self_0),
Predicate::Match(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Match",
&__self_0),
Predicate::Not(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Not",
&__self_0),
Predicate::All(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "All",
&__self_0),
Predicate::Any(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Any",
&__self_0),
}
}
}Debug)]
44enum Predicate {
45 Flag(Flag),
47 Match(NameValue),
49 Not(Box<Predicate>),
51 All(Vec<Predicate>),
53 Any(Vec<Predicate>),
55}
56
57impl Predicate {
58 fn parse(input: &MetaItemInner, generics: &[Symbol]) -> Result<Self, InvalidOnClause> {
59 let meta_item = match input {
60 MetaItemInner::MetaItem(meta_item) => meta_item,
61 MetaItemInner::Lit(lit) => {
62 return Err(InvalidOnClause::UnsupportedLiteral { span: lit.span });
63 }
64 };
65
66 let Some(predicate) = meta_item.ident() else {
67 return Err(InvalidOnClause::ExpectedIdentifier {
68 span: meta_item.path.span,
69 path: meta_item.path.clone(),
70 });
71 };
72
73 match meta_item.kind {
74 MetaItemKind::List(ref mis) => match predicate.name {
75 sym::any => Ok(Predicate::Any(Predicate::parse_sequence(mis, generics)?)),
76 sym::all => Ok(Predicate::All(Predicate::parse_sequence(mis, generics)?)),
77 sym::not => match &**mis {
78 [one] => Ok(Predicate::Not(Box::new(Predicate::parse(one, generics)?))),
79 [first, .., last] => Err(InvalidOnClause::ExpectedOnePredInNot {
80 span: first.span().to(last.span()),
81 }),
82 [] => Err(InvalidOnClause::ExpectedOnePredInNot { span: meta_item.span }),
83 },
84 invalid_pred => {
85 Err(InvalidOnClause::InvalidPredicate { span: predicate.span, invalid_pred })
86 }
87 },
88 MetaItemKind::NameValue(MetaItemLit { symbol, .. }) => {
89 let name = Name::parse(predicate, generics)?;
90 let value = FilterFormatString::parse(symbol);
91 let kv = NameValue { name, value };
92 Ok(Predicate::Match(kv))
93 }
94 MetaItemKind::Word => {
95 let flag = Flag::parse(predicate)?;
96 Ok(Predicate::Flag(flag))
97 }
98 }
99 }
100
101 fn parse_sequence(
102 sequence: &[MetaItemInner],
103 generics: &[Symbol],
104 ) -> Result<Vec<Self>, InvalidOnClause> {
105 sequence.iter().map(|item| Predicate::parse(item, generics)).collect()
106 }
107
108 fn eval(&self, eval: &mut impl FnMut(FlagOrNv<'_>) -> bool) -> bool {
109 match self {
110 Predicate::Flag(flag) => eval(FlagOrNv::Flag(flag)),
111 Predicate::Match(nv) => eval(FlagOrNv::NameValue(nv)),
112 Predicate::Not(not) => !not.eval(eval),
113 Predicate::All(preds) => preds.into_iter().all(|pred| pred.eval(eval)),
114 Predicate::Any(preds) => preds.into_iter().any(|pred| pred.eval(eval)),
115 }
116 }
117}
118
119#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Flag {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Flag::CrateLocal => "CrateLocal",
Flag::Direct => "Direct",
Flag::FromDesugaring => "FromDesugaring",
})
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Flag {
#[inline]
fn clone(&self) -> Flag { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Flag { }Copy)]
121enum Flag {
122 CrateLocal,
125 Direct,
127 FromDesugaring,
130}
131
132impl Flag {
133 fn parse(Ident { name, span }: Ident) -> Result<Self, InvalidOnClause> {
134 match name {
135 sym::crate_local => Ok(Flag::CrateLocal),
136 sym::direct => Ok(Flag::Direct),
137 sym::from_desugaring => Ok(Flag::FromDesugaring),
138 invalid_flag => Err(InvalidOnClause::InvalidFlag { invalid_flag, span }),
139 }
140 }
141}
142
143#[derive(#[automatically_derived]
impl ::core::fmt::Debug for NameValue {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "NameValue",
"name", &self.name, "value", &&self.value)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for NameValue {
#[inline]
fn clone(&self) -> NameValue {
NameValue {
name: ::core::clone::Clone::clone(&self.name),
value: ::core::clone::Clone::clone(&self.value),
}
}
}Clone)]
147struct NameValue {
148 name: Name,
149 value: FilterFormatString,
153}
154
155#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Name {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Name::Cause => ::core::fmt::Formatter::write_str(f, "Cause"),
Name::FromDesugaring =>
::core::fmt::Formatter::write_str(f, "FromDesugaring"),
Name::SelfUpper =>
::core::fmt::Formatter::write_str(f, "SelfUpper"),
Name::GenericArg(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"GenericArg", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Name {
#[inline]
fn clone(&self) -> Name {
let _: ::core::clone::AssertParamIsClone<Symbol>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Name { }Copy)]
157enum Name {
158 Cause,
159 FromDesugaring,
160 SelfUpper,
161 GenericArg(Symbol),
162}
163
164impl Name {
165 fn parse(Ident { name, span }: Ident, generics: &[Symbol]) -> Result<Self, InvalidOnClause> {
166 match name {
167 kw::SelfUpper => Ok(Name::SelfUpper),
168 sym::from_desugaring => Ok(Name::FromDesugaring),
169 sym::cause => Ok(Name::Cause),
170 generic if generics.contains(&generic) => Ok(Name::GenericArg(generic)),
171 invalid_name => Err(InvalidOnClause::InvalidName { invalid_name, span }),
172 }
173 }
174}
175
176#[derive(#[automatically_derived]
impl<'p> ::core::fmt::Debug for FlagOrNv<'p> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
FlagOrNv::Flag(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Flag",
&__self_0),
FlagOrNv::NameValue(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"NameValue", &__self_0),
}
}
}Debug, #[automatically_derived]
impl<'p> ::core::clone::Clone for FlagOrNv<'p> {
#[inline]
fn clone(&self) -> FlagOrNv<'p> {
match self {
FlagOrNv::Flag(__self_0) =>
FlagOrNv::Flag(::core::clone::Clone::clone(__self_0)),
FlagOrNv::NameValue(__self_0) =>
FlagOrNv::NameValue(::core::clone::Clone::clone(__self_0)),
}
}
}Clone)]
177enum FlagOrNv<'p> {
178 Flag(&'p Flag),
179 NameValue(&'p NameValue),
180}
181
182#[derive(#[automatically_derived]
impl ::core::fmt::Debug for FilterFormatString {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"FilterFormatString", "pieces", &&self.pieces)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for FilterFormatString {
#[inline]
fn clone(&self) -> FilterFormatString {
FilterFormatString {
pieces: ::core::clone::Clone::clone(&self.pieces),
}
}
}Clone)]
189struct FilterFormatString {
190 pieces: Vec<LitOrArg>,
191}
192
193#[derive(#[automatically_derived]
impl ::core::fmt::Debug for LitOrArg {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
LitOrArg::Lit(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Lit",
&__self_0),
LitOrArg::Arg(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Arg",
&__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for LitOrArg {
#[inline]
fn clone(&self) -> LitOrArg {
match self {
LitOrArg::Lit(__self_0) =>
LitOrArg::Lit(::core::clone::Clone::clone(__self_0)),
LitOrArg::Arg(__self_0) =>
LitOrArg::Arg(::core::clone::Clone::clone(__self_0)),
}
}
}Clone)]
194enum LitOrArg {
195 Lit(String),
196 Arg(String),
197}
198
199impl FilterFormatString {
200 fn parse(input: Symbol) -> Self {
201 let pieces = Parser::new(input.as_str(), None, None, false, ParseMode::Diagnostic)
202 .map(|p| match p {
203 Piece::Lit(s) => LitOrArg::Lit(s.to_owned()),
204 Piece::NextArgument(a) => match a.position {
206 Position::ArgumentNamed(arg @ "integer" | arg @ "integral" | arg @ "float") => {
213 LitOrArg::Lit(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", arg))
})format!("{{{arg}}}"))
214 }
215
216 Position::ArgumentNamed(arg) => LitOrArg::Arg(arg.to_owned()),
218
219 Position::ArgumentImplicitlyIs(_) => LitOrArg::Lit(String::from("{}")),
221 Position::ArgumentIs(idx) => LitOrArg::Lit(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}}}", idx))
})format!("{{{idx}}}")),
222 },
223 })
224 .collect();
225 Self { pieces }
226 }
227
228 fn format(&self, generic_args: &[(Symbol, String)]) -> String {
229 let mut ret = String::new();
230
231 for piece in &self.pieces {
232 match piece {
233 LitOrArg::Lit(s) => ret.push_str(s),
234 LitOrArg::Arg(arg) => {
235 let s = Symbol::intern(arg);
236 match generic_args.iter().find(|(k, _)| *k == s) {
237 Some((_, val)) => ret.push_str(val),
238 None => {
239 let _ = std::fmt::write(&mut ret, format_args!("{{{0}}}", s)format_args!("{{{s}}}"));
242 }
243 }
244 }
245 }
246 }
247
248 ret
249 }
250}
251
252#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ConditionOptions {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["self_types", "from_desugaring", "cause", "crate_local",
"direct", "generic_args"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.self_types, &self.from_desugaring, &self.cause,
&self.crate_local, &self.direct, &&self.generic_args];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"ConditionOptions", names, values)
}
}Debug)]
292pub(crate) struct ConditionOptions {
293 pub(crate) self_types: Vec<String>,
295 pub(crate) from_desugaring: Option<DesugaringKind>,
297 pub(crate) cause: Option<String>,
299 pub(crate) crate_local: bool,
300 pub(crate) direct: bool,
302 pub(crate) generic_args: Vec<(Symbol, String)>,
304}
305
306impl ConditionOptions {
307 fn has_flag(&self, name: Flag) -> bool {
308 match name {
309 Flag::CrateLocal => self.crate_local,
310 Flag::Direct => self.direct,
311 Flag::FromDesugaring => self.from_desugaring.is_some(),
312 }
313 }
314 fn contains(&self, name: Name, value: String) -> bool {
315 match name {
316 Name::SelfUpper => self.self_types.contains(&value),
317 Name::FromDesugaring => self.from_desugaring.is_some_and(|ds| ds.matches(&value)),
318 Name::Cause => self.cause == Some(value),
319 Name::GenericArg(arg) => self.generic_args.contains(&(arg, value)),
320 }
321 }
322}