From 84fcd0dc991e2f5b9035d118d8c016f35ab37d0a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 14 Aug 2020 10:46:39 +0200 Subject: [PATCH 1/4] Move macro test to ui/macros --- src/test/ui/{issues => macros}/issue-39404.rs | 0 src/test/ui/{issues => macros}/issue-39404.stderr | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{issues => macros}/issue-39404.rs (100%) rename src/test/ui/{issues => macros}/issue-39404.stderr (100%) diff --git a/src/test/ui/issues/issue-39404.rs b/src/test/ui/macros/issue-39404.rs similarity index 100% rename from src/test/ui/issues/issue-39404.rs rename to src/test/ui/macros/issue-39404.rs diff --git a/src/test/ui/issues/issue-39404.stderr b/src/test/ui/macros/issue-39404.stderr similarity index 100% rename from src/test/ui/issues/issue-39404.stderr rename to src/test/ui/macros/issue-39404.stderr From 02eae432e7476a0686633a8c2b7cb1d5aab1bd2c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 14 Aug 2020 11:24:01 +0200 Subject: [PATCH 2/4] Promote missing_fragment_specifier to hard error It has been deny_by_default since 2017 (and warned for some time before that), so it seems reasonable to promote it. The specific technical motivation to do this now is to remove a field from `ParseSess` -- it is a global state, and global state makes extracting libraries annoying. Closes #40107 --- src/librustc_expand/mbe.rs | 2 +- src/librustc_expand/mbe/macro_parser.rs | 20 +++-------------- src/librustc_expand/mbe/macro_rules.rs | 15 ++++++------- src/librustc_expand/mbe/quoted.rs | 11 ++++------ src/librustc_interface/passes.rs | 19 +--------------- src/librustc_session/parse.rs | 2 -- src/test/ui/lint/expansion-time.rs | 4 ---- src/test/ui/lint/expansion-time.stderr | 22 ++++--------------- src/test/ui/macros/issue-39404.rs | 1 - src/test/ui/macros/issue-39404.stderr | 4 ---- src/test/ui/macros/macro-match-nonterminal.rs | 1 - .../ui/macros/macro-match-nonterminal.stderr | 4 ---- src/test/ui/parser/macro/issue-33569.rs | 1 + src/test/ui/parser/macro/issue-33569.stderr | 16 +++++++++----- 14 files changed, 32 insertions(+), 90 deletions(-) diff --git a/src/librustc_expand/mbe.rs b/src/librustc_expand/mbe.rs index 9920e0650a7f7..e9e6fc5af2230 100644 --- a/src/librustc_expand/mbe.rs +++ b/src/librustc_expand/mbe.rs @@ -84,7 +84,7 @@ enum TokenTree { /// e.g., `$var` MetaVar(Span, Ident), /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros. - MetaVarDecl(Span, Ident /* name to bind */, Option), + MetaVarDecl(Span, Ident /* name to bind */, NonterminalKind), } impl TokenTree { diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index d2fe7fe10a830..92a8f23112679 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -378,11 +378,6 @@ fn nameize>( n_rec(sess, next_m, res.by_ref(), ret_val)?; } } - TokenTree::MetaVarDecl(span, _, None) => { - if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { - return Err((span, "missing fragment specifier".to_string())); - } - } TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val .entry(MacroRulesNormalizedIdent::new(bind_name)) { @@ -442,7 +437,6 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool { /// /// A `ParseResult`. Note that matches are kept track of through the items generated. fn inner_parse_loop<'root, 'tt>( - sess: &ParseSess, cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, next_items: &mut Vec>, eof_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, @@ -560,16 +554,9 @@ fn inner_parse_loop<'root, 'tt>( }))); } - // We need to match a metavar (but the identifier is invalid)... this is an error - TokenTree::MetaVarDecl(span, _, None) => { - if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { - return Error(span, "missing fragment specifier".to_string()); - } - } - // We need to match a metavar with a valid ident... call out to the black-box // parser by adding an item to `bb_items`. - TokenTree::MetaVarDecl(_, _, Some(kind)) => { + TokenTree::MetaVarDecl(_, _, kind) => { // Built-in nonterminals never start with these tokens, // so we can eliminate them from consideration. if Parser::nonterminal_may_begin_with(kind, token) { @@ -640,7 +627,6 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na // parsing from the black-box parser done. The result is that `next_items` will contain a // bunch of possible next matcher positions in `next_items`. match inner_parse_loop( - parser.sess, &mut cur_items, &mut next_items, &mut eof_items, @@ -702,7 +688,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na let nts = bb_items .iter() .map(|item| match item.top_elts.get_tt(item.idx) { - TokenTree::MetaVarDecl(_, bind, Some(kind)) => format!("{} ('{}')", kind, bind), + TokenTree::MetaVarDecl(_, bind, kind) => format!("{} ('{}')", kind, bind), _ => panic!(), }) .collect::>() @@ -732,7 +718,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na assert_eq!(bb_items.len(), 1); let mut item = bb_items.pop().unwrap(); - if let TokenTree::MetaVarDecl(span, _, Some(kind)) = item.top_elts.get_tt(item.idx) { + if let TokenTree::MetaVarDecl(span, _, kind) = item.top_elts.get_tt(item.idx) { let match_cur = item.match_cur; let nt = match parser.to_mut().parse_nonterminal(kind) { Err(mut err) => { diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 48a622d13efcb..f0e6fe39a3c7f 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -400,7 +400,7 @@ pub fn compile_declarative_macro( let diag = &sess.parse_sess.span_diagnostic; let lhs_nm = Ident::new(sym::lhs, def.span); let rhs_nm = Ident::new(sym::rhs, def.span); - let tt_spec = Some(NonterminalKind::TT); + let tt_spec = NonterminalKind::TT; // Parse the macro_rules! invocation let (macro_rules, body) = match &def.kind { @@ -577,7 +577,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { TokenTree::Sequence(span, ref seq) => { if seq.separator.is_none() && seq.tts.iter().all(|seq_tt| match *seq_tt { - TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)) => true, + TokenTree::MetaVarDecl(_, _, NonterminalKind::Vis) => true, TokenTree::Sequence(_, ref sub_seq) => { sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore || sub_seq.kleene.op == mbe::KleeneOp::ZeroOrOne @@ -960,7 +960,7 @@ fn check_matcher_core( // Now `last` holds the complete set of NT tokens that could // end the sequence before SUFFIX. Check that every one works with `suffix`. for token in &last.tokens { - if let TokenTree::MetaVarDecl(_, name, Some(kind)) = *token { + if let TokenTree::MetaVarDecl(_, name, kind) = *token { for next_token in &suffix_first.tokens { match is_in_follow(next_token, kind) { IsInFollow::Yes => {} @@ -1018,7 +1018,7 @@ fn check_matcher_core( } fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool { - if let mbe::TokenTree::MetaVarDecl(_, _, Some(kind)) = *tok { + if let mbe::TokenTree::MetaVarDecl(_, _, kind) = *tok { frag_can_be_followed_by_any(kind) } else { // (Non NT's can always be followed by anything in matchers.) @@ -1123,7 +1123,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { } _ => IsInFollow::No(TOKENS), }, - TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Block)) => IsInFollow::Yes, + TokenTree::MetaVarDecl(_, _, NonterminalKind::Block) => IsInFollow::Yes, _ => IsInFollow::No(TOKENS), } } @@ -1158,7 +1158,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { TokenTree::MetaVarDecl( _, _, - Some(NonterminalKind::Ident | NonterminalKind::Ty | NonterminalKind::Path), + NonterminalKind::Ident | NonterminalKind::Ty | NonterminalKind::Path, ) => IsInFollow::Yes, _ => IsInFollow::No(TOKENS), } @@ -1171,8 +1171,7 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { match *tt { mbe::TokenTree::Token(ref token) => pprust::token_to_string(&token), mbe::TokenTree::MetaVar(_, name) => format!("${}", name), - mbe::TokenTree::MetaVarDecl(_, name, Some(kind)) => format!("${}:{}", name, kind), - mbe::TokenTree::MetaVarDecl(_, name, None) => format!("${}:", name), + mbe::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind), _ => panic!( "unexpected mbe::TokenTree::{{Sequence or Delimited}} \ in follow set checker" diff --git a/src/librustc_expand/mbe/quoted.rs b/src/librustc_expand/mbe/quoted.rs index 01b11bb979d68..48db532c78f30 100644 --- a/src/librustc_expand/mbe/quoted.rs +++ b/src/librustc_expand/mbe/quoted.rs @@ -3,7 +3,7 @@ use crate::mbe::{Delimited, KleeneOp, KleeneToken, SequenceRepetition, TokenTree use rustc_ast::token::{self, Token}; use rustc_ast::tokenstream; -use rustc_ast::{NodeId, DUMMY_NODE_ID}; +use rustc_ast::NodeId; use rustc_ast_pretty::pprust; use rustc_session::parse::ParseSess; use rustc_span::symbol::{kw, Ident}; @@ -73,7 +73,7 @@ pub(super) fn parse( .emit(); token::NonterminalKind::Ident }); - result.push(TokenTree::MetaVarDecl(span, ident, Some(kind))); + result.push(TokenTree::MetaVarDecl(span, ident, kind)); continue; } _ => token.span, @@ -83,11 +83,8 @@ pub(super) fn parse( } tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp), }; - if node_id != DUMMY_NODE_ID { - // Macros loaded from other crates have dummy node ids. - sess.missing_fragment_specifiers.borrow_mut().insert(span, node_id); - } - result.push(TokenTree::MetaVarDecl(span, ident, None)); + sess.span_diagnostic.struct_span_err(span, "missing fragment specifier").emit(); + continue; } // Not a metavar or no matchers allowed, so just return the tree diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 007dbfb9fdd58..403aea8b304eb 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -30,7 +30,6 @@ use rustc_passes::{self, hir_stats, layout_test}; use rustc_plugin_impl as plugin; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode}; -use rustc_session::lint; use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::Session; @@ -307,27 +306,11 @@ fn configure_and_expand_inner<'a>( ecx.check_unused_macros(); }); - let mut missing_fragment_specifiers: Vec<_> = ecx - .sess - .parse_sess - .missing_fragment_specifiers - .borrow() - .iter() - .map(|(span, node_id)| (*span, *node_id)) - .collect(); - missing_fragment_specifiers.sort_unstable_by_key(|(span, _)| *span); - - let recursion_limit_hit = ecx.reduced_recursion_limit.is_some(); - - for (span, node_id) in missing_fragment_specifiers { - let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; - let msg = "missing fragment specifier"; - resolver.lint_buffer().buffer_lint(lint, node_id, span, msg); - } if cfg!(windows) { env::set_var("PATH", &old_path); } + let recursion_limit_hit = ecx.reduced_recursion_limit.is_some(); if recursion_limit_hit { // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed // with a large AST diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index a2bb8c4f91ff4..6f10d0c4b89ea 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -119,7 +119,6 @@ pub struct ParseSess { pub unstable_features: UnstableFeatures, pub config: CrateConfig, pub edition: Edition, - pub missing_fragment_specifiers: Lock>, /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. pub raw_identifier_spans: Lock>, /// Used to determine and report recursive module inclusions. @@ -154,7 +153,6 @@ impl ParseSess { unstable_features: UnstableFeatures::from_environment(), config: FxHashSet::default(), edition: ExpnId::root().expn_data().edition, - missing_fragment_specifiers: Default::default(), raw_identifier_spans: Lock::new(Vec::new()), included_mod_stack: Lock::new(vec![]), source_map, diff --git a/src/test/ui/lint/expansion-time.rs b/src/test/ui/lint/expansion-time.rs index 6e420c51f0a7f..c98ecc980dd3d 100644 --- a/src/test/ui/lint/expansion-time.rs +++ b/src/test/ui/lint/expansion-time.rs @@ -5,10 +5,6 @@ macro_rules! foo { ( $($i:ident)* ) => { $($i)+ }; //~ WARN meta-variable repeats with different Kleene operator } -#[warn(missing_fragment_specifier)] -macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier - //~| WARN this was previously accepted - #[warn(soft_unstable)] mod benches { #[bench] //~ WARN use of unstable library feature 'test' diff --git a/src/test/ui/lint/expansion-time.stderr b/src/test/ui/lint/expansion-time.stderr index e6b5cf67e3904..bc48d64e7e6b7 100644 --- a/src/test/ui/lint/expansion-time.stderr +++ b/src/test/ui/lint/expansion-time.stderr @@ -12,28 +12,14 @@ note: the lint level is defined here LL | #[warn(meta_variable_misuse)] | ^^^^^^^^^^^^^^^^^^^^ -warning: missing fragment specifier - --> $DIR/expansion-time.rs:9:19 - | -LL | macro_rules! m { ($i) => {} } - | ^^ - | -note: the lint level is defined here - --> $DIR/expansion-time.rs:8:8 - | -LL | #[warn(missing_fragment_specifier)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable - --> $DIR/expansion-time.rs:14:7 + --> $DIR/expansion-time.rs:10:7 | LL | #[bench] | ^^^^^ | note: the lint level is defined here - --> $DIR/expansion-time.rs:12:8 + --> $DIR/expansion-time.rs:8:8 | LL | #[warn(soft_unstable)] | ^^^^^^^^^^^^^ @@ -47,10 +33,10 @@ LL | 2 | ^ | note: the lint level is defined here - --> $DIR/expansion-time.rs:19:8 + --> $DIR/expansion-time.rs:15:8 | LL | #[warn(incomplete_include)] | ^^^^^^^^^^^^^^^^^^ -warning: 4 warnings emitted +warning: 3 warnings emitted diff --git a/src/test/ui/macros/issue-39404.rs b/src/test/ui/macros/issue-39404.rs index 2229f2c3900c3..054958ba00b8d 100644 --- a/src/test/ui/macros/issue-39404.rs +++ b/src/test/ui/macros/issue-39404.rs @@ -2,6 +2,5 @@ macro_rules! m { ($i) => {} } //~^ ERROR missing fragment specifier -//~| WARN previously accepted fn main() {} diff --git a/src/test/ui/macros/issue-39404.stderr b/src/test/ui/macros/issue-39404.stderr index d2f2a823c2a6b..645f06e59d817 100644 --- a/src/test/ui/macros/issue-39404.stderr +++ b/src/test/ui/macros/issue-39404.stderr @@ -3,10 +3,6 @@ error: missing fragment specifier | LL | macro_rules! m { ($i) => {} } | ^^ - | - = note: `#[deny(missing_fragment_specifier)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 error: aborting due to previous error diff --git a/src/test/ui/macros/macro-match-nonterminal.rs b/src/test/ui/macros/macro-match-nonterminal.rs index b23e5c71c03f0..6b023e4137274 100644 --- a/src/test/ui/macros/macro-match-nonterminal.rs +++ b/src/test/ui/macros/macro-match-nonterminal.rs @@ -2,7 +2,6 @@ macro_rules! test { ($a, $b) => { //~^ ERROR missing fragment //~| ERROR missing fragment - //~| WARN this was previously accepted () }; } diff --git a/src/test/ui/macros/macro-match-nonterminal.stderr b/src/test/ui/macros/macro-match-nonterminal.stderr index 674ce3434aac6..334d62812cdab 100644 --- a/src/test/ui/macros/macro-match-nonterminal.stderr +++ b/src/test/ui/macros/macro-match-nonterminal.stderr @@ -9,10 +9,6 @@ error: missing fragment specifier | LL | ($a, $b) => { | ^^ - | - = note: `#[deny(missing_fragment_specifier)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/macro/issue-33569.rs b/src/test/ui/parser/macro/issue-33569.rs index 80e2d7c6545ba..cf81f0480a2a7 100644 --- a/src/test/ui/parser/macro/issue-33569.rs +++ b/src/test/ui/parser/macro/issue-33569.rs @@ -2,6 +2,7 @@ macro_rules! foo { { $+ } => { //~ ERROR expected identifier, found `+` //~^ ERROR missing fragment specifier $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?` + //~^ ERROR attempted to repeat an expression containing no syntax variables } } diff --git a/src/test/ui/parser/macro/issue-33569.stderr b/src/test/ui/parser/macro/issue-33569.stderr index b4d38d3ce4806..f54efaa6996f2 100644 --- a/src/test/ui/parser/macro/issue-33569.stderr +++ b/src/test/ui/parser/macro/issue-33569.stderr @@ -4,17 +4,23 @@ error: expected identifier, found `+` LL | { $+ } => { | ^ +error: missing fragment specifier + --> $DIR/issue-33569.rs:2:8 + | +LL | { $+ } => { + | ^ + error: expected one of: `*`, `+`, or `?` --> $DIR/issue-33569.rs:4:13 | LL | $(x)(y) | ^^^ -error: missing fragment specifier - --> $DIR/issue-33569.rs:2:8 +error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth + --> $DIR/issue-33569.rs:4:10 | -LL | { $+ } => { - | ^ +LL | $(x)(y) + | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From 5ba961018c482e050af908de60e4f8bd1a00f0ae Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 14 Aug 2020 11:29:22 +0200 Subject: [PATCH 3/4] Remove missing_fragment_specifier lint --- src/doc/rustc/src/lints/listing/deny-by-default.md | 9 --------- src/librustc_session/lint/builtin.rs | 11 ----------- 2 files changed, 20 deletions(-) diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index dc5a9e44acfa2..55714f8f4548b 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -45,15 +45,6 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type` = note: for more information, see issue #36887 ``` -## missing-fragment-specifier - -The missing_fragment_specifier warning is issued when an unused pattern in a -`macro_rules!` macro definition has a meta-variable (e.g. `$e`) that is not -followed by a fragment specifier (e.g. `:expr`). - -This warning can always be fixed by removing the unused pattern in the -`macro_rules!` macro definition. - ## mutable-transmutes This lint catches transmuting from `&T` to `&mut T` because it is undefined diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index 144a06a4916bd..2db4d2a7f51d9 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -252,16 +252,6 @@ declare_lint! { }; } -declare_lint! { - pub MISSING_FRAGMENT_SPECIFIER, - Deny, - "detects missing fragment specifiers in unused `macro_rules!` patterns", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #40107 ", - edition: None, - }; -} - declare_lint! { pub LATE_BOUND_LIFETIME_ARGUMENTS, Warn, @@ -584,7 +574,6 @@ declare_lint_pass! { UNALIGNED_REFERENCES, SAFE_PACKED_BORROWS, PATTERNS_IN_FNS_WITHOUT_BODY, - MISSING_FRAGMENT_SPECIFIER, LATE_BOUND_LIFETIME_ARGUMENTS, ORDER_DEPENDENT_TRAIT_OBJECTS, COHERENCE_LEAK_CHECK, From eb4d6b520b3e75c7e93f1ea13f1a45eda0687b4e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 15 Aug 2020 14:12:51 +0200 Subject: [PATCH 4/4] Remove broken clap versions from cargotest treeify depends on an outdated version of clap, which will fail to compile when we promote missing_fragment_specifier future compat lint to error (ie, old clap contains code that shouldn't have compiled in the first place). Additionally, this crate seem tiny relative to other crates we are testing here, so it seems like it doesn't provide that much additional confidence. The same happens with tokei project, but it is an actively maintained one, so we can just upgrade it to a version from 2018, where clap was upgraded. --- src/tools/cargotest/main.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index ecaeda68695a7..269ab8042c070 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -29,14 +29,7 @@ const TEST_REPOS: &'static [Test] = &[ Test { name: "tokei", repo: "https://github.com/XAMPPRocky/tokei", - sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928", - lock: None, - packages: &[], - }, - Test { - name: "treeify", - repo: "https://github.com/dzamlo/treeify", - sha: "999001b223152441198f117a68fb81f57bc086dd", + sha: "a950ff128d5a435a8083b1c7577c0431f98360ca", lock: None, packages: &[], },