diff --git a/.travis.yml b/.travis.yml index 990cac4dbe98b..3d8918095accb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -200,7 +200,7 @@ matrix: before_install: # We'll use the AWS cli to download/upload cached docker layers as well as # push our deployments, so download that here. - - pip install --user awscli; export PATH=$PATH:$HOME/.local/bin + - pip install --user awscli; export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/ - mkdir -p $HOME/rustsrc # FIXME(#46924): these two commands are required to enable IPv6, # they shouldn't exist, please revert once more official solutions appeared. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index fea6302d0a119..6d40575352418 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -881,6 +881,7 @@ impl Step for Src { "src/jemalloc", "src/libprofiler_builtins", "src/stdsimd", + "src/libproc_macro", ]; let std_src_dirs_exclude = [ "src/libcompiler_builtins/compiler-rt/test", diff --git a/src/libcore/default.rs b/src/libcore/default.rs index ab36e29b1e1d4..638acebd617bf 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -76,7 +76,7 @@ /// } /// /// impl Default for Kind { -/// fn default() -> Kind { Kind::A } +/// fn default() -> Self { Kind::A } /// } /// ``` /// @@ -118,7 +118,7 @@ pub trait Default: Sized { /// } /// /// impl Default for Kind { - /// fn default() -> Kind { Kind::A } + /// fn default() -> Self { Kind::A } /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 7a20146130d94..f5f8e3512a0ea 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1254,7 +1254,7 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { Some(Node::MacroDef(_)) => { format!("macro {}{}", path_str(), id_str) } - Some(Node::Crate) => format!("root_crate"), + Some(Node::Crate) => String::from("root_crate"), None => format!("unknown node{}", id_str), } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 62cc3113a3d37..61b5886e7832d 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -295,12 +295,10 @@ impl AllocDecodingState { } pub fn new(data_offsets: Vec<u32>) -> AllocDecodingState { - let decoding_state: Vec<_> = ::std::iter::repeat(Mutex::new(State::Empty)) - .take(data_offsets.len()) - .collect(); + let decoding_state = vec![Mutex::new(State::Empty); data_offsets.len()]; AllocDecodingState { - decoding_state: decoding_state, + decoding_state, data_offsets, } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 15a0adc3c0692..b463faef1921a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -34,7 +34,6 @@ use hir::def_id::DefId; use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; use std::fmt; -use std::iter; use syntax::ast; use session::DiagnosticMessageId; use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; @@ -1095,10 +1094,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // found arguments is empty (assume the user just wants to ignore args in this case). // For example, if `expected_args_length` is 2, suggest `|_, _|`. if found_args.is_empty() && is_closure { - let underscores = iter::repeat("_") - .take(expected_args.len()) - .collect::<Vec<_>>() - .join(", "); + let underscores = vec!["_"; expected_args.len()].join(", "); err.span_suggestion_with_applicability( found_span, &format!( diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 870eeadc081e7..a323282f23353 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -350,10 +350,10 @@ impl Diagnostic { } pub fn span_suggestions_with_applicability(&mut self, sp: Span, msg: &str, - suggestions: Vec<String>, - applicability: Applicability) -> &mut Self { + suggestions: impl Iterator<Item = String>, applicability: Applicability) -> &mut Self + { self.suggestions.push(CodeSuggestion { - substitutions: suggestions.into_iter().map(|snippet| Substitution { + substitutions: suggestions.map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp, diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index f4289ea2d4b26..2f16470530e43 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -253,7 +253,7 @@ impl<'a> DiagnosticBuilder<'a> { pub fn span_suggestions_with_applicability(&mut self, sp: Span, msg: &str, - suggestions: Vec<String>, + suggestions: impl Iterator<Item = String>, applicability: Applicability) -> &mut Self { if !self.allow_suggestions { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index b2b92a6f85784..3c4d8e09fc166 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -788,7 +788,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let what_was_dropped = match self.describe_place(place) { Some(name) => format!("`{}`", name.as_str()), - None => format!("temporary value"), + None => String::from("temporary value"), }; let label = match self.describe_place(&borrow.borrowed_place) { @@ -1028,7 +1028,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match category { ConstraintCategory::Return => { - err.span_note(constraint_span, &format!("closure is returned here")); + err.span_note(constraint_span, "closure is returned here"); } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 08696dc098e00..b46489a162b85 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -12,12 +12,12 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::mir::tcx::RvalueInitializationState; use rustc_data_structures::indexed_vec::{IndexVec}; +use smallvec::{SmallVec, smallvec}; use std::collections::hash_map::Entry; use std::mem; use super::abs_domain::Lift; - use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex}; use super::{MoveError, InitIndex, Init, InitLocation, LookupResult, InitKind}; use super::IllegalMoveOriginKind::*; @@ -64,8 +64,8 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> { } fn new_move_path(move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>, - path_map: &mut IndexVec<MovePathIndex, Vec<MoveOutIndex>>, - init_path_map: &mut IndexVec<MovePathIndex, Vec<InitIndex>>, + path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>, + init_path_map: &mut IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>, parent: Option<MovePathIndex>, place: Place<'tcx>) -> MovePathIndex @@ -83,10 +83,10 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> { move_paths[move_path].next_sibling = next_sibling; } - let path_map_ent = path_map.push(vec![]); + let path_map_ent = path_map.push(smallvec![]); assert_eq!(path_map_ent, move_path); - let init_path_map_ent = init_path_map.push(vec![]); + let init_path_map_ent = init_path_map.push(smallvec![]); assert_eq!(init_path_map_ent, move_path); move_path diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 58a2b9361032e..2a026b8f52c2a 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -13,6 +13,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec}; +use smallvec::SmallVec; use syntax_pos::{Span}; use std::fmt; @@ -141,14 +142,14 @@ pub struct MoveData<'tcx> { /// of executing the code at `l`. (There can be multiple MoveOut's /// for a given `l` because each MoveOut is associated with one /// particular path being moved.) - pub loc_map: LocationMap<Vec<MoveOutIndex>>, - pub path_map: IndexVec<MovePathIndex, Vec<MoveOutIndex>>, + pub loc_map: LocationMap<SmallVec<[MoveOutIndex; 4]>>, + pub path_map: IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>, pub rev_lookup: MovePathLookup<'tcx>, pub inits: IndexVec<InitIndex, Init>, /// Each Location `l` is mapped to the Inits that are effects /// of executing the code at `l`. - pub init_loc_map: LocationMap<Vec<InitIndex>>, - pub init_path_map: IndexVec<MovePathIndex, Vec<InitIndex>>, + pub init_loc_map: LocationMap<SmallVec<[InitIndex; 4]>>, + pub init_path_map: IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>, } pub trait HasMoveData<'tcx> { diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 9d86e737dd5b6..15d0a9166a678 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -408,7 +408,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ), _ => return validation_failure!( - format!("non-integer enum discriminant"), path + String::from("non-integer enum discriminant"), path ), } }; diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 1715086686c42..ae0483e3c140c 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -575,7 +575,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { OGN = o ); err.span_label(mutate_span, format!("cannot {}", action)); - err.span_label(match_span, format!("value is immutable in match guard")); + err.span_label(match_span, String::from("value is immutable in match guard")); self.cancel_if_wrong_origin(err, o) } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 094488f3af3cf..7b5e704f60f6e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4948,7 +4948,7 @@ fn show_candidates(err: &mut DiagnosticBuilder, err.span_suggestions_with_applicability( span, &msg, - path_strings, + path_strings.into_iter(), Applicability::Unspecified, ); } else { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 7773e2d570844..0a196834cb494 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -132,7 +132,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if compatible_variants.peek().is_some() { let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr)); let suggestions = compatible_variants - .map(|v| format!("{}({})", v, expr_text)).collect::<Vec<_>>(); + .map(|v| format!("{}({})", v, expr_text)); err.span_suggestions_with_applicability( expr.span, "try using a variant of the expected type", diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 5a63a2971e49d..cd243d4144394 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -521,7 +521,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { with_crate_prefix(|| self.tcx.item_path_str(*did)), additional_newline ) - }).collect(); + }); err.span_suggestions_with_applicability( span, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4851938653b53..17784a4681d00 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4744,7 +4744,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else if !self.check_for_cast(err, expr, found, expected) { let methods = self.get_conversion_methods(expr.span, expected, found); if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { - let suggestions = iter::repeat(&expr_text).zip(methods.iter()) + let mut suggestions = iter::repeat(&expr_text).zip(methods.iter()) .filter_map(|(receiver, method)| { let method_call = format!(".{}()", method.ident); if receiver.ends_with(&method_call) { @@ -4760,8 +4760,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(format!("{}{}", receiver, method_call)) } } - }).collect::<Vec<_>>(); - if !suggestions.is_empty() { + }).peekable(); + if suggestions.peek().is_some() { err.span_suggestions_with_applicability( expr.span, "try using a conversion method", diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 33b651e1b3854..41ed90fb94eed 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -387,6 +387,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { add_derived_markers(&mut self.cx, item.span(), &traits, item.clone()); let derives = derives.entry(invoc.expansion_data.mark).or_default(); + derives.reserve(traits.len()); + invocations.reserve(traits.len()); for path in &traits { let mark = Mark::fresh(self.cx.current_expansion.mark); derives.push(mark); @@ -687,7 +689,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { "proc_macro_hygiene", self.span, GateIssue::Language, - &format!("procedural macros cannot expand to macro definitions"), + "procedural macros cannot expand to macro definitions", ); } visit::walk_item(self, i); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 03a8376e76361..38bbfc6b4c375 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -143,6 +143,8 @@ struct MatcherTtFrame<'a> { idx: usize, } +type NamedMatchVec = SmallVec<[NamedMatch; 4]>; + /// Represents a single "position" (aka "matcher position", aka "item"), as described in the module /// documentation. #[derive(Clone)] @@ -168,7 +170,7 @@ struct MatcherPos<'a> { /// all bound matches from the submatcher into the shared top-level `matches` vector. If `sep` /// and `up` are `Some`, then `matches` is _not_ the shared top-level list. Instead, if one /// wants the shared `matches`, one should use `up.matches`. - matches: Vec<Rc<Vec<NamedMatch>>>, + matches: Box<[Rc<NamedMatchVec>]>, /// The position in `matches` corresponding to the first metavar in this matcher's sequence of /// token trees. In other words, the first metavar in the first token of `top_elts` corresponds /// to `matches[match_lo]`. @@ -278,9 +280,14 @@ pub fn count_names(ms: &[TokenTree]) -> usize { }) } -/// Initialize `len` empty shared `Vec`s to be used to store matches of metavars. -fn create_matches(len: usize) -> Vec<Rc<Vec<NamedMatch>>> { - (0..len).into_iter().map(|_| Rc::new(Vec::new())).collect() +/// `len` `Vec`s (initially shared and empty) that will store matches of metavars. +fn create_matches(len: usize) -> Box<[Rc<NamedMatchVec>]> { + if len == 0 { + vec![] + } else { + let empty_matches = Rc::new(SmallVec::new()); + vec![empty_matches.clone(); len] + }.into_boxed_slice() } /// Generate the top-level matcher position in which the "dot" is before the first token of the @@ -332,7 +339,7 @@ fn initial_matcher_pos(ms: &[TokenTree], open: Span) -> MatcherPos { /// token tree it was derived from. #[derive(Debug, Clone)] pub enum NamedMatch { - MatchedSeq(Rc<Vec<NamedMatch>>, DelimSpan), + MatchedSeq(Rc<NamedMatchVec>, DelimSpan), MatchedNonterminal(Rc<Nonterminal>), } @@ -540,7 +547,7 @@ fn inner_parse_loop<'a>( new_item.match_cur += seq.num_captures; new_item.idx += 1; for idx in item.match_cur..item.match_cur + seq.num_captures { - new_item.push_match(idx, MatchedSeq(Rc::new(vec![]), sp)); + new_item.push_match(idx, MatchedSeq(Rc::new(smallvec![]), sp)); } cur_items.push(new_item); } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 002ecce58e652..dd90ef06c3929 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1384,7 +1384,7 @@ impl<'a> MethodDef<'a> { // let __self2_vi = unsafe { // std::intrinsics::discriminant_value(&arg2) } as i32; // ``` - let mut index_let_stmts: Vec<ast::Stmt> = Vec::new(); + let mut index_let_stmts: Vec<ast::Stmt> = Vec::with_capacity(vi_idents.len() + 1); // We also build an expression which checks whether all discriminants are equal // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... diff --git a/src/test/run-pass/invalid_const_promotion.rs b/src/test/run-pass/invalid_const_promotion.rs index ed8c4992417af..0f354e1aad6c9 100644 --- a/src/test/run-pass/invalid_const_promotion.rs +++ b/src/test/run-pass/invalid_const_promotion.rs @@ -39,6 +39,7 @@ fn check_status(status: std::process::ExitStatus) use std::os::unix::process::ExitStatusExt; assert!(status.signal() == Some(libc::SIGILL) + || status.signal() == Some(libc::SIGTRAP) || status.signal() == Some(libc::SIGABRT)); } diff --git a/src/test/run-pass/issues/issue-54477-reduced-2.rs b/src/test/run-pass/issues/issue-54477-reduced-2.rs new file mode 100644 index 0000000000000..28731d4b0df02 --- /dev/null +++ b/src/test/run-pass/issues/issue-54477-reduced-2.rs @@ -0,0 +1,25 @@ +// rust-lang/rust#54477: runtime bug in the VecDeque library that was +// exposed by this test case, derived from test suite of crates.io +// `collection` crate. + +use std::collections::VecDeque; + +fn main() { + let mut vecdeque_13 = VecDeque::from(vec![ ]); + let mut vecdeque_29 = VecDeque::from(vec![ 0 ]); + vecdeque_29.insert(0, 30 ); + vecdeque_29.insert(1, 31 ); + vecdeque_29.insert(2, 32 ); + vecdeque_29.insert(3, 33 ); + vecdeque_29.insert(4, 34 ); + vecdeque_29.insert(5, 35 ); + // println!("vecdeque_13: {:?}", vecdeque_13); + // println!("vecdeque_29: {:?}", vecdeque_29); + + // println!("Invoking: `vecdeque_13.append(&mut vecdeque_29)`"); + vecdeque_13.append(&mut vecdeque_29); + + // println!("vecdeque_13: {:?}", vecdeque_13); + + assert_eq!(vecdeque_13, VecDeque::from(vec![30, 31, 32, 33, 34, 35, 0])); +} diff --git a/src/test/ui/consts/const-eval/double_check.rs b/src/test/ui/consts/const-eval/double_check.rs index 81f6e7ddd2de2..76f9276c05807 100644 --- a/src/test/ui/consts/const-eval/double_check.rs +++ b/src/test/ui/consts/const-eval/double_check.rs @@ -21,12 +21,12 @@ enum Bar { union Union { foo: &'static Foo, bar: &'static Bar, - usize: &'static usize, + u8: &'static u8, } -static BAR: usize = 42; +static BAR: u8 = 42; static FOO: (&Foo, &Bar) = unsafe {( - Union { usize: &BAR }.foo, - Union { usize: &BAR }.bar, + Union { u8: &BAR }.foo, + Union { u8: &BAR }.bar, )}; fn main() {} diff --git a/src/test/ui/consts/const-eval/double_check2.rs b/src/test/ui/consts/const-eval/double_check2.rs index b661ee92475e6..701632362ce7a 100644 --- a/src/test/ui/consts/const-eval/double_check2.rs +++ b/src/test/ui/consts/const-eval/double_check2.rs @@ -19,12 +19,12 @@ enum Bar { union Union { foo: &'static Foo, bar: &'static Bar, - usize: &'static usize, + u8: &'static u8, } -static BAR: usize = 5; +static BAR: u8 = 5; static FOO: (&Foo, &Bar) = unsafe {( //~ undefined behavior - Union { usize: &BAR }.foo, - Union { usize: &BAR }.bar, + Union { u8: &BAR }.foo, + Union { u8: &BAR }.bar, )}; fn main() {} diff --git a/src/test/ui/consts/const-eval/double_check2.stderr b/src/test/ui/consts/const-eval/double_check2.stderr index 9dd7570232d37..28825477c8102 100644 --- a/src/test/ui/consts/const-eval/double_check2.stderr +++ b/src/test/ui/consts/const-eval/double_check2.stderr @@ -2,8 +2,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/double_check2.rs:25:1 | LL | / static FOO: (&Foo, &Bar) = unsafe {( //~ undefined behavior -LL | | Union { usize: &BAR }.foo, -LL | | Union { usize: &BAR }.bar, +LL | | Union { u8: &BAR }.foo, +LL | | Union { u8: &BAR }.bar, LL | | )}; | |___^ type validation failed: encountered invalid enum discriminant 5 at .1.<deref> | diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index ca30a4dd95d0e..f63950b448a14 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -766,7 +766,7 @@ fn make_test_name( .join(&testpaths.file.file_name().unwrap()); let mode_suffix = match config.compare_mode { Some(ref mode) => format!(" ({})", mode.to_str()), - None => format!(""), + None => String::new(), }; test::DynTestName(format!( "[{}{}] {}{}", diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 1539c2e25781b..c794e169fca33 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -14,7 +14,6 @@ import sys import re import json -import copy import datetime import collections import textwrap