mirror of https://github.com/rust-lang/rust.git
Auto merge of #117928 - nnethercote:rustc_ast_pretty, r=fee1-dead
`rustc_ast_pretty` cleanups Some improvements I found while looking at this code. r? `@fee1-dead`
This commit is contained in:
commit
cc4bb0de20
|
@ -2060,9 +2060,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
@ -3471,6 +3471,7 @@ dependencies = [
|
|||
name = "rustc_ast_pretty"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"rustc_ast",
|
||||
"rustc_span",
|
||||
"thin-vec",
|
||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
|
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
itertools = "0.11"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
thin-vec = "0.2.12"
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
#![doc(rust_logo)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(with_negative_coherence)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
mod helpers;
|
||||
|
|
|
@ -165,20 +165,20 @@ enum IndentStyle {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Default, PartialEq)]
|
||||
pub struct BreakToken {
|
||||
pub(crate) struct BreakToken {
|
||||
offset: isize,
|
||||
blank_space: isize,
|
||||
pre_break: Option<char>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct BeginToken {
|
||||
pub(crate) struct BeginToken {
|
||||
indent: IndentStyle,
|
||||
breaks: Breaks,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum Token {
|
||||
#[derive(PartialEq)]
|
||||
pub(crate) enum Token {
|
||||
// In practice a string token contains either a `&'static str` or a
|
||||
// `String`. `Cow` is overkill for this because we never modify the data,
|
||||
// but it's more convenient than rolling our own more specialized type.
|
||||
|
@ -229,7 +229,6 @@ pub struct Printer {
|
|||
last_printed: Option<Token>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct BufEntry {
|
||||
token: Token,
|
||||
size: isize,
|
||||
|
@ -251,16 +250,16 @@ impl Printer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn last_token(&self) -> Option<&Token> {
|
||||
pub(crate) fn last_token(&self) -> Option<&Token> {
|
||||
self.last_token_still_buffered().or_else(|| self.last_printed.as_ref())
|
||||
}
|
||||
|
||||
pub fn last_token_still_buffered(&self) -> Option<&Token> {
|
||||
pub(crate) fn last_token_still_buffered(&self) -> Option<&Token> {
|
||||
self.buf.last().map(|last| &last.token)
|
||||
}
|
||||
|
||||
/// Be very careful with this!
|
||||
pub fn replace_last_token_still_buffered(&mut self, token: Token) {
|
||||
pub(crate) fn replace_last_token_still_buffered(&mut self, token: Token) {
|
||||
self.buf.last_mut().unwrap().token = token;
|
||||
}
|
||||
|
||||
|
@ -314,7 +313,7 @@ impl Printer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn offset(&mut self, offset: isize) {
|
||||
pub(crate) fn offset(&mut self, offset: isize) {
|
||||
if let Some(BufEntry { token: Token::Break(token), .. }) = &mut self.buf.last_mut() {
|
||||
token.offset += offset;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ impl Printer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn hardbreak_tok_offset(off: isize) -> Token {
|
||||
pub(crate) fn hardbreak_tok_offset(off: isize) -> Token {
|
||||
Token::Break(BreakToken {
|
||||
offset: off,
|
||||
blank_space: SIZE_INFINITY,
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
mod delimited;
|
||||
//! AST pretty printing.
|
||||
//!
|
||||
//! Note that HIR pretty printing is layered on top of this crate.
|
||||
|
||||
mod expr;
|
||||
mod item;
|
||||
|
||||
|
@ -23,8 +26,6 @@ use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
|
|||
use std::borrow::Cow;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
pub use self::delimited::IterDelimited;
|
||||
|
||||
pub enum MacHeader<'a> {
|
||||
Path(&'a ast::Path),
|
||||
Keyword(&'static str),
|
||||
|
@ -46,8 +47,7 @@ pub trait PpAnn {
|
|||
fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NoAnn;
|
||||
struct NoAnn;
|
||||
|
||||
impl PpAnn for NoAnn {}
|
||||
|
||||
|
@ -64,11 +64,11 @@ impl<'a> Comments<'a> {
|
|||
}
|
||||
|
||||
// FIXME: This shouldn't probably clone lmao
|
||||
pub fn next(&self) -> Option<Comment> {
|
||||
fn next(&self) -> Option<Comment> {
|
||||
self.comments.get(self.current).cloned()
|
||||
}
|
||||
|
||||
pub fn trailing_comment(
|
||||
fn trailing_comment(
|
||||
&self,
|
||||
span: rustc_span::Span,
|
||||
next_pos: Option<BytePos>,
|
||||
|
@ -95,7 +95,7 @@ pub struct State<'a> {
|
|||
ann: &'a (dyn PpAnn + 'a),
|
||||
}
|
||||
|
||||
pub(crate) const INDENT_UNIT: isize = 4;
|
||||
const INDENT_UNIT: isize = 4;
|
||||
|
||||
/// Requires you to pass an input filename and reader so that
|
||||
/// it can scan the input text for comments to copy forward.
|
||||
|
@ -220,7 +220,7 @@ fn doc_comment_to_string(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn literal_to_string(lit: token::Lit) -> String {
|
||||
fn literal_to_string(lit: token::Lit) -> String {
|
||||
let token::Lit { kind, symbol, suffix } = lit;
|
||||
let mut out = match kind {
|
||||
token::Byte => format!("b'{symbol}'"),
|
||||
|
@ -260,11 +260,17 @@ impl std::ops::DerefMut for State<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// This trait is used for both AST and HIR pretty-printing.
|
||||
pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
|
||||
fn comments(&mut self) -> &mut Option<Comments<'a>>;
|
||||
fn print_ident(&mut self, ident: Ident);
|
||||
fn ann_post(&mut self, ident: Ident);
|
||||
fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
|
||||
|
||||
fn print_ident(&mut self, ident: Ident) {
|
||||
self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
|
||||
self.ann_post(ident)
|
||||
}
|
||||
|
||||
fn strsep<T, F>(
|
||||
&mut self,
|
||||
sep: &'static str,
|
||||
|
@ -401,15 +407,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
}
|
||||
}
|
||||
|
||||
fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) {
|
||||
self.print_token_literal(lit.as_token_lit(), lit.span)
|
||||
}
|
||||
|
||||
fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) {
|
||||
self.maybe_print_comment(span.lo());
|
||||
self.word(token_lit.to_string())
|
||||
}
|
||||
|
||||
fn print_string(&mut self, st: &str, style: ast::StrStyle) {
|
||||
let st = match style {
|
||||
ast::StrStyle::Cooked => format!("\"{}\"", st.escape_debug()),
|
||||
|
@ -420,30 +417,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
self.word(st)
|
||||
}
|
||||
|
||||
fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) {
|
||||
self.print_string(sym.as_str(), style);
|
||||
}
|
||||
|
||||
fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
|
||||
}
|
||||
|
||||
fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
|
||||
}
|
||||
|
||||
fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
|
||||
}
|
||||
|
||||
fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true)
|
||||
}
|
||||
|
||||
fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
|
||||
}
|
||||
|
||||
fn print_either_attributes(
|
||||
&mut self,
|
||||
attrs: &[ast::Attribute],
|
||||
|
@ -467,10 +448,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
printed
|
||||
}
|
||||
|
||||
fn print_attribute(&mut self, attr: &ast::Attribute) {
|
||||
self.print_attribute_inline(attr, false)
|
||||
}
|
||||
|
||||
fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) {
|
||||
if !is_inline {
|
||||
self.hardbreak_if_not_bol();
|
||||
|
@ -525,33 +502,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
self.end();
|
||||
}
|
||||
|
||||
fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {
|
||||
match item {
|
||||
ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi),
|
||||
ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_meta_item(&mut self, item: &ast::MetaItem) {
|
||||
self.ibox(INDENT_UNIT);
|
||||
match &item.kind {
|
||||
ast::MetaItemKind::Word => self.print_path(&item.path, false, 0),
|
||||
ast::MetaItemKind::NameValue(value) => {
|
||||
self.print_path(&item.path, false, 0);
|
||||
self.space();
|
||||
self.word_space("=");
|
||||
self.print_meta_item_lit(value);
|
||||
}
|
||||
ast::MetaItemKind::List(items) => {
|
||||
self.print_path(&item.path, false, 0);
|
||||
self.popen();
|
||||
self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i));
|
||||
self.pclose();
|
||||
}
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
||||
/// This doesn't deserve to be called "pretty" printing, but it should be
|
||||
/// meaning-preserving. A quick hack that might help would be to look at the
|
||||
/// spans embedded in the TTs to decide where to put spaces and newlines.
|
||||
|
@ -843,17 +793,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
Self::to_string(|s| s.print_type(ty))
|
||||
}
|
||||
|
||||
fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String {
|
||||
Self::to_string(|s| s.print_type_bounds(bounds))
|
||||
}
|
||||
|
||||
fn where_bound_predicate_to_string(
|
||||
&self,
|
||||
where_bound_predicate: &ast::WhereBoundPredicate,
|
||||
) -> String {
|
||||
Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
|
||||
}
|
||||
|
||||
fn pat_to_string(&self, pat: &ast::Pat) -> String {
|
||||
Self::to_string(|s| s.print_pat(pat))
|
||||
}
|
||||
|
@ -866,14 +805,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
Self::to_string(|s| s.print_meta_item_lit(lit))
|
||||
}
|
||||
|
||||
fn tt_to_string(&self, tt: &TokenTree) -> String {
|
||||
Self::to_string(|s| s.print_tt(tt, false))
|
||||
}
|
||||
|
||||
fn tts_to_string(&self, tokens: &TokenStream) -> String {
|
||||
Self::to_string(|s| s.print_tts(tokens, false))
|
||||
}
|
||||
|
||||
fn stmt_to_string(&self, stmt: &ast::Stmt) -> String {
|
||||
Self::to_string(|s| s.print_stmt(stmt))
|
||||
}
|
||||
|
@ -882,26 +813,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
Self::to_string(|s| s.print_item(i))
|
||||
}
|
||||
|
||||
fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String {
|
||||
Self::to_string(|s| s.print_assoc_item(i))
|
||||
}
|
||||
|
||||
fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String {
|
||||
Self::to_string(|s| s.print_foreign_item(i))
|
||||
}
|
||||
|
||||
fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String {
|
||||
Self::to_string(|s| s.print_generic_params(generic_params))
|
||||
}
|
||||
|
||||
fn path_to_string(&self, p: &ast::Path) -> String {
|
||||
Self::to_string(|s| s.print_path(p, false, 0))
|
||||
}
|
||||
|
||||
fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
|
||||
Self::to_string(|s| s.print_path_segment(p, false))
|
||||
}
|
||||
|
||||
fn vis_to_string(&self, v: &ast::Visibility) -> String {
|
||||
Self::to_string(|s| s.print_visibility(v))
|
||||
}
|
||||
|
@ -916,22 +831,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
})
|
||||
}
|
||||
|
||||
fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String {
|
||||
Self::to_string(|s| s.print_meta_list_item(li))
|
||||
}
|
||||
|
||||
fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String {
|
||||
Self::to_string(|s| s.print_attr_item(ai, ai.path.span))
|
||||
}
|
||||
|
||||
fn attribute_to_string(&self, attr: &ast::Attribute) -> String {
|
||||
Self::to_string(|s| s.print_attribute(attr))
|
||||
}
|
||||
|
||||
fn param_to_string(&self, arg: &ast::Param) -> String {
|
||||
Self::to_string(|s| s.print_param(arg, false))
|
||||
}
|
||||
|
||||
fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
|
||||
let mut printer = State::new();
|
||||
f(&mut printer);
|
||||
|
@ -944,9 +847,8 @@ impl<'a> PrintState<'a> for State<'a> {
|
|||
&mut self.comments
|
||||
}
|
||||
|
||||
fn print_ident(&mut self, ident: Ident) {
|
||||
self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
|
||||
self.ann.post(self, AnnNode::Ident(&ident))
|
||||
fn ann_post(&mut self, ident: Ident) {
|
||||
self.ann.post(self, AnnNode::Ident(&ident));
|
||||
}
|
||||
|
||||
fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) {
|
||||
|
@ -979,13 +881,8 @@ impl<'a> State<'a> {
|
|||
State { s: pp::Printer::new(), comments: None, ann: &NoAnn }
|
||||
}
|
||||
|
||||
pub(crate) fn commasep_cmnt<T, F, G>(
|
||||
&mut self,
|
||||
b: Breaks,
|
||||
elts: &[T],
|
||||
mut op: F,
|
||||
mut get_span: G,
|
||||
) where
|
||||
fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)
|
||||
where
|
||||
F: FnMut(&mut State<'_>, &T),
|
||||
G: FnMut(&T) -> rustc_span::Span,
|
||||
{
|
||||
|
@ -1005,7 +902,7 @@ impl<'a> State<'a> {
|
|||
self.end();
|
||||
}
|
||||
|
||||
pub(crate) fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
|
||||
fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
|
||||
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
|
||||
}
|
||||
|
||||
|
@ -1156,7 +1053,7 @@ impl<'a> State<'a> {
|
|||
self.print_trait_ref(&t.trait_ref)
|
||||
}
|
||||
|
||||
pub(crate) fn print_stmt(&mut self, st: &ast::Stmt) {
|
||||
fn print_stmt(&mut self, st: &ast::Stmt) {
|
||||
self.maybe_print_comment(st.span.lo());
|
||||
match &st.kind {
|
||||
ast::StmtKind::Local(loc) => {
|
||||
|
@ -1211,19 +1108,19 @@ impl<'a> State<'a> {
|
|||
self.maybe_print_trailing_comment(st.span, None)
|
||||
}
|
||||
|
||||
pub(crate) fn print_block(&mut self, blk: &ast::Block) {
|
||||
fn print_block(&mut self, blk: &ast::Block) {
|
||||
self.print_block_with_attrs(blk, &[])
|
||||
}
|
||||
|
||||
pub(crate) fn print_block_unclosed_indent(&mut self, blk: &ast::Block) {
|
||||
fn print_block_unclosed_indent(&mut self, blk: &ast::Block) {
|
||||
self.print_block_maybe_unclosed(blk, &[], false)
|
||||
}
|
||||
|
||||
pub(crate) fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) {
|
||||
fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) {
|
||||
self.print_block_maybe_unclosed(blk, attrs, true)
|
||||
}
|
||||
|
||||
pub(crate) fn print_block_maybe_unclosed(
|
||||
fn print_block_maybe_unclosed(
|
||||
&mut self,
|
||||
blk: &ast::Block,
|
||||
attrs: &[ast::Attribute],
|
||||
|
@ -1257,7 +1154,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
|
||||
/// Print a `let pat = expr` expression.
|
||||
pub(crate) fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) {
|
||||
fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) {
|
||||
self.word("let ");
|
||||
self.print_pat(pat);
|
||||
self.space();
|
||||
|
@ -1266,7 +1163,7 @@ impl<'a> State<'a> {
|
|||
self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals())
|
||||
}
|
||||
|
||||
pub(crate) fn print_mac(&mut self, m: &ast::MacCall) {
|
||||
fn print_mac(&mut self, m: &ast::MacCall) {
|
||||
self.print_mac_common(
|
||||
Some(MacHeader::Path(&m.path)),
|
||||
true,
|
||||
|
@ -1407,7 +1304,7 @@ impl<'a> State<'a> {
|
|||
self.pclose();
|
||||
}
|
||||
|
||||
pub(crate) fn print_local_decl(&mut self, loc: &ast::Local) {
|
||||
fn print_local_decl(&mut self, loc: &ast::Local) {
|
||||
self.print_pat(&loc.pat);
|
||||
if let Some(ty) = &loc.ty {
|
||||
self.word_space(":");
|
||||
|
@ -1415,7 +1312,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_name(&mut self, name: Symbol) {
|
||||
fn print_name(&mut self, name: Symbol) {
|
||||
self.word(name.to_string());
|
||||
self.ann.post(self, AnnNode::Name(&name))
|
||||
}
|
||||
|
@ -1439,7 +1336,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_pat(&mut self, pat: &ast::Pat) {
|
||||
fn print_pat(&mut self, pat: &ast::Pat) {
|
||||
self.maybe_print_comment(pat.span.lo());
|
||||
self.ann.pre(self, AnnNode::Pat(pat));
|
||||
/* Pat isn't normalized, but the beauty of it
|
||||
|
@ -1592,7 +1489,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_asyncness(&mut self, asyncness: ast::Async) {
|
||||
fn print_asyncness(&mut self, asyncness: ast::Async) {
|
||||
if asyncness.is_async() {
|
||||
self.word_nbsp("async");
|
||||
}
|
||||
|
@ -1637,11 +1534,11 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_lifetime(&mut self, lifetime: ast::Lifetime) {
|
||||
fn print_lifetime(&mut self, lifetime: ast::Lifetime) {
|
||||
self.print_name(lifetime.ident.name)
|
||||
}
|
||||
|
||||
pub(crate) fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) {
|
||||
fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) {
|
||||
for (i, bound) in bounds.iter().enumerate() {
|
||||
if i != 0 {
|
||||
self.word(" + ");
|
||||
|
@ -1653,7 +1550,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
|
||||
fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
|
||||
if generic_params.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
@ -1717,12 +1614,12 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) {
|
||||
fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) {
|
||||
self.print_mutability(mt.mutbl, print_const);
|
||||
self.print_type(&mt.ty)
|
||||
}
|
||||
|
||||
pub(crate) fn print_param(&mut self, input: &ast::Param, is_closure: bool) {
|
||||
fn print_param(&mut self, input: &ast::Param, is_closure: bool) {
|
||||
self.ibox(INDENT_UNIT);
|
||||
|
||||
self.print_outer_attributes_inline(&input.attrs);
|
||||
|
@ -1750,7 +1647,7 @@ impl<'a> State<'a> {
|
|||
self.end();
|
||||
}
|
||||
|
||||
pub(crate) fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) {
|
||||
fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) {
|
||||
if let ast::FnRetTy::Ty(ty) = fn_ret_ty {
|
||||
self.space_if_not_bol();
|
||||
self.ibox(INDENT_UNIT);
|
||||
|
@ -1761,7 +1658,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_ty_fn(
|
||||
fn print_ty_fn(
|
||||
&mut self,
|
||||
ext: ast::Extern,
|
||||
unsafety: ast::Unsafe,
|
||||
|
@ -1785,7 +1682,7 @@ impl<'a> State<'a> {
|
|||
self.end();
|
||||
}
|
||||
|
||||
pub(crate) fn print_fn_header_info(&mut self, header: ast::FnHeader) {
|
||||
fn print_fn_header_info(&mut self, header: ast::FnHeader) {
|
||||
self.print_constness(header.constness);
|
||||
self.print_asyncness(header.asyncness);
|
||||
self.print_unsafety(header.unsafety);
|
||||
|
@ -1805,24 +1702,107 @@ impl<'a> State<'a> {
|
|||
self.word("fn")
|
||||
}
|
||||
|
||||
pub(crate) fn print_unsafety(&mut self, s: ast::Unsafe) {
|
||||
fn print_unsafety(&mut self, s: ast::Unsafe) {
|
||||
match s {
|
||||
ast::Unsafe::No => {}
|
||||
ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_constness(&mut self, s: ast::Const) {
|
||||
fn print_constness(&mut self, s: ast::Const) {
|
||||
match s {
|
||||
ast::Const::No => {}
|
||||
ast::Const::Yes(_) => self.word_nbsp("const"),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_is_auto(&mut self, s: ast::IsAuto) {
|
||||
fn print_is_auto(&mut self, s: ast::IsAuto) {
|
||||
match s {
|
||||
ast::IsAuto::Yes => self.word_nbsp("auto"),
|
||||
ast::IsAuto::No => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) {
|
||||
self.print_token_literal(lit.as_token_lit(), lit.span)
|
||||
}
|
||||
|
||||
fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) {
|
||||
self.maybe_print_comment(span.lo());
|
||||
self.word(token_lit.to_string())
|
||||
}
|
||||
|
||||
fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) {
|
||||
self.print_string(sym.as_str(), style);
|
||||
}
|
||||
|
||||
fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
|
||||
}
|
||||
|
||||
fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
|
||||
}
|
||||
|
||||
fn print_attribute(&mut self, attr: &ast::Attribute) {
|
||||
self.print_attribute_inline(attr, false)
|
||||
}
|
||||
|
||||
fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {
|
||||
match item {
|
||||
ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi),
|
||||
ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_meta_item(&mut self, item: &ast::MetaItem) {
|
||||
self.ibox(INDENT_UNIT);
|
||||
match &item.kind {
|
||||
ast::MetaItemKind::Word => self.print_path(&item.path, false, 0),
|
||||
ast::MetaItemKind::NameValue(value) => {
|
||||
self.print_path(&item.path, false, 0);
|
||||
self.space();
|
||||
self.word_space("=");
|
||||
self.print_meta_item_lit(value);
|
||||
}
|
||||
ast::MetaItemKind::List(items) => {
|
||||
self.print_path(&item.path, false, 0);
|
||||
self.popen();
|
||||
self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i));
|
||||
self.pclose();
|
||||
}
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
||||
pub(crate) fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String {
|
||||
Self::to_string(|s| s.print_type_bounds(bounds))
|
||||
}
|
||||
|
||||
pub(crate) fn where_bound_predicate_to_string(
|
||||
&self,
|
||||
where_bound_predicate: &ast::WhereBoundPredicate,
|
||||
) -> String {
|
||||
Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
|
||||
}
|
||||
|
||||
pub(crate) fn tt_to_string(&self, tt: &TokenTree) -> String {
|
||||
Self::to_string(|s| s.print_tt(tt, false))
|
||||
}
|
||||
|
||||
pub(crate) fn tts_to_string(&self, tokens: &TokenStream) -> String {
|
||||
Self::to_string(|s| s.print_tts(tokens, false))
|
||||
}
|
||||
|
||||
pub(crate) fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
|
||||
Self::to_string(|s| s.print_path_segment(p, false))
|
||||
}
|
||||
|
||||
pub(crate) fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String {
|
||||
Self::to_string(|s| s.print_meta_list_item(li))
|
||||
}
|
||||
|
||||
pub(crate) fn attribute_to_string(&self, attr: &ast::Attribute) -> String {
|
||||
Self::to_string(|s| s.print_attribute(attr))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
use std::iter::Peekable;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub struct Delimited<I: Iterator> {
|
||||
is_first: bool,
|
||||
iter: Peekable<I>,
|
||||
}
|
||||
|
||||
pub trait IterDelimited: Iterator + Sized {
|
||||
fn delimited(self) -> Delimited<Self> {
|
||||
Delimited { is_first: true, iter: self.peekable() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Iterator> IterDelimited for I {}
|
||||
|
||||
pub struct IteratorItem<T> {
|
||||
value: T,
|
||||
pub is_first: bool,
|
||||
pub is_last: bool,
|
||||
}
|
||||
|
||||
impl<I: Iterator> Iterator for Delimited<I> {
|
||||
type Item = IteratorItem<I::Item>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let value = self.iter.next()?;
|
||||
let is_first = mem::replace(&mut self.is_first, false);
|
||||
let is_last = self.iter.peek().is_none();
|
||||
Some(IteratorItem { value, is_first, is_last })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for IteratorItem<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.value
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use crate::pp::Breaks::Inconsistent;
|
||||
use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT};
|
||||
|
||||
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||
|
@ -149,10 +149,12 @@ impl<'a> State<'a> {
|
|||
return;
|
||||
}
|
||||
self.cbox(0);
|
||||
for field in fields.iter().delimited() {
|
||||
for (pos, field) in fields.iter().with_position() {
|
||||
let is_first = matches!(pos, Position::First | Position::Only);
|
||||
let is_last = matches!(pos, Position::Last | Position::Only);
|
||||
self.maybe_print_comment(field.span.hi());
|
||||
self.print_outer_attributes(&field.attrs);
|
||||
if field.is_first {
|
||||
if is_first {
|
||||
self.space_if_not_bol();
|
||||
}
|
||||
if !field.is_shorthand {
|
||||
|
@ -160,7 +162,7 @@ impl<'a> State<'a> {
|
|||
self.word_nbsp(":");
|
||||
}
|
||||
self.print_expr(&field.expr);
|
||||
if !field.is_last || has_rest {
|
||||
if !is_last || has_rest {
|
||||
self.word_space(",");
|
||||
} else {
|
||||
self.trailing_comma_or_space();
|
||||
|
@ -279,7 +281,7 @@ impl<'a> State<'a> {
|
|||
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
|
||||
}
|
||||
|
||||
pub fn print_expr(&mut self, expr: &ast::Expr) {
|
||||
pub(super) fn print_expr(&mut self, expr: &ast::Expr) {
|
||||
self.print_expr_outer_attr_style(expr, true)
|
||||
}
|
||||
|
||||
|
@ -679,7 +681,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String {
|
||||
fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String {
|
||||
let mut template = "\"".to_string();
|
||||
for piece in pieces {
|
||||
match piece {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::pp::Breaks::Inconsistent;
|
||||
use crate::pprust::state::delimited::IterDelimited;
|
||||
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
||||
|
||||
use ast::StaticItem;
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::GenericBound;
|
||||
use rustc_ast::ModKind;
|
||||
|
@ -20,7 +20,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
|
||||
fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
|
||||
let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
|
||||
self.ann.pre(self, AnnNode::SubItem(id));
|
||||
self.hardbreak_if_not_bol();
|
||||
|
@ -518,7 +518,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_assoc_item(&mut self, item: &ast::AssocItem) {
|
||||
fn print_assoc_item(&mut self, item: &ast::AssocItem) {
|
||||
let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
|
||||
self.ann.pre(self, AnnNode::SubItem(id));
|
||||
self.hardbreak_if_not_bol();
|
||||
|
@ -621,7 +621,7 @@ impl<'a> State<'a> {
|
|||
self.print_where_clause_parts(where_clause.has_where_token, &where_clause.predicates);
|
||||
}
|
||||
|
||||
pub(crate) fn print_where_clause_parts(
|
||||
fn print_where_clause_parts(
|
||||
&mut self,
|
||||
has_where_token: bool,
|
||||
predicates: &[ast::WherePredicate],
|
||||
|
@ -668,7 +668,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn print_where_bound_predicate(
|
||||
pub(crate) fn print_where_bound_predicate(
|
||||
&mut self,
|
||||
where_bound_predicate: &ast::WhereBoundPredicate,
|
||||
) {
|
||||
|
@ -712,9 +712,10 @@ impl<'a> State<'a> {
|
|||
self.word("{");
|
||||
self.zerobreak();
|
||||
self.ibox(0);
|
||||
for use_tree in items.iter().delimited() {
|
||||
for (pos, use_tree) in items.iter().with_position() {
|
||||
let is_last = matches!(pos, Position::Last | Position::Only);
|
||||
self.print_use_tree(&use_tree.0);
|
||||
if !use_tree.is_last {
|
||||
if !is_last {
|
||||
self.word(",");
|
||||
if let ast::UseTreeKind::Nested(_) = use_tree.0.kind {
|
||||
self.hardbreak();
|
||||
|
|
|
@ -6,7 +6,7 @@ edition = "2021"
|
|||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
either = "1.5.0"
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
polonius-engine = "0.13.0"
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
@ -10,7 +10,7 @@ test = false
|
|||
# tidy-alphabetical-start
|
||||
bitflags = "1.0"
|
||||
cstr = "0.2"
|
||||
itertools = "0.10.5"
|
||||
itertools = "0.11"
|
||||
libc = "0.2"
|
||||
measureme = "10.0.0"
|
||||
object = { version = "0.32.0", default-features = false, features = ["std", "read"] }
|
||||
|
|
|
@ -8,7 +8,7 @@ edition = "2021"
|
|||
ar_archive_writer = "0.1.5"
|
||||
bitflags = "1.2.1"
|
||||
cc = "1.0.69"
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
jobserver = "0.1.22"
|
||||
pathdiff = "0.2.0"
|
||||
regex = "1.4"
|
||||
|
|
|
@ -10,7 +10,7 @@ bitflags = "1.2.1"
|
|||
elsa = "=1.7.1"
|
||||
ena = "0.14.2"
|
||||
indexmap = { version = "2.0.0" }
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
jobserver_crate = { version = "0.1.13", package = "jobserver" }
|
||||
libc = "0.2"
|
||||
measureme = "10.0.0"
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
//! HIR pretty-printing is layered on top of AST pretty-printing. A number of
|
||||
//! the definitions in this file have equivalents in `rustc_ast_pretty`.
|
||||
|
||||
#![recursion_limit = "256"]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
@ -12,7 +15,7 @@ use rustc_hir::LifetimeParamKind;
|
|||
use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term};
|
||||
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::{self, FileName};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
|
@ -49,8 +52,8 @@ pub trait PpAnn {
|
|||
}
|
||||
|
||||
pub struct NoAnn;
|
||||
|
||||
impl PpAnn for NoAnn {}
|
||||
pub const NO_ANN: &dyn PpAnn = &NoAnn;
|
||||
|
||||
impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
|
||||
fn nested(&self, state: &mut State<'_>, nested: Nested) {
|
||||
|
@ -136,9 +139,8 @@ impl<'a> PrintState<'a> for State<'a> {
|
|||
&mut self.comments
|
||||
}
|
||||
|
||||
fn print_ident(&mut self, ident: Ident) {
|
||||
self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
|
||||
self.ann.post(self, AnnNode::Name(&ident.name))
|
||||
fn ann_post(&mut self, ident: Ident) {
|
||||
self.ann.post(self, AnnNode::Name(&ident.name));
|
||||
}
|
||||
|
||||
fn print_generic_args(&mut self, _: &ast::GenericArgs, _colons_before_params: bool) {
|
||||
|
@ -183,15 +185,15 @@ where
|
|||
}
|
||||
|
||||
pub fn ty_to_string(ty: &hir::Ty<'_>) -> String {
|
||||
to_string(NO_ANN, |s| s.print_type(ty))
|
||||
to_string(&NoAnn, |s| s.print_type(ty))
|
||||
}
|
||||
|
||||
pub fn qpath_to_string(segment: &hir::QPath<'_>) -> String {
|
||||
to_string(NO_ANN, |s| s.print_qpath(segment, false))
|
||||
to_string(&NoAnn, |s| s.print_qpath(segment, false))
|
||||
}
|
||||
|
||||
pub fn pat_to_string(pat: &hir::Pat<'_>) -> String {
|
||||
to_string(NO_ANN, |s| s.print_pat(pat))
|
||||
to_string(&NoAnn, |s| s.print_pat(pat))
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
|
|
|
@ -114,7 +114,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
|
||||
/// Runs the "early phases" of the compiler: initial `cfg` processing,
|
||||
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
|
||||
/// harness if one is to be provided, injection of a dependency on the
|
||||
/// standard library and prelude, and name resolution.
|
||||
|
|
|
@ -6,7 +6,7 @@ edition = "2021"
|
|||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
either = "1"
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
|
|
|
@ -27,5 +27,5 @@ rustc = [
|
|||
|
||||
[dev-dependencies]
|
||||
# tidy-alphabetical-start
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
|
|
|
@ -9,7 +9,7 @@ path = "lib.rs"
|
|||
[dependencies]
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
askama = { version = "0.12", default-features = false, features = ["config"] }
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
indexmap = "2"
|
||||
minifier = "0.3.0"
|
||||
once_cell = "1.10.0"
|
||||
|
|
|
@ -37,7 +37,7 @@ toml = "0.7.3"
|
|||
walkdir = "2.3"
|
||||
# This is used by the `collect-metadata` alias.
|
||||
filetime = "0.2"
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
|
||||
# UI test dependencies
|
||||
clippy_utils = { path = "clippy_utils" }
|
||||
|
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||
aho-corasick = "0.7"
|
||||
clap = "4.1.4"
|
||||
indoc = "1.0"
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
opener = "0.5"
|
||||
shell-escape = "0.1"
|
||||
walkdir = "2.3"
|
||||
|
|
|
@ -14,7 +14,7 @@ cargo_metadata = "0.15.3"
|
|||
clippy_config = { path = "../clippy_config" }
|
||||
clippy_utils = { path = "../clippy_utils" }
|
||||
declare_clippy_lint = { path = "../declare_clippy_lint" }
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
quine-mc_cluskey = "0.2"
|
||||
regex-syntax = "0.7"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
|
@ -7,7 +7,7 @@ publish = false
|
|||
[dependencies]
|
||||
clippy_config = { path = "../clippy_config" }
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
rustc-semver = "1.1"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -8,7 +8,7 @@ publish = false
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.10.1"
|
||||
itertools = "0.11"
|
||||
quote = "1.0.21"
|
||||
syn = "2.0"
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ diff = "0.1"
|
|||
dirs = "4.0"
|
||||
getopts = "0.2"
|
||||
ignore = "0.4"
|
||||
itertools = "0.10"
|
||||
itertools = "0.11"
|
||||
lazy_static = "1.4"
|
||||
regex = "1.7"
|
||||
serde = { version = "1.0.160", features = ["derive"] }
|
||||
|
|
Loading…
Reference in New Issue