rust-proptest-derive-upgrade-to-stable-proc-macro-ecosyst.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. From 7bb86b288150850657052a9f08ebe52e999c4369 Mon Sep 17 00:00:00 2001
  2. Message-Id: <7bb86b288150850657052a9f08ebe52e999c4369.1653424146.git.h.goebel@crazy-compilers.com>
  3. From: Nikhil Benesch <nikhil.benesch@gmail.com>
  4. Date: Wed, 6 Apr 2022 09:54:56 -0400
  5. Subject: [PATCH] proptest-derive: upgrade to stable proc macro ecosystem
  6. Upgrade proptest-derive to the stable versions of proc-macro2, syn, and
  7. quote.
  8. Taken from https://github.com/AltSysrq/proptest/pull/264
  9. which is based on proptest-derive 0.3.0,
  10. adjusted for guix by Hartmut Goebel.
  11. ---
  12. Cargo.toml | 6 +-
  13. src/ast.rs | 2 +-
  14. src/attr.rs | 58 ++++++++--------
  15. src/error.rs | 24 +++----
  16. src/interp.rs | 125 +---------------------------------
  17. 5 files changed, 47 insertions(+), 168 deletions(-)
  18. diff --git a/src/ast.rs b/src/ast.rs
  19. index 971eb65..3786fbb 100644
  20. --- a/src/ast.rs
  21. +++ b/src/ast.rs
  22. @@ -805,6 +805,6 @@ struct Tuple<I>(I);
  23. impl<T: ToTokens, I: Clone + IntoIterator<Item = T>> ToTokens for Tuple<I> {
  24. fn to_tokens(&self, tokens: &mut TokenStream) {
  25. let iter = self.0.clone();
  26. - quote_append!(tokens, ( #(#iter),* ) );
  27. + tokens.append_all(iter);
  28. }
  29. }
  30. diff --git a/src/attr.rs b/src/attr.rs
  31. index 97c3dc3..59ef134 100644
  32. --- a/src/attr.rs
  33. +++ b/src/attr.rs
  34. @@ -8,7 +8,7 @@
  35. //! Provides a parser from syn attributes to our logical model.
  36. -use syn::{self, Attribute, Expr, Ident, Lit, Meta, NestedMeta, Type};
  37. +use syn::{self, Attribute, Expr, Lit, Meta, NestedMeta, Type, Path};
  38. use crate::error::{self, Ctx, DeriveResult};
  39. use crate::interp;
  40. @@ -221,7 +221,7 @@ fn extract_modifiers(ctx: Ctx, attr: &Attribute) -> Vec<Meta> {
  41. error::inner_attr(ctx);
  42. }
  43. - match attr.interpret_meta() {
  44. + match attr.parse_meta().ok() {
  45. Some(Meta::List(list)) => {
  46. return list
  47. .nested
  48. @@ -229,7 +229,7 @@ fn extract_modifiers(ctx: Ctx, attr: &Attribute) -> Vec<Meta> {
  49. .filter_map(|nm| extract_metas(ctx, nm))
  50. .collect()
  51. }
  52. - Some(Meta::Word(_)) => error::bare_proptest_attr(ctx),
  53. + Some(Meta::Path(_)) => error::bare_proptest_attr(ctx),
  54. Some(Meta::NameValue(_)) => error::literal_set_proptest(ctx),
  55. None => error::no_interp_meta(ctx),
  56. }
  57. @@ -239,7 +239,7 @@ fn extract_modifiers(ctx: Ctx, attr: &Attribute) -> Vec<Meta> {
  58. fn extract_metas(ctx: Ctx, nested: NestedMeta) -> Option<Meta> {
  59. match nested {
  60. - NestedMeta::Literal(_) => {
  61. + NestedMeta::Lit(_) => {
  62. error::immediate_literals(ctx);
  63. None
  64. }
  65. @@ -263,21 +263,21 @@ fn is_outer_attr(attr: &Attribute) -> bool {
  66. /// let's them add stuff into our accumulartor.
  67. fn dispatch_attribute(ctx: Ctx, mut acc: ParseAcc, meta: Meta) -> ParseAcc {
  68. // Dispatch table for attributes:
  69. - let name = meta.name().to_string();
  70. - let name = name.as_ref();
  71. - match name {
  72. + let name = meta.path().get_ident().map(|id| id.to_string());
  73. + match name.as_deref() {
  74. // Valid modifiers:
  75. - "skip" => parse_skip(ctx, &mut acc, meta),
  76. - "w" | "weight" => parse_weight(ctx, &mut acc, &meta),
  77. - "no_params" => parse_no_params(ctx, &mut acc, meta),
  78. - "params" => parse_params(ctx, &mut acc, meta),
  79. - "strategy" => parse_strategy(ctx, &mut acc, &meta),
  80. - "value" => parse_value(ctx, &mut acc, &meta),
  81. - "regex" => parse_regex(ctx, &mut acc, &meta),
  82. - "filter" => parse_filter(ctx, &mut acc, &meta),
  83. - "no_bound" => parse_no_bound(ctx, &mut acc, meta),
  84. + Some("skip") => parse_skip(ctx, &mut acc, meta),
  85. + Some("w") | Some("weight") => parse_weight(ctx, &mut acc, &meta),
  86. + Some("no_params") => parse_no_params(ctx, &mut acc, meta),
  87. + Some("params") => parse_params(ctx, &mut acc, meta),
  88. + Some("strategy") => parse_strategy(ctx, &mut acc, &meta),
  89. + Some("value") => parse_value(ctx, &mut acc, &meta),
  90. + Some("regex") => parse_regex(ctx, &mut acc, &meta),
  91. + Some("filter") => parse_filter(ctx, &mut acc, &meta),
  92. + Some("no_bound") => parse_no_bound(ctx, &mut acc, meta),
  93. // Invalid modifiers:
  94. - name => dispatch_unknown_mod(ctx, name),
  95. + Some(name) => dispatch_unknown_mod(ctx, name),
  96. + None => error::unkown_modifier(ctx, &format!("{:?}", meta.path())),
  97. }
  98. acc
  99. }
  100. @@ -368,7 +368,7 @@ fn parse_weight(ctx: Ctx, acc: &mut ParseAcc, meta: &Meta) {
  101. fn parse_filter(ctx: Ctx, acc: &mut ParseAcc, meta: &Meta) {
  102. if let Some(filter) = match normalize_meta(meta.clone()) {
  103. Some(NormMeta::Lit(Lit::Str(lit))) => lit.parse().ok(),
  104. - Some(NormMeta::Word(ident)) => Some(parse_quote!( #ident )),
  105. + Some(NormMeta::Path(path)) => Some(parse_quote!( #path )),
  106. _ => None,
  107. } {
  108. acc.filter.push(filter);
  109. @@ -390,7 +390,7 @@ fn parse_regex(ctx: Ctx, acc: &mut ParseAcc, meta: &Meta) {
  110. error_if_set(ctx, &acc.regex, &meta);
  111. if let expr @ Some(_) = match normalize_meta(meta.clone()) {
  112. - Some(NormMeta::Word(fun)) => Some(function_call(fun)),
  113. + Some(NormMeta::Path(fun)) => Some(function_call(fun)),
  114. Some(NormMeta::Lit(lit @ Lit::Str(_))) => Some(lit_to_expr(lit)),
  115. _ => None,
  116. } {
  117. @@ -433,7 +433,7 @@ fn parse_strategy_base(ctx: Ctx, loc: &mut Option<Expr>, meta: &Meta) {
  118. error_if_set(ctx, &loc, &meta);
  119. if let expr @ Some(_) = match normalize_meta(meta.clone()) {
  120. - Some(NormMeta::Word(fun)) => Some(function_call(fun)),
  121. + Some(NormMeta::Path(fun)) => Some(function_call(fun)),
  122. Some(NormMeta::Lit(lit)) => extract_expr(lit),
  123. _ => None,
  124. } {
  125. @@ -493,7 +493,7 @@ fn parse_params(ctx: Ctx, acc: &mut ParseAcc, meta: Meta) {
  126. let typ = match normalize_meta(meta) {
  127. // Form is: `#[proptest(params(<type>)]`.
  128. - Some(NormMeta::Word(ident)) => Some(ident_to_type(ident)),
  129. + Some(NormMeta::Path(path)) => Some(path_to_type(path)),
  130. // Form is: `#[proptest(params = "<type>"]` or,
  131. // Form is: `#[proptest(params("<type>")]`..
  132. Some(NormMeta::Lit(Lit::Str(lit))) => lit.parse().ok(),
  133. @@ -546,11 +546,11 @@ fn error_if_set<T>(ctx: Ctx, loc: &Option<T>, meta: &Meta) {
  134. }
  135. }
  136. -/// Constructs a type out of an identifier.
  137. -fn ident_to_type(ident: Ident) -> Type {
  138. +/// Constructs a type out of a path.
  139. +fn path_to_type(path: Path) -> Type {
  140. Type::Path(syn::TypePath {
  141. qself: None,
  142. - path: ident.into(),
  143. + path,
  144. })
  145. }
  146. @@ -579,7 +579,7 @@ fn lit_to_expr(lit: Lit) -> Expr {
  147. }
  148. /// Construct a function call expression for an identifier.
  149. -fn function_call(fun: Ident) -> Expr {
  150. +fn function_call(fun: Path) -> Expr {
  151. parse_quote!( #fun() )
  152. }
  153. @@ -591,19 +591,19 @@ enum NormMeta {
  154. /// Accepts: `#[proptest(<word> = <lit>)]` and `#[proptest(<word>(<lit>))]`
  155. Lit(Lit),
  156. /// Accepts: `#[proptest(<word>(<word>))`.
  157. - Word(Ident),
  158. + Path(Path),
  159. }
  160. /// Normalize a `meta: Meta` into the forms accepted in `#[proptest(<meta>)]`.
  161. fn normalize_meta(meta: Meta) -> Option<NormMeta> {
  162. Some(match meta {
  163. - Meta::Word(_) => NormMeta::Plain,
  164. + Meta::Path(_) => NormMeta::Plain,
  165. Meta::NameValue(nv) => NormMeta::Lit(nv.lit),
  166. Meta::List(ml) => {
  167. if let Some(nm) = util::match_singleton(ml.nested) {
  168. match nm {
  169. - NestedMeta::Literal(lit) => NormMeta::Lit(lit),
  170. - NestedMeta::Meta(Meta::Word(word)) => NormMeta::Word(word),
  171. + NestedMeta::Lit(lit) => NormMeta::Lit(lit),
  172. + NestedMeta::Meta(Meta::Path(path)) => NormMeta::Path(path),
  173. _ => return None,
  174. }
  175. } else {
  176. diff --git a/src/error.rs b/src/error.rs
  177. index a59963b..deebde2 100644
  178. --- a/src/error.rs
  179. +++ b/src/error.rs
  180. @@ -426,9 +426,9 @@ error!(
  181. error!(
  182. set_again(meta: &syn::Meta),
  183. E0017,
  184. - "The attribute modifier `{}` inside `#[proptest(..)]` has already been \
  185. + "The attribute modifier `{:?}` inside `#[proptest(..)]` has already been \
  186. set. To fix the error, please remove at least one such modifier.",
  187. - meta.name()
  188. + meta.path()
  189. );
  190. // Happens when `<modifier>` in `#[proptest(<modifier>)]` is unknown to
  191. @@ -472,11 +472,11 @@ error!(
  192. error!(
  193. weight_malformed(meta: &syn::Meta),
  194. E0021,
  195. - "The attribute modifier `{0}` inside `#[proptest(..)]` must have the \
  196. - format `#[proptest({0} = <integer>)]` where `<integer>` is an integer that \
  197. - fits within a `u32`. An example: `#[proptest({0} = 2)]` to set a relative \
  198. + "The attribute modifier `{0:?}` inside `#[proptest(..)]` must have the \
  199. + format `#[proptest({0:?} = <integer>)]` where `<integer>` is an integer that \
  200. + fits within a `u32`. An example: `#[proptest({0:?} = 2)]` to set a relative \
  201. weight of 2.",
  202. - meta.name()
  203. + meta.path()
  204. );
  205. // Happens when both `#[proptest(params = "<type>")]` and
  206. @@ -526,10 +526,10 @@ fatal!(
  207. error!(
  208. strategy_malformed(meta: &syn::Meta),
  209. E0026,
  210. - "The attribute modifier `{0}` inside `#[proptest(..)]` must have the \
  211. - format `#[proptest({0} = \"<expr>\")]` where `<expr>` is a valid Rust \
  212. + "The attribute modifier `{0:?}` inside `#[proptest(..)]` must have the \
  213. + format `#[proptest({0:?} = \"<expr>\")]` where `<expr>` is a valid Rust \
  214. expression.",
  215. - meta.name()
  216. + meta.path()
  217. );
  218. // Happens when `#[proptest(filter..)]` is malformed.
  219. @@ -538,10 +538,10 @@ error!(
  220. error!(
  221. filter_malformed(meta: &syn::Meta),
  222. E0027,
  223. - "The attribute modifier `{0}` inside `#[proptest(..)]` must have the \
  224. - format `#[proptest({0} = \"<expr>\")]` where `<expr>` is a valid Rust \
  225. + "The attribute modifier `{0:?}` inside `#[proptest(..)]` must have the \
  226. + format `#[proptest({0:?} = \"<expr>\")]` where `<expr>` is a valid Rust \
  227. expression.",
  228. - meta.name()
  229. + meta.path()
  230. );
  231. // Any attributes on a skipped variant has no effect - so we emit this error
  232. diff --git a/src/interp.rs b/src/interp.rs
  233. index 594c5d8..34f0968 100644
  234. --- a/src/interp.rs
  235. +++ b/src/interp.rs
  236. @@ -6,134 +6,13 @@
  237. // option. This file may not be copied, modified, or distributed
  238. // except according to those terms.
  239. -use syn::{self, BinOp as B, Expr as E, IntSuffix as IS, Lit as L, UnOp as U};
  240. -
  241. -/// Adapted from https://docs.rs/syn/0.14.2/src/syn/lit.rs.html#943 to accept
  242. -/// u128.
  243. -fn parse_lit_int(mut s: &str) -> Option<u128> {
  244. - /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
  245. - /// past the end of the input buffer.
  246. - pub fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
  247. - let s = s.as_ref();
  248. - if idx < s.len() {
  249. - s[idx]
  250. - } else {
  251. - 0
  252. - }
  253. - }
  254. -
  255. - let base = match (byte(s, 0), byte(s, 1)) {
  256. - (b'0', b'x') => {
  257. - s = &s[2..];
  258. - 16
  259. - }
  260. - (b'0', b'o') => {
  261. - s = &s[2..];
  262. - 8
  263. - }
  264. - (b'0', b'b') => {
  265. - s = &s[2..];
  266. - 2
  267. - }
  268. - (b'0'..=b'9', _) => 10,
  269. - _ => unreachable!(),
  270. - };
  271. -
  272. - let mut value = 0u128;
  273. - loop {
  274. - let b = byte(s, 0);
  275. - let digit = match b {
  276. - b'0'..=b'9' => u128::from(b - b'0'),
  277. - b'a'..=b'f' if base > 10 => 10 + u128::from(b - b'a'),
  278. - b'A'..=b'F' if base > 10 => 10 + u128::from(b - b'A'),
  279. - b'_' => {
  280. - s = &s[1..];
  281. - continue;
  282. - }
  283. - // NOTE: Looking at a floating point literal, we don't want to
  284. - // consider these integers.
  285. - b'.' if base == 10 => return None,
  286. - b'e' | b'E' if base == 10 => return None,
  287. - _ => break,
  288. - };
  289. -
  290. - if digit >= base {
  291. - panic!("Unexpected digit {:x} out of base range", digit);
  292. - }
  293. -
  294. - value = value.checked_mul(base)?.checked_add(digit)?;
  295. - s = &s[1..];
  296. - }
  297. -
  298. - Some(value)
  299. -}
  300. -
  301. -/// Parse a suffix of an integer literal.
  302. -fn parse_suffix(lit: &str) -> IS {
  303. - [
  304. - ("i8", IS::I8),
  305. - ("i16", IS::I16),
  306. - ("i32", IS::I32),
  307. - ("i64", IS::I64),
  308. - ("i128", IS::I128),
  309. - ("isize", IS::Isize),
  310. - ("u8", IS::U8),
  311. - ("u16", IS::U16),
  312. - ("u32", IS::U32),
  313. - ("u64", IS::U64),
  314. - ("u128", IS::U128),
  315. - ("usize", IS::Usize),
  316. - ]
  317. - .iter()
  318. - .find(|&(s, _)| lit.ends_with(s))
  319. - .map(|(_, suffix)| suffix.clone())
  320. - .unwrap_or(IS::None)
  321. -}
  322. -
  323. -/// Interprets an integer literal in a string.
  324. -fn eval_str_int(lit: &str) -> Option<u128> {
  325. - use std::{i128, i16, i32, i64, i8, u16, u32, u64, u8};
  326. - use syn::IntSuffix::*;
  327. -
  328. - let val = parse_lit_int(lit)?;
  329. - Some(match parse_suffix(lit) {
  330. - None => val,
  331. - I8 if val <= i8::MAX as u128 => val,
  332. - I16 if val <= i16::MAX as u128 => val,
  333. - I32 if val <= i32::MAX as u128 => val,
  334. - I64 if val <= i64::MAX as u128 => val,
  335. - U8 if val <= u128::from(u8::MAX) => val,
  336. - U16 if val <= u128::from(u16::MAX) => val,
  337. - U32 if val <= u128::from(u32::MAX) => val,
  338. - U64 if val <= u128::from(u64::MAX) => val,
  339. - Usize if val <= u128::max_value() => val,
  340. - Isize if val <= i128::max_value() as u128 => val,
  341. - U128 => val,
  342. - I128 if val <= i128::MAX as u128 => val,
  343. -
  344. - // Does not fit in suffix:
  345. - _ => return Option::None,
  346. - })
  347. -}
  348. -
  349. -/// Interprets an integer literal.
  350. -fn eval_lit_int(lit: &syn::LitInt) -> Option<u128> {
  351. - use quote::ToTokens;
  352. - eval_str_int(&lit.into_token_stream().to_string())
  353. -}
  354. -
  355. -/// Interprets a verbatim literal.
  356. -fn eval_lit_verbatim(lit: &syn::LitVerbatim) -> Option<u128> {
  357. - let lit = lit.token.to_string();
  358. - eval_str_int(&lit)
  359. -}
  360. +use syn::{self, BinOp as B, Expr as E, Lit as L, UnOp as U};
  361. /// Interprets a literal.
  362. fn eval_lit(lit: &syn::ExprLit) -> Option<u128> {
  363. match &lit.lit {
  364. - L::Int(lit) => eval_lit_int(lit),
  365. + L::Int(lit) => lit.base10_parse().ok(),
  366. L::Byte(lit) => Some(u128::from(lit.value())),
  367. - L::Verbatim(lit) => eval_lit_verbatim(lit),
  368. _ => None,
  369. }
  370. }
  371. --
  372. 2.30.4