From 2a1efca2f332055ff1a68164040afbb9e394edd0 Mon Sep 17 00:00:00 2001 From: Jake Worth Date: Tue, 15 Dec 2015 12:51:08 -0600 Subject: [PATCH 01/13] Fix typo --- src/librustc_trans/trans/adt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index f6f1918fd0741..c744ef321278d 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -1165,7 +1165,7 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v let meta = val.meta; - // Calculate the unaligned offset of the the unsized field. + // Calculate the unaligned offset of the unsized field. let mut offset = 0; for &ty in &st.fields[0..ix] { let llty = type_of::sizing_type_of(ccx, ty); From d91b256fe54b5ac2095c4417407497b0739c8b29 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Tue, 15 Dec 2015 20:48:25 -0500 Subject: [PATCH 02/13] change macro ambiguity example from ty to ident The previous example had no chance of compiling in either form, due to the restrictive follow set for `ty`. This one has the desired behavior: http://is.gd/kYdw4g (well, I don't exactly desire this behavior at all, but it's true at least :p ) --- src/doc/book/macros.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/book/macros.md b/src/doc/book/macros.md index f7f27858cd240..e4a900a2b1a4f 100644 --- a/src/doc/book/macros.md +++ b/src/doc/book/macros.md @@ -485,10 +485,10 @@ These rules provide some flexibility for Rust’s syntax to evolve without breaking existing macros. The macro system does not deal with parse ambiguity at all. For example, the -grammar `$($t:ty)* $e:expr` will always fail to parse, because the parser would -be forced to choose between parsing `$t` and parsing `$e`. Changing the +grammar `$($i:ident)* $e:expr` will always fail to parse, because the parser would +be forced to choose between parsing `$i` and parsing `$e`. Changing the invocation syntax to put a distinctive token in front can solve the problem. In -this case, you can write `$(T $t:ty)* E $e:exp`. +this case, you can write `$(I $i:ident)* E $e:expr`. [item]: ../reference.html#items From 6309b0f5bb558b844f45b2d313d2078fd7b7614c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 Dec 2015 11:17:55 +1300 Subject: [PATCH 03/13] move error handling from libsyntax/diagnostics.rs to libsyntax/errors/* Also split out emitters into their own module. --- src/librustc/lint/context.rs | 6 +- src/librustc/session/config.rs | 26 +- src/librustc/session/mod.rs | 59 +- src/librustc/session/search_paths.rs | 4 +- src/librustc_back/target/mod.rs | 8 +- src/librustc_driver/lib.rs | 25 +- src/librustc_front/print/pprust.rs | 6 +- src/librustc_metadata/encoder.rs | 9 +- src/librustc_metadata/loader.rs | 6 +- src/librustc_metadata/tyencode.rs | 8 +- src/librustc_plugin/build.rs | 8 +- src/librustc_trans/back/lto.rs | 2 +- src/librustc_trans/back/write.rs | 21 +- src/librustdoc/core.rs | 16 +- src/librustdoc/lib.rs | 6 +- src/librustdoc/test.rs | 27 +- src/libsyntax/attr.rs | 28 +- src/libsyntax/config.rs | 18 +- src/libsyntax/diagnostic.rs | 900 ---------------------- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/ext/tt/transcribe.rs | 8 +- src/libsyntax/feature_gate.rs | 24 +- src/libsyntax/lib.rs | 5 +- src/libsyntax/parse/lexer/comments.rs | 4 +- src/libsyntax/parse/lexer/mod.rs | 17 +- src/libsyntax/parse/mod.rs | 27 +- src/libsyntax/parse/obsolete.rs | 3 +- src/libsyntax/parse/parser.rs | 13 +- src/libsyntax/print/pprust.rs | 6 +- src/libsyntax/show_span.rs | 6 +- src/libsyntax/test.rs | 12 +- src/libsyntax_ext/deriving/generic/mod.rs | 4 +- 33 files changed, 207 insertions(+), 1109 deletions(-) delete mode 100644 src/libsyntax/diagnostic.rs diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 1ed873f0508d5..054e0401b273d 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -47,7 +47,7 @@ use rustc_front::hir; use rustc_front::util; use rustc_front::intravisit as hir_visit; use syntax::visit as ast_visit; -use syntax::diagnostic; +use syntax::errors; /// Information about the registered lints. /// @@ -167,7 +167,7 @@ impl LintStore { match (sess, from_plugin) { // We load builtin lints first, so a duplicate is a compiler bug. // Use early_error when handling -W help with no crate. - (None, _) => early_error(diagnostic::Auto, &msg[..]), + (None, _) => early_error(errors::ColorConfig::Auto, &msg[..]), (Some(sess), false) => sess.bug(&msg[..]), // A duplicate name from a plugin is a user error. @@ -191,7 +191,7 @@ impl LintStore { match (sess, from_plugin) { // We load builtin lints first, so a duplicate is a compiler bug. // Use early_error when handling -W help with no crate. - (None, _) => early_error(diagnostic::Auto, &msg[..]), + (None, _) => early_error(errors::ColorConfig::Auto, &msg[..]), (Some(sess), false) => sess.bug(&msg[..]), // A duplicate name from a plugin is a user error. diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 6fb8c03370142..75761dbc15ade 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -27,7 +27,7 @@ use middle::cstore; use syntax::ast::{self, IntTy, UintTy}; use syntax::attr; use syntax::attr::AttrMetaMethods; -use syntax::diagnostic::{ColorConfig, Auto, Always, Never, SpanHandler}; +use syntax::errors::{ColorConfig, Handler}; use syntax::parse; use syntax::parse::token::InternedString; use syntax::feature_gate::UnstableFeatures; @@ -238,7 +238,7 @@ pub fn basic_options() -> Options { debugging_opts: basic_debugging_options(), prints: Vec::new(), cg: basic_codegen_options(), - color: Auto, + color: ColorConfig::Auto, show_span: None, externs: HashMap::new(), crate_name: None, @@ -687,19 +687,19 @@ pub fn build_configuration(sess: &Session) -> ast::CrateConfig { v } -pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config { +pub fn build_target_config(opts: &Options, sp: &Handler) -> Config { let target = match Target::search(&opts.target_triple) { Ok(t) => t, Err(e) => { - panic!(sp.handler().fatal(&format!("Error loading target specification: {}", e))); + panic!(sp.fatal(&format!("Error loading target specification: {}", e))); } }; let (int_type, uint_type) = match &target.target_pointer_width[..] { "32" => (ast::TyI32, ast::TyU32), "64" => (ast::TyI64, ast::TyU64), - w => panic!(sp.handler().fatal(&format!("target specification was invalid: \ - unrecognized target-pointer-width {}", w))), + w => panic!(sp.fatal(&format!("target specification was invalid: \ + unrecognized target-pointer-width {}", w))), }; Config { @@ -884,16 +884,16 @@ pub fn parse_cfgspecs(cfgspecs: Vec ) -> ast::CrateConfig { pub fn build_session_options(matches: &getopts::Matches) -> Options { let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) { - Some("auto") => Auto, - Some("always") => Always, - Some("never") => Never, + Some("auto") => ColorConfig::Auto, + Some("always") => ColorConfig::Always, + Some("never") => ColorConfig::Never, - None => Auto, + None => ColorConfig::Auto, Some(arg) => { - early_error(Auto, &format!("argument for --color must be auto, always \ - or never (instead was `{}`)", - arg)) + early_error(ColorConfig::Auto, &format!("argument for --color must be auto, always \ + or never (instead was `{}`)", + arg)) } }; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index b7bfc2f8db53e..76d765c9626a3 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -16,7 +16,8 @@ use util::nodemap::{NodeMap, FnvHashMap}; use syntax::ast::{NodeId, NodeIdAssigner, Name}; use syntax::codemap::Span; -use syntax::diagnostic::{self, Emitter}; +use syntax::errors; +use syntax::errors::emitter::{Emitter, BasicEmitter}; use syntax::diagnostics; use syntax::feature_gate; use syntax::parse; @@ -99,7 +100,7 @@ impl Session { if self.opts.treat_err_as_bug { self.bug(msg); } - panic!(self.diagnostic().handler().fatal(msg)) + panic!(self.diagnostic().fatal(msg)) } pub fn span_err_or_warn(&self, is_warning: bool, sp: Span, msg: &str) { if is_warning { @@ -137,16 +138,16 @@ impl Session { if self.opts.treat_err_as_bug { self.bug(msg); } - self.diagnostic().handler().err(msg) + self.diagnostic().err(msg) } pub fn err_count(&self) -> usize { - self.diagnostic().handler().err_count() + self.diagnostic().err_count() } pub fn has_errors(&self) -> bool { - self.diagnostic().handler().has_errors() + self.diagnostic().has_errors() } pub fn abort_if_errors(&self) { - self.diagnostic().handler().abort_if_errors(); + self.diagnostic().abort_if_errors(); let delayed_bug = self.delayed_span_bug.borrow(); match *delayed_bug { @@ -177,7 +178,7 @@ impl Session { } pub fn warn(&self, msg: &str) { if self.can_print_warnings { - self.diagnostic().handler().warn(msg) + self.diagnostic().warn(msg) } } pub fn opt_span_warn(&self, opt_sp: Option, msg: &str) { @@ -195,7 +196,7 @@ impl Session { /// Prints out a message with a suggested edit of the code. /// - /// See `diagnostic::RenderSpan::Suggestion` for more information. + /// See `errors::RenderSpan::Suggestion` for more information. pub fn span_suggestion(&self, sp: Span, msg: &str, suggestion: String) { self.diagnostic().span_suggestion(sp, msg, suggestion) } @@ -209,10 +210,10 @@ impl Session { self.diagnostic().fileline_help(sp, msg) } pub fn note(&self, msg: &str) { - self.diagnostic().handler().note(msg) + self.diagnostic().note(msg) } pub fn help(&self, msg: &str) { - self.diagnostic().handler().help(msg) + self.diagnostic().help(msg) } pub fn opt_span_bug(&self, opt_sp: Option, msg: &str) -> ! { match opt_sp { @@ -229,13 +230,13 @@ impl Session { self.diagnostic().span_bug(sp, msg) } pub fn bug(&self, msg: &str) -> ! { - self.diagnostic().handler().bug(msg) + self.diagnostic().bug(msg) } pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! { self.diagnostic().span_unimpl(sp, msg) } pub fn unimpl(&self, msg: &str) -> ! { - self.diagnostic().handler().unimpl(msg) + self.diagnostic().unimpl(msg) } pub fn add_lint(&self, lint: &'static lint::Lint, @@ -260,7 +261,7 @@ impl Session { id } - pub fn diagnostic<'a>(&'a self) -> &'a diagnostic::SpanHandler { + pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { &self.parse_sess.span_diagnostic } pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { @@ -414,29 +415,27 @@ pub fn build_session(sopts: config::Options, .last() .unwrap_or(true); - let codemap = codemap::CodeMap::new(); + let codemap = Rc::new(codemap::CodeMap::new()); let diagnostic_handler = - diagnostic::Handler::new(sopts.color, Some(registry), can_print_warnings); - let span_diagnostic_handler = - diagnostic::SpanHandler::new(diagnostic_handler, codemap); + errors::Handler::new(sopts.color, Some(registry), can_print_warnings, codemap.clone()); - build_session_(sopts, local_crate_source_file, span_diagnostic_handler, cstore) + build_session_(sopts, local_crate_source_file, diagnostic_handler, codemap, cstore) } pub fn build_session_(sopts: config::Options, local_crate_source_file: Option, - span_diagnostic: diagnostic::SpanHandler, + span_diagnostic: errors::Handler, + codemap: Rc, cstore: Rc CrateStore<'a>>) -> Session { let host = match Target::search(config::host_triple()) { Ok(t) => t, Err(e) => { - panic!(span_diagnostic.handler() - .fatal(&format!("Error loading host specification: {}", e))); + panic!(span_diagnostic.fatal(&format!("Error loading host specification: {}", e))); } }; let target_cfg = config::build_target_config(&sopts, &span_diagnostic); - let p_s = parse::ParseSess::with_span_handler(span_diagnostic); + let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap); let default_sysroot = match sopts.maybe_sysroot { Some(_) => None, None => Some(filesearch::get_or_default_sysroot()) @@ -494,16 +493,16 @@ pub fn build_session_(sopts: config::Options, pub fn expect(sess: &Session, opt: Option, msg: M) -> T where M: FnOnce() -> String, { - diagnostic::expect(sess.diagnostic(), opt, msg) + errors::expect(sess.diagnostic(), opt, msg) } -pub fn early_error(color: diagnostic::ColorConfig, msg: &str) -> ! { - let mut emitter = diagnostic::EmitterWriter::stderr(color, None); - emitter.emit(None, msg, None, diagnostic::Fatal); - panic!(diagnostic::FatalError); +pub fn early_error(color: errors::ColorConfig, msg: &str) -> ! { + let mut emitter = BasicEmitter::stderr(color); + emitter.emit(None, msg, None, errors::Level::Fatal); + panic!(errors::FatalError); } -pub fn early_warn(color: diagnostic::ColorConfig, msg: &str) { - let mut emitter = diagnostic::EmitterWriter::stderr(color, None); - emitter.emit(None, msg, None, diagnostic::Warning); +pub fn early_warn(color: errors::ColorConfig, msg: &str) { + let mut emitter = BasicEmitter::stderr(color); + emitter.emit(None, msg, None, errors::Level::Warning); } diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index caf776dad85e0..6a787139d77aa 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -11,7 +11,7 @@ use std::slice; use std::path::{Path, PathBuf}; use session::early_error; -use syntax::diagnostic; +use syntax::errors; #[derive(Clone, Debug)] pub struct SearchPaths { @@ -38,7 +38,7 @@ impl SearchPaths { SearchPaths { paths: Vec::new() } } - pub fn add_path(&mut self, path: &str, color: diagnostic::ColorConfig) { + pub fn add_path(&mut self, path: &str, color: errors::ColorConfig) { let (kind, path) = if path.starts_with("native=") { (PathKind::Native, &path["native=".len()..]) } else if path.starts_with("crate=") { diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 1bfb7471daa21..f259698a220e2 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -48,7 +48,7 @@ use serialize::json::Json; use std::default::Default; use std::io::prelude::*; -use syntax::{diagnostic, abi}; +use syntax::abi; mod android_base; mod apple_base; @@ -263,17 +263,13 @@ impl Target { pub fn from_json(obj: Json) -> Target { // this is 1. ugly, 2. error prone. - - let handler = diagnostic::Handler::new(diagnostic::Auto, None, true); - let get_req_field = |name: &str| { match obj.find(name) .map(|s| s.as_string()) .and_then(|os| os.map(|s| s.to_string())) { Some(val) => val, None => { - panic!(handler.fatal(&format!("Field {} in target specification is required", - name))) + panic!("Field {} in target specification is required", name) } } }; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index fcbcdbacd33cb..8cfaec62f4775 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -59,8 +59,6 @@ extern crate log; extern crate syntax; extern crate syntax_ext; -pub use syntax::diagnostic; - use driver::CompileController; use pretty::{PpMode, UserIdentifiedItem}; @@ -91,7 +89,8 @@ use rustc::session::early_error; use syntax::ast; use syntax::parse; -use syntax::diagnostic::Emitter; +use syntax::errors; +use syntax::errors::emitter::Emitter; use syntax::diagnostics; use syntax::parse::token; @@ -239,7 +238,7 @@ pub trait CompilerCalls<'a> { fn early_callback(&mut self, _: &getopts::Matches, _: &diagnostics::registry::Registry, - _: diagnostic::ColorConfig) + _: errors::ColorConfig) -> Compilation { Compilation::Continue } @@ -315,7 +314,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn early_callback(&mut self, matches: &getopts::Matches, descriptions: &diagnostics::registry::Registry, - color: diagnostic::ColorConfig) + color: errors::ColorConfig) -> Compilation { match matches.opt_str("explain") { Some(ref code) => { @@ -774,7 +773,7 @@ pub fn handle_options(mut args: Vec) -> Option { &opt.opt_group.short_name }; if m.opt_present(opt_name) { - early_error(diagnostic::Auto, + early_error(errors::ColorConfig::Auto, &format!("use of unstable option '{}' requires -Z \ unstable-options", opt_name)); @@ -783,7 +782,7 @@ pub fn handle_options(mut args: Vec) -> Option { } m } - Err(f) => early_error(diagnostic::Auto, &f.to_string()), + Err(f) => early_error(errors::ColorConfig::Auto, &f.to_string()), } } @@ -895,25 +894,25 @@ pub fn monitor(f: F) { } Err(value) => { // Thread panicked without emitting a fatal diagnostic - if !value.is::() { - let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None); + if !value.is::() { + let mut emitter = errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto); // a .span_bug or .bug call has already printed what // it wants to print. - if !value.is::() { - emitter.emit(None, "unexpected panic", None, diagnostic::Bug); + if !value.is::() { + emitter.emit(None, "unexpected panic", None, errors::Level::Bug); } let xs = ["the compiler unexpectedly panicked. this is a bug.".to_string(), format!("we would appreciate a bug report: {}", BUG_REPORT_URL)]; for note in &xs { - emitter.emit(None, ¬e[..], None, diagnostic::Note) + emitter.emit(None, ¬e[..], None, errors::Level::Note) } if let None = env::var_os("RUST_BACKTRACE") { emitter.emit(None, "run with `RUST_BACKTRACE=1` for a backtrace", None, - diagnostic::Note); + errors::Level::Note); } println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap()); diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index 81076b6e40276..13ddd9ca55ce4 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -14,7 +14,7 @@ use syntax::abi; use syntax::ast; use syntax::owned_slice::OwnedSlice; use syntax::codemap::{self, CodeMap, BytePos, Spanned}; -use syntax::diagnostic; +use syntax::errors; use syntax::parse::token::{self, BinOpToken}; use syntax::parse::lexer::comments; use syntax::parse; @@ -121,7 +121,7 @@ pub const default_columns: usize = 78; /// it can scan the input text for comments and literals to /// copy forward. pub fn print_crate<'a>(cm: &'a CodeMap, - span_diagnostic: &diagnostic::SpanHandler, + span_diagnostic: &errors::Handler, krate: &hir::Crate, filename: String, input: &mut Read, @@ -142,7 +142,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, impl<'a> State<'a> { pub fn new_from_input(cm: &'a CodeMap, - span_diagnostic: &diagnostic::SpanHandler, + span_diagnostic: &errors::Handler, filename: String, input: &mut Read, out: Box, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 888776eaa5610..cd70172e8fa21 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -44,7 +44,7 @@ use syntax::abi; use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum}; use syntax::attr; use syntax::attr::AttrMetaMethods; -use syntax::diagnostic::SpanHandler; +use syntax::errors::Handler; use syntax::parse::token::special_idents; use syntax; use rbml::writer::Encoder; @@ -57,7 +57,7 @@ pub type EncodeInlinedItem<'a> = Box; pub struct EncodeParams<'a, 'tcx: 'a> { - pub diag: &'a SpanHandler, + pub diag: &'a Handler, pub tcx: &'a ty::ctxt<'tcx>, pub reexports: &'a def::ExportMap, pub item_symbols: &'a RefCell>, @@ -69,7 +69,7 @@ pub struct EncodeParams<'a, 'tcx: 'a> { } pub struct EncodeContext<'a, 'tcx: 'a> { - pub diag: &'a SpanHandler, + pub diag: &'a Handler, pub tcx: &'a ty::ctxt<'tcx>, pub reexports: &'a def::ExportMap, pub item_symbols: &'a RefCell>, @@ -275,8 +275,7 @@ fn encode_symbol(ecx: &EncodeContext, rbml_w.wr_tagged_str(tag_items_data_item_symbol, x); } None => { - ecx.diag.handler().bug( - &format!("encode_symbol: id not found {}", id)); + ecx.diag.bug(&format!("encode_symbol: id not found {}", id)); } } } diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index bd9f9c36f631b..81788e08c7ef2 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -226,7 +226,7 @@ use rustc_llvm as llvm; use rustc_llvm::{False, ObjectFile, mk_section_iter}; use rustc_llvm::archive_ro::ArchiveRO; use syntax::codemap::Span; -use syntax::diagnostic::SpanHandler; +use syntax::errors::Handler; use rustc_back::target::Target; use std::cmp; @@ -697,8 +697,8 @@ impl<'a> Context<'a> { } } -pub fn note_crate_name(diag: &SpanHandler, name: &str) { - diag.handler().note(&format!("crate name: {}", name)); +pub fn note_crate_name(diag: &Handler, name: &str) { + diag.note(&format!("crate name: {}", name)); } impl ArchiveMetadata { diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index bc1edd5c76718..e1329f288b2c5 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -29,14 +29,14 @@ use rustc_front::hir; use syntax::abi::Abi; use syntax::ast; -use syntax::diagnostic::SpanHandler; +use syntax::errors::Handler; use rbml::writer::{self, Encoder}; macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) } pub struct ctxt<'a, 'tcx: 'a> { - pub diag: &'a SpanHandler, + pub diag: &'a Handler, // Def -> str Callback: pub ds: fn(DefId) -> String, // The type context. @@ -136,7 +136,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { enc_bare_fn_ty(w, cx, f); } ty::TyInfer(_) => { - cx.diag.handler().bug("cannot encode inference variable types"); + cx.diag.bug("cannot encode inference variable types"); } ty::TyParam(ParamTy {space, idx, name}) => { mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), name) @@ -279,7 +279,7 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) { } ty::ReVar(_) | ty::ReSkolemized(..) => { // these should not crop up after typeck - cx.diag.handler().bug("cannot encode region variables"); + cx.diag.bug("cannot encode region variables"); } } } diff --git a/src/librustc_plugin/build.rs b/src/librustc_plugin/build.rs index 00f58c6af9155..476425a75c22d 100644 --- a/src/librustc_plugin/build.rs +++ b/src/librustc_plugin/build.rs @@ -13,7 +13,7 @@ use syntax::ast; use syntax::attr; use syntax::codemap::Span; -use syntax::diagnostic; +use syntax::errors; use rustc_front::intravisit::Visitor; use rustc_front::hir; @@ -33,7 +33,7 @@ impl<'v> Visitor<'v> for RegistrarFinder { } /// Find the function marked with `#[plugin_registrar]`, if any. -pub fn find_plugin_registrar(diagnostic: &diagnostic::SpanHandler, +pub fn find_plugin_registrar(diagnostic: &errors::Handler, krate: &hir::Crate) -> Option { let mut finder = RegistrarFinder { registrars: Vec::new() }; @@ -46,11 +46,11 @@ pub fn find_plugin_registrar(diagnostic: &diagnostic::SpanHandler, Some(node_id) }, _ => { - diagnostic.handler().err("multiple plugin registration functions found"); + diagnostic.err("multiple plugin registration functions found"); for &(_, span) in &finder.registrars { diagnostic.span_note(span, "one is here"); } - diagnostic.handler().abort_if_errors(); + diagnostic.abort_if_errors(); unreachable!(); } } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index ba6ec895a8e12..8505c3968ee15 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -101,7 +101,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, if !llvm::LLVMRustLinkInExternalBitcode(llmod, ptr as *const libc::c_char, bc_decoded.len() as libc::size_t) { - write::llvm_err(sess.diagnostic().handler(), + write::llvm_err(sess.diagnostic(), format!("failed to load bc of `{}`", &name[..])); } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 4815a399d9913..26813d89915ac 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -20,8 +20,8 @@ use trans::{CrateTranslation, ModuleTranslation}; use util::common::time; use util::common::path2cstr; use syntax::codemap; -use syntax::diagnostic; -use syntax::diagnostic::{Emitter, Handler, Level}; +use syntax::errors::{self, Handler, Level}; +use syntax::errors::emitter::Emitter; use std::collections::HashMap; use std::ffi::{CStr, CString}; @@ -34,7 +34,7 @@ use std::sync::mpsc::channel; use std::thread; use libc::{self, c_uint, c_int, c_void}; -pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { +pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! { unsafe { let cstr = llvm::LLVMRustGetLastError(); if cstr == ptr::null() { @@ -49,7 +49,7 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { } pub fn write_output_file( - handler: &diagnostic::Handler, + handler: &errors::Handler, target: llvm::TargetMachineRef, pm: llvm::PassManagerRef, m: ModuleRef, @@ -109,9 +109,9 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, codemap::Span)>, + fn emit(&mut self, sp: Option, msg: &str, code: Option<&str>, lvl: Level) { - assert!(cmsp.is_none(), "SharedEmitter doesn't support spans"); + assert!(sp.is_none(), "SharedEmitter doesn't support spans"); self.buffer.lock().unwrap().push(Diagnostic { msg: msg.to_string(), @@ -120,8 +120,7 @@ impl Emitter for SharedEmitter { }); } - fn custom_emit(&mut self, _cm: &codemap::CodeMap, - _sp: diagnostic::RenderSpan, _msg: &str, _lvl: Level) { + fn custom_emit(&mut self, _sp: errors::RenderSpan, _msg: &str, _lvl: Level) { panic!("SharedEmitter doesn't support custom_emit"); } } @@ -226,7 +225,7 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef { }; if tm.is_null() { - llvm_err(sess.diagnostic().handler(), + llvm_err(sess.diagnostic(), format!("Could not create LLVM TargetMachine for triple: {}", triple).to_string()); } else { @@ -333,7 +332,7 @@ impl<'a> CodegenContext<'a> { fn new_with_session(sess: &'a Session, reachable: &'a [String]) -> CodegenContext<'a> { CodegenContext { lto_ctxt: Some((sess, reachable)), - handler: sess.diagnostic().handler(), + handler: sess.diagnostic(), plugin_passes: sess.plugin_llvm_passes.borrow().clone(), remark: sess.opts.cg.remark.clone(), worker: 0, @@ -903,7 +902,7 @@ fn run_work_multithreaded(sess: &Session, }, } // Display any new diagnostics. - diag_emitter.dump(sess.diagnostic().handler()); + diag_emitter.dump(sess.diagnostic()); } if panicked { sess.fatal("aborting due to worker thread panic"); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1ccab1b16ebdb..c6c98851f7c34 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -22,7 +22,8 @@ use rustc_resolve as resolve; use rustc_front::lowering::{lower_crate, LoweringContext}; use rustc_metadata::cstore::CStore; -use syntax::{ast, codemap, diagnostic}; +use syntax::{ast, codemap, errors}; +use syntax::errors::emitter::ColorConfig; use syntax::feature_gate::UnstableFeatures; use syntax::parse::token; @@ -116,15 +117,16 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, ..config::basic_options().clone() }; - let codemap = codemap::CodeMap::new(); - let diagnostic_handler = diagnostic::Handler::new(diagnostic::Auto, None, true); - let span_diagnostic_handler = - diagnostic::SpanHandler::new(diagnostic_handler, codemap); + let codemap = Rc::new(codemap::CodeMap::new()); + let diagnostic_handler = errors::Handler::new(ColorConfig::Auto, + None, + true, + false, + codemap.clone()); let cstore = Rc::new(CStore::new(token::get_ident_interner())); let cstore_ = ::rustc_driver::cstore_to_cratestore(cstore.clone()); - let sess = session::build_session_(sessopts, cpath, - span_diagnostic_handler, cstore_); + let sess = session::build_session_(sessopts, cpath, diagnostic_handler, codemap, cstore_); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index af6510cb3870e..31fdc1170c026 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -65,7 +65,7 @@ use externalfiles::ExternalHtml; use serialize::Decodable; use serialize::json::{self, Json}; use rustc::session::search_paths::SearchPaths; -use syntax::diagnostic; +use syntax::errors::emitter::ColorConfig; // reexported from `clean` so it can be easily updated with the mod itself pub use clean::SCHEMA_VERSION; @@ -228,7 +228,7 @@ pub fn main_args(args: &[String]) -> isize { let mut libs = SearchPaths::new(); for s in &matches.opt_strs("L") { - libs.add_path(s, diagnostic::Auto); + libs.add_path(s, ColorConfig::Auto); } let externs = match parse_externs(&matches) { Ok(ex) => ex, @@ -363,7 +363,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche // First, parse the crate and extract all relevant information. let mut paths = SearchPaths::new(); for s in &matches.opt_strs("L") { - paths.add_path(s, diagnostic::Auto); + paths.add_path(s, ColorConfig::Auto); } let cfgs = matches.opt_strs("cfg"); let triple = matches.opt_str("target"); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3322794c7781e..4ac20ba001b9f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -34,7 +34,8 @@ use rustc_back::tempdir::TempDir; use rustc_driver::{driver, Compilation}; use rustc_metadata::cstore::CStore; use syntax::codemap::CodeMap; -use syntax::diagnostic; +use syntax::errors; +use syntax::errors::emitter::ColorConfig; use syntax::parse::token; use core; @@ -71,16 +72,19 @@ pub fn run(input: &str, ..config::basic_options().clone() }; - let codemap = CodeMap::new(); - let diagnostic_handler = diagnostic::Handler::new(diagnostic::Auto, None, true); - let span_diagnostic_handler = - diagnostic::SpanHandler::new(diagnostic_handler, codemap); + let codemap = Rc::new(CodeMap::new()); + let diagnostic_handler = errors::Handler::new(ColorConfig::Auto, + None, + true, + false, + codemap.clone()); let cstore = Rc::new(CStore::new(token::get_ident_interner())); let cstore_ = ::rustc_driver::cstore_to_cratestore(cstore.clone()); let sess = session::build_session_(sessopts, Some(input_path.clone()), - span_diagnostic_handler, + diagnostic_handler, + codemap, cstore_); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); @@ -220,21 +224,20 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, } } let data = Arc::new(Mutex::new(Vec::new())); - let emitter = diagnostic::EmitterWriter::new(box Sink(data.clone()), None); + let codemap = Rc::new(CodeMap::new()); + let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()), None, codemap.clone()); let old = io::set_panic(box Sink(data.clone())); let _bomb = Bomb(data, old.unwrap_or(box io::stdout())); // Compile the code - let codemap = CodeMap::new(); - let diagnostic_handler = diagnostic::Handler::with_emitter(true, box emitter); - let span_diagnostic_handler = - diagnostic::SpanHandler::new(diagnostic_handler, codemap); + let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter); let cstore = Rc::new(CStore::new(token::get_ident_interner())); let cstore_ = ::rustc_driver::cstore_to_cratestore(cstore.clone()); let sess = session::build_session_(sessopts, None, - span_diagnostic_handler, + diagnostic_handler, + codemap, cstore_); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index d511ce09a3616..ea5608b398427 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -21,7 +21,7 @@ use ast::{Expr, Item, Local, Decl}; use codemap::{Span, Spanned, spanned, dummy_spanned}; use codemap::BytePos; use config::CfgDiag; -use diagnostic::SpanHandler; +use errors::Handler; use feature_gate::{GatedCfg, GatedCfgAttr}; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use parse::token::{InternedString, intern_and_get_ident}; @@ -299,14 +299,14 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option { } /// Find the value of #[export_name=*] attribute and check its validity. -pub fn find_export_name_attr(diag: &SpanHandler, attrs: &[Attribute]) -> Option { +pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option { attrs.iter().fold(None, |ia,attr| { if attr.check_name("export_name") { if let s@Some(_) = attr.value_str() { s } else { diag.span_err(attr.span, "export_name attribute has invalid format"); - diag.handler.help("use #[export_name=\"*\"]"); + diag.help("use #[export_name=\"*\"]"); None } } else { @@ -324,7 +324,7 @@ pub enum InlineAttr { } /// Determine what `#[inline]` attribute is present in `attrs`, if any. -pub fn find_inline_attr(diagnostic: Option<&SpanHandler>, attrs: &[Attribute]) -> InlineAttr { +pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr { attrs.iter().fold(InlineAttr::None, |ia,attr| { match attr.node.value.node { MetaWord(ref n) if *n == "inline" => { @@ -426,7 +426,7 @@ impl StabilityLevel { pub fn is_stable(&self) -> bool { if let Stable {..} = *self { true } else { false }} } -fn find_stability_generic<'a, I>(diagnostic: &SpanHandler, +fn find_stability_generic<'a, I>(diagnostic: &Handler, attrs_iter: I, item_sp: Span) -> Option @@ -612,10 +612,10 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler, stab } -fn find_deprecation_generic<'a, I>(diagnostic: &SpanHandler, - attrs_iter: I, - item_sp: Span) - -> Option +fn find_deprecation_generic<'a, I>(diagnostic: &Handler, + attrs_iter: I, + item_sp: Span) + -> Option where I: Iterator { let mut depr: Option = None; @@ -672,18 +672,18 @@ fn find_deprecation_generic<'a, I>(diagnostic: &SpanHandler, } /// Find the first stability attribute. `None` if none exists. -pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute], +pub fn find_stability(diagnostic: &Handler, attrs: &[Attribute], item_sp: Span) -> Option { find_stability_generic(diagnostic, attrs.iter(), item_sp) } /// Find the deprecation attribute. `None` if none exists. -pub fn find_deprecation(diagnostic: &SpanHandler, attrs: &[Attribute], - item_sp: Span) -> Option { +pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute], + item_sp: Span) -> Option { find_deprecation_generic(diagnostic, attrs.iter(), item_sp) } -pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P]) { +pub fn require_unique_names(diagnostic: &Handler, metas: &[P]) { let mut set = HashSet::new(); for meta in metas { let name = meta.name(); @@ -702,7 +702,7 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P]) { /// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use /// the same discriminant size that the corresponding C enum would or C /// structure layout, and `packed` to remove padding. -pub fn find_repr_attrs(diagnostic: &SpanHandler, attr: &Attribute) -> Vec { +pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec { let mut acc = Vec::new(); match attr.node.value.node { ast::MetaList(ref s, ref items) if *s == "repr" => { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 1209c58fd5ed1..64b16538f05a1 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -9,7 +9,7 @@ // except according to those terms. use attr::AttrMetaMethods; -use diagnostic::SpanHandler; +use errors::Handler; use feature_gate::GatedCfgAttr; use fold::Folder; use {ast, fold, attr}; @@ -23,12 +23,12 @@ use util::small_vector::SmallVector; /// configuration. struct Context<'a, F> where F: FnMut(&[ast::Attribute]) -> bool { in_cfg: F, - diagnostic: &'a SpanHandler, + diagnostic: &'a Handler, } // Support conditional compilation by transforming the AST, stripping out // any items that do not belong in the current configuration -pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate, +pub fn strip_unconfigured_items(diagnostic: &Handler, krate: ast::Crate, feature_gated_cfgs: &mut Vec) -> ast::Crate { @@ -83,7 +83,7 @@ impl<'a, F> fold::Folder for Context<'a, F> where F: FnMut(&[ast::Attribute]) -> } } -pub fn strip_items<'a, F>(diagnostic: &'a SpanHandler, +pub fn strip_items<'a, F>(diagnostic: &'a Handler, krate: ast::Crate, in_cfg: F) -> ast::Crate where F: FnMut(&[ast::Attribute]) -> bool, { @@ -291,7 +291,7 @@ struct CfgAttrFolder<'a, T> { } // Process `#[cfg_attr]`. -fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate, +fn process_cfg_attr(diagnostic: &Handler, krate: ast::Crate, feature_gated_cfgs: &mut Vec) -> ast::Crate { let mut fld = CfgAttrFolder { diag: CfgDiagReal { @@ -463,17 +463,17 @@ impl<'v, 'a, 'b> visit::Visitor<'v> for StmtExprAttrFeatureVisitor<'a, 'b> { } pub trait CfgDiag { - fn emit_error(&mut self, f: F) where F: FnMut(&SpanHandler); + fn emit_error(&mut self, f: F) where F: FnMut(&Handler); fn flag_gated(&mut self, f: F) where F: FnMut(&mut Vec); } pub struct CfgDiagReal<'a, 'b> { - pub diag: &'a SpanHandler, + pub diag: &'a Handler, pub feature_gated_cfgs: &'b mut Vec, } impl<'a, 'b> CfgDiag for CfgDiagReal<'a, 'b> { - fn emit_error(&mut self, mut f: F) where F: FnMut(&SpanHandler) { + fn emit_error(&mut self, mut f: F) where F: FnMut(&Handler) { f(self.diag) } fn flag_gated(&mut self, mut f: F) where F: FnMut(&mut Vec) { @@ -486,7 +486,7 @@ struct CfgDiagSilent { } impl CfgDiag for CfgDiagSilent { - fn emit_error(&mut self, _: F) where F: FnMut(&SpanHandler) { + fn emit_error(&mut self, _: F) where F: FnMut(&Handler) { self.error = true; } fn flag_gated(&mut self, _: F) where F: FnMut(&mut Vec) {} diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs deleted file mode 100644 index b854a2f2a0a17..0000000000000 --- a/src/libsyntax/diagnostic.rs +++ /dev/null @@ -1,900 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub use self::Level::*; -pub use self::RenderSpan::*; -pub use self::ColorConfig::*; -use self::Destination::*; - -use codemap::{self, COMMAND_LINE_SP, COMMAND_LINE_EXPN, Pos, Span}; -use diagnostics; - -use std::cell::{RefCell, Cell}; -use std::{cmp, error, fmt}; -use std::io::prelude::*; -use std::io; -use term; - -/// maximum number of lines we will print for each error; arbitrary. -const MAX_LINES: usize = 6; - -#[derive(Clone)] -pub enum RenderSpan { - /// A FullSpan renders with both with an initial line for the - /// message, prefixed by file:linenum, followed by a summary of - /// the source code covered by the span. - FullSpan(Span), - - /// Similar to a FullSpan, but the cited position is the end of - /// the span, instead of the start. Used, at least, for telling - /// compiletest/runtest to look at the last line of the span - /// (since `end_highlight_lines` displays an arrow to the end - /// of the span). - EndSpan(Span), - - /// A suggestion renders with both with an initial line for the - /// message, prefixed by file:linenum, followed by a summary - /// of hypothetical source code, where the `String` is spliced - /// into the lines in place of the code covered by the span. - Suggestion(Span, String), - - /// A FileLine renders with just a line for the message prefixed - /// by file:linenum. - FileLine(Span), -} - -impl RenderSpan { - fn span(&self) -> Span { - match *self { - FullSpan(s) | - Suggestion(s, _) | - EndSpan(s) | - FileLine(s) => - s - } - } -} - -#[derive(Clone, Copy)] -pub enum ColorConfig { - Auto, - Always, - Never -} - -pub trait Emitter { - fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, Span)>, - msg: &str, code: Option<&str>, lvl: Level); - fn custom_emit(&mut self, cm: &codemap::CodeMap, - sp: RenderSpan, msg: &str, lvl: Level); -} - -/// Used as a return value to signify a fatal error occurred. (It is also -/// used as the argument to panic at the moment, but that will eventually -/// not be true.) -#[derive(Copy, Clone, Debug)] -#[must_use] -pub struct FatalError; - -impl fmt::Display for FatalError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "parser fatal error") - } -} - -impl error::Error for FatalError { - fn description(&self) -> &str { - "The parser has encountered a fatal error" - } -} - -/// Signifies that the compiler died with an explicit call to `.bug` -/// or `.span_bug` rather than a failed assertion, etc. -#[derive(Copy, Clone, Debug)] -pub struct ExplicitBug; - -impl fmt::Display for ExplicitBug { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "parser internal bug") - } -} - -impl error::Error for ExplicitBug { - fn description(&self) -> &str { - "The parser has encountered an internal bug" - } -} - -/// A span-handler is like a handler but also -/// accepts span information for source-location -/// reporting. -pub struct SpanHandler { - pub handler: Handler, - pub cm: codemap::CodeMap, -} - -impl SpanHandler { - pub fn new(handler: Handler, cm: codemap::CodeMap) -> SpanHandler { - SpanHandler { - handler: handler, - cm: cm, - } - } - pub fn span_fatal(&self, sp: Span, msg: &str) -> FatalError { - self.handler.emit(Some((&self.cm, sp)), msg, Fatal); - return FatalError; - } - pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> FatalError { - self.handler.emit_with_code(Some((&self.cm, sp)), msg, code, Fatal); - return FatalError; - } - pub fn span_err(&self, sp: Span, msg: &str) { - self.handler.emit(Some((&self.cm, sp)), msg, Error); - self.handler.bump_err_count(); - } - pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) { - self.handler.emit_with_code(Some((&self.cm, sp)), msg, code, Error); - self.handler.bump_err_count(); - } - pub fn span_warn(&self, sp: Span, msg: &str) { - self.handler.emit(Some((&self.cm, sp)), msg, Warning); - } - pub fn span_warn_with_code(&self, sp: Span, msg: &str, code: &str) { - self.handler.emit_with_code(Some((&self.cm, sp)), msg, code, Warning); - } - pub fn span_note(&self, sp: Span, msg: &str) { - self.handler.emit(Some((&self.cm, sp)), msg, Note); - } - pub fn span_end_note(&self, sp: Span, msg: &str) { - self.handler.custom_emit(&self.cm, EndSpan(sp), msg, Note); - } - pub fn span_help(&self, sp: Span, msg: &str) { - self.handler.emit(Some((&self.cm, sp)), msg, Help); - } - /// Prints out a message with a suggested edit of the code. - /// - /// See `diagnostic::RenderSpan::Suggestion` for more information. - pub fn span_suggestion(&self, sp: Span, msg: &str, suggestion: String) { - self.handler.custom_emit(&self.cm, Suggestion(sp, suggestion), msg, Help); - } - pub fn fileline_note(&self, sp: Span, msg: &str) { - self.handler.custom_emit(&self.cm, FileLine(sp), msg, Note); - } - pub fn fileline_help(&self, sp: Span, msg: &str) { - self.handler.custom_emit(&self.cm, FileLine(sp), msg, Help); - } - pub fn span_bug(&self, sp: Span, msg: &str) -> ! { - self.handler.emit(Some((&self.cm, sp)), msg, Bug); - panic!(ExplicitBug); - } - pub fn span_bug_no_panic(&self, sp: Span, msg: &str) { - self.handler.emit(Some((&self.cm, sp)), msg, Bug); - self.handler.bump_err_count(); - } - pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! { - self.span_bug(sp, &format!("unimplemented {}", msg)); - } - pub fn handler<'a>(&'a self) -> &'a Handler { - &self.handler - } -} - -/// A handler deals with errors; certain errors -/// (fatal, bug, unimpl) may cause immediate exit, -/// others log errors for later reporting. -pub struct Handler { - err_count: Cell, - emit: RefCell>, - pub can_emit_warnings: bool -} - -impl Handler { - pub fn new(color_config: ColorConfig, - registry: Option, - can_emit_warnings: bool) -> Handler { - let emitter = Box::new(EmitterWriter::stderr(color_config, registry)); - Handler::with_emitter(can_emit_warnings, emitter) - } - pub fn with_emitter(can_emit_warnings: bool, e: Box) -> Handler { - Handler { - err_count: Cell::new(0), - emit: RefCell::new(e), - can_emit_warnings: can_emit_warnings - } - } - pub fn fatal(&self, msg: &str) -> FatalError { - self.emit.borrow_mut().emit(None, msg, None, Fatal); - FatalError - } - pub fn err(&self, msg: &str) { - self.emit.borrow_mut().emit(None, msg, None, Error); - self.bump_err_count(); - } - pub fn bump_err_count(&self) { - self.err_count.set(self.err_count.get() + 1); - } - pub fn err_count(&self) -> usize { - self.err_count.get() - } - pub fn has_errors(&self) -> bool { - self.err_count.get() > 0 - } - pub fn abort_if_errors(&self) { - let s; - match self.err_count.get() { - 0 => return, - 1 => s = "aborting due to previous error".to_string(), - _ => { - s = format!("aborting due to {} previous errors", - self.err_count.get()); - } - } - - panic!(self.fatal(&s[..])); - } - pub fn warn(&self, msg: &str) { - self.emit.borrow_mut().emit(None, msg, None, Warning); - } - pub fn note(&self, msg: &str) { - self.emit.borrow_mut().emit(None, msg, None, Note); - } - pub fn help(&self, msg: &str) { - self.emit.borrow_mut().emit(None, msg, None, Help); - } - pub fn bug(&self, msg: &str) -> ! { - self.emit.borrow_mut().emit(None, msg, None, Bug); - panic!(ExplicitBug); - } - pub fn unimpl(&self, msg: &str) -> ! { - self.bug(&format!("unimplemented {}", msg)); - } - pub fn emit(&self, - cmsp: Option<(&codemap::CodeMap, Span)>, - msg: &str, - lvl: Level) { - if lvl == Warning && !self.can_emit_warnings { return } - self.emit.borrow_mut().emit(cmsp, msg, None, lvl); - } - pub fn emit_with_code(&self, - cmsp: Option<(&codemap::CodeMap, Span)>, - msg: &str, - code: &str, - lvl: Level) { - if lvl == Warning && !self.can_emit_warnings { return } - self.emit.borrow_mut().emit(cmsp, msg, Some(code), lvl); - } - pub fn custom_emit(&self, cm: &codemap::CodeMap, - sp: RenderSpan, msg: &str, lvl: Level) { - if lvl == Warning && !self.can_emit_warnings { return } - self.emit.borrow_mut().custom_emit(cm, sp, msg, lvl); - } -} - -#[derive(Copy, PartialEq, Clone, Debug)] -pub enum Level { - Bug, - Fatal, - Error, - Warning, - Note, - Help, -} - -impl fmt::Display for Level { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use std::fmt::Display; - - match *self { - Bug => "error: internal compiler error".fmt(f), - Fatal | Error => "error".fmt(f), - Warning => "warning".fmt(f), - Note => "note".fmt(f), - Help => "help".fmt(f), - } - } -} - -impl Level { - fn color(self) -> term::color::Color { - match self { - Bug | Fatal | Error => term::color::BRIGHT_RED, - Warning => term::color::BRIGHT_YELLOW, - Note => term::color::BRIGHT_GREEN, - Help => term::color::BRIGHT_CYAN, - } - } -} - -pub struct EmitterWriter { - dst: Destination, - registry: Option -} - -enum Destination { - Terminal(Box), - Raw(Box), -} - -/// Do not use this for messages that end in `\n` – use `println_maybe_styled` instead. See -/// `EmitterWriter::print_maybe_styled` for details. -macro_rules! print_maybe_styled { - ($writer: expr, $style: expr, $($arg: tt)*) => { - $writer.print_maybe_styled(format_args!($($arg)*), $style, false) - } -} - -macro_rules! println_maybe_styled { - ($writer: expr, $style: expr, $($arg: tt)*) => { - $writer.print_maybe_styled(format_args!($($arg)*), $style, true) - } -} - -impl EmitterWriter { - pub fn stderr(color_config: ColorConfig, - registry: Option) -> EmitterWriter { - let stderr = io::stderr(); - - let use_color = match color_config { - Always => true, - Never => false, - Auto => stderr_isatty(), - }; - - if use_color { - let dst = match term::stderr() { - Some(t) => Terminal(t), - None => Raw(Box::new(stderr)), - }; - EmitterWriter { dst: dst, registry: registry } - } else { - EmitterWriter { dst: Raw(Box::new(stderr)), registry: registry } - } - } - - pub fn new(dst: Box, - registry: Option) -> EmitterWriter { - EmitterWriter { dst: Raw(dst), registry: registry } - } - - fn print_maybe_styled(&mut self, - args: fmt::Arguments, - color: term::Attr, - print_newline_at_end: bool) -> io::Result<()> { - match self.dst { - Terminal(ref mut t) => { - try!(t.attr(color)); - // If `msg` ends in a newline, we need to reset the color before - // the newline. We're making the assumption that we end up writing - // to a `LineBufferedWriter`, which means that emitting the reset - // after the newline ends up buffering the reset until we print - // another line or exit. Buffering the reset is a problem if we're - // sharing the terminal with any other programs (e.g. other rustc - // instances via `make -jN`). - // - // Note that if `msg` contains any internal newlines, this will - // result in the `LineBufferedWriter` flushing twice instead of - // once, which still leaves the opportunity for interleaved output - // to be miscolored. We assume this is rare enough that we don't - // have to worry about it. - try!(t.write_fmt(args)); - try!(t.reset()); - if print_newline_at_end { - t.write_all(b"\n") - } else { - Ok(()) - } - } - Raw(ref mut w) => { - try!(w.write_fmt(args)); - if print_newline_at_end { - w.write_all(b"\n") - } else { - Ok(()) - } - } - } - } - - fn print_diagnostic(&mut self, topic: &str, lvl: Level, - msg: &str, code: Option<&str>) -> io::Result<()> { - if !topic.is_empty() { - try!(write!(&mut self.dst, "{} ", topic)); - } - - try!(print_maybe_styled!(self, term::Attr::ForegroundColor(lvl.color()), - "{}: ", lvl.to_string())); - try!(print_maybe_styled!(self, term::Attr::Bold, "{}", msg)); - - match code { - Some(code) => { - let style = term::Attr::ForegroundColor(term::color::BRIGHT_MAGENTA); - try!(print_maybe_styled!(self, style, " [{}]", code.clone())); - } - None => () - } - try!(write!(&mut self.dst, "\n")); - Ok(()) - } - - fn emit_(&mut self, cm: &codemap::CodeMap, rsp: RenderSpan, - msg: &str, code: Option<&str>, lvl: Level) -> io::Result<()> { - let sp = rsp.span(); - - // We cannot check equality directly with COMMAND_LINE_SP - // since PartialEq is manually implemented to ignore the ExpnId - let ss = if sp.expn_id == COMMAND_LINE_EXPN { - "".to_string() - } else if let EndSpan(_) = rsp { - let span_end = Span { lo: sp.hi, hi: sp.hi, expn_id: sp.expn_id}; - cm.span_to_string(span_end) - } else { - cm.span_to_string(sp) - }; - - try!(self.print_diagnostic(&ss[..], lvl, msg, code)); - - match rsp { - FullSpan(_) => { - try!(self.highlight_lines(cm, sp, lvl, cm.span_to_lines(sp))); - try!(self.print_macro_backtrace(cm, sp)); - } - EndSpan(_) => { - try!(self.end_highlight_lines(cm, sp, lvl, cm.span_to_lines(sp))); - try!(self.print_macro_backtrace(cm, sp)); - } - Suggestion(_, ref suggestion) => { - try!(self.highlight_suggestion(cm, sp, suggestion)); - try!(self.print_macro_backtrace(cm, sp)); - } - FileLine(..) => { - // no source text in this case! - } - } - - match code { - Some(code) => - match self.registry.as_ref().and_then(|registry| registry.find_description(code)) { - Some(_) => { - try!(self.print_diagnostic(&ss[..], Help, - &format!("run `rustc --explain {}` to see a \ - detailed explanation", code), None)); - } - None => () - }, - None => (), - } - Ok(()) - } - - fn highlight_suggestion(&mut self, - cm: &codemap::CodeMap, - sp: Span, - suggestion: &str) - -> io::Result<()> - { - let lines = cm.span_to_lines(sp).unwrap(); - assert!(!lines.lines.is_empty()); - - // To build up the result, we want to take the snippet from the first - // line that precedes the span, prepend that with the suggestion, and - // then append the snippet from the last line that trails the span. - let fm = &lines.file; - - let first_line = &lines.lines[0]; - let prefix = fm.get_line(first_line.line_index) - .map(|l| &l[..first_line.start_col.0]) - .unwrap_or(""); - - let last_line = lines.lines.last().unwrap(); - let suffix = fm.get_line(last_line.line_index) - .map(|l| &l[last_line.end_col.0..]) - .unwrap_or(""); - - let complete = format!("{}{}{}", prefix, suggestion, suffix); - - // print the suggestion without any line numbers, but leave - // space for them. This helps with lining up with previous - // snippets from the actual error being reported. - let fm = &*lines.file; - let mut lines = complete.lines(); - for (line, line_index) in lines.by_ref().take(MAX_LINES).zip(first_line.line_index..) { - let elided_line_num = format!("{}", line_index+1); - try!(write!(&mut self.dst, "{0}:{1:2$} {3}\n", - fm.name, "", elided_line_num.len(), line)); - } - - // if we elided some lines, add an ellipsis - if lines.next().is_some() { - let elided_line_num = format!("{}", first_line.line_index + MAX_LINES + 1); - try!(write!(&mut self.dst, "{0:1$} {0:2$} ...\n", - "", fm.name.len(), elided_line_num.len())); - } - - Ok(()) - } - - fn highlight_lines(&mut self, - cm: &codemap::CodeMap, - sp: Span, - lvl: Level, - lines: codemap::FileLinesResult) - -> io::Result<()> - { - let lines = match lines { - Ok(lines) => lines, - Err(_) => { - try!(write!(&mut self.dst, "(internal compiler error: unprintable span)\n")); - return Ok(()); - } - }; - - let fm = &*lines.file; - - let line_strings: Option> = - lines.lines.iter() - .map(|info| fm.get_line(info.line_index)) - .collect(); - - let line_strings = match line_strings { - None => { return Ok(()); } - Some(line_strings) => line_strings - }; - - // Display only the first MAX_LINES lines. - let all_lines = lines.lines.len(); - let display_lines = cmp::min(all_lines, MAX_LINES); - let display_line_infos = &lines.lines[..display_lines]; - let display_line_strings = &line_strings[..display_lines]; - - // Calculate the widest number to format evenly and fix #11715 - assert!(display_line_infos.len() > 0); - let mut max_line_num = display_line_infos[display_line_infos.len() - 1].line_index + 1; - let mut digits = 0; - while max_line_num > 0 { - max_line_num /= 10; - digits += 1; - } - - // Print the offending lines - for (line_info, line) in display_line_infos.iter().zip(display_line_strings) { - try!(write!(&mut self.dst, "{}:{:>width$} {}\n", - fm.name, - line_info.line_index + 1, - line, - width=digits)); - } - - // If we elided something, put an ellipsis. - if display_lines < all_lines { - let last_line_index = display_line_infos.last().unwrap().line_index; - let s = format!("{}:{} ", fm.name, last_line_index + 1); - try!(write!(&mut self.dst, "{0:1$}...\n", "", s.len())); - } - - // FIXME (#3260) - // If there's one line at fault we can easily point to the problem - if lines.lines.len() == 1 { - let lo = cm.lookup_char_pos(sp.lo); - let mut digits = 0; - let mut num = (lines.lines[0].line_index + 1) / 10; - - // how many digits must be indent past? - while num > 0 { num /= 10; digits += 1; } - - let mut s = String::new(); - // Skip is the number of characters we need to skip because they are - // part of the 'filename:line ' part of the previous line. - let skip = fm.name.chars().count() + digits + 3; - for _ in 0..skip { - s.push(' '); - } - if let Some(orig) = fm.get_line(lines.lines[0].line_index) { - let mut col = skip; - let mut lastc = ' '; - let mut iter = orig.chars().enumerate(); - for (pos, ch) in iter.by_ref() { - lastc = ch; - if pos >= lo.col.to_usize() { break; } - // Whenever a tab occurs on the previous line, we insert one on - // the error-point-squiggly-line as well (instead of a space). - // That way the squiggly line will usually appear in the correct - // position. - match ch { - '\t' => { - col += 8 - col%8; - s.push('\t'); - }, - _ => { - col += 1; - s.push(' '); - }, - } - } - - try!(write!(&mut self.dst, "{}", s)); - let mut s = String::from("^"); - let count = match lastc { - // Most terminals have a tab stop every eight columns by default - '\t' => 8 - col%8, - _ => 1, - }; - col += count; - s.extend(::std::iter::repeat('~').take(count)); - - let hi = cm.lookup_char_pos(sp.hi); - if hi.col != lo.col { - for (pos, ch) in iter { - if pos >= hi.col.to_usize() { break; } - let count = match ch { - '\t' => 8 - col%8, - _ => 1, - }; - col += count; - s.extend(::std::iter::repeat('~').take(count)); - } - } - - if s.len() > 1 { - // One extra squiggly is replaced by a "^" - s.pop(); - } - - try!(println_maybe_styled!(self, term::Attr::ForegroundColor(lvl.color()), - "{}", s)); - } - } - Ok(()) - } - - /// Here are the differences between this and the normal `highlight_lines`: - /// `end_highlight_lines` will always put arrow on the last byte of the - /// span (instead of the first byte). Also, when the span is too long (more - /// than 6 lines), `end_highlight_lines` will print the first line, then - /// dot dot dot, then last line, whereas `highlight_lines` prints the first - /// six lines. - #[allow(deprecated)] - fn end_highlight_lines(&mut self, - cm: &codemap::CodeMap, - sp: Span, - lvl: Level, - lines: codemap::FileLinesResult) - -> io::Result<()> { - let lines = match lines { - Ok(lines) => lines, - Err(_) => { - try!(write!(&mut self.dst, "(internal compiler error: unprintable span)\n")); - return Ok(()); - } - }; - - let fm = &*lines.file; - - let lines = &lines.lines[..]; - if lines.len() > MAX_LINES { - if let Some(line) = fm.get_line(lines[0].line_index) { - try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, - lines[0].line_index + 1, line)); - } - try!(write!(&mut self.dst, "...\n")); - let last_line_index = lines[lines.len() - 1].line_index; - if let Some(last_line) = fm.get_line(last_line_index) { - try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, - last_line_index + 1, last_line)); - } - } else { - for line_info in lines { - if let Some(line) = fm.get_line(line_info.line_index) { - try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, - line_info.line_index + 1, line)); - } - } - } - let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1].line_index + 1); - let hi = cm.lookup_char_pos(sp.hi); - let skip = last_line_start.chars().count(); - let mut s = String::new(); - for _ in 0..skip { - s.push(' '); - } - if let Some(orig) = fm.get_line(lines[0].line_index) { - let iter = orig.chars().enumerate(); - for (pos, ch) in iter { - // Span seems to use half-opened interval, so subtract 1 - if pos >= hi.col.to_usize() - 1 { break; } - // Whenever a tab occurs on the previous line, we insert one on - // the error-point-squiggly-line as well (instead of a space). - // That way the squiggly line will usually appear in the correct - // position. - match ch { - '\t' => s.push('\t'), - _ => s.push(' '), - } - } - } - s.push('^'); - println_maybe_styled!(self, term::Attr::ForegroundColor(lvl.color()), - "{}", s) - } - - fn print_macro_backtrace(&mut self, - cm: &codemap::CodeMap, - sp: Span) - -> io::Result<()> { - let mut last_span = codemap::DUMMY_SP; - let mut sp_opt = Some(sp); - - while let Some(sp) = sp_opt { - sp_opt = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { - match expn_info { - Some(ei) => { - let (pre, post) = match ei.callee.format { - codemap::MacroAttribute(..) => ("#[", "]"), - codemap::MacroBang(..) => ("", "!"), - }; - // Don't print recursive invocations - if ei.call_site != last_span { - last_span = ei.call_site; - - let mut diag_string = format!("in this expansion of {}{}{}", - pre, - ei.callee.name(), - post); - - if let Some(def_site_span) = ei.callee.span { - diag_string.push_str(&format!(" (defined in {})", - cm.span_to_filename(def_site_span))); - } - - try!(self.print_diagnostic(&cm.span_to_string(ei.call_site), - Note, - &diag_string, - None)); - } - Ok(Some(ei.call_site)) - } - None => Ok(None) - } - })); - } - - Ok(()) - } -} - -#[cfg(unix)] -fn stderr_isatty() -> bool { - use libc; - unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } -} -#[cfg(windows)] -fn stderr_isatty() -> bool { - type DWORD = u32; - type BOOL = i32; - type HANDLE = *mut u8; - const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; - extern "system" { - fn GetStdHandle(which: DWORD) -> HANDLE; - fn GetConsoleMode(hConsoleHandle: HANDLE, - lpMode: *mut DWORD) -> BOOL; - } - unsafe { - let handle = GetStdHandle(STD_ERROR_HANDLE); - let mut out = 0; - GetConsoleMode(handle, &mut out) != 0 - } -} - -impl Write for Destination { - fn write(&mut self, bytes: &[u8]) -> io::Result { - match *self { - Terminal(ref mut t) => t.write(bytes), - Raw(ref mut w) => w.write(bytes), - } - } - fn flush(&mut self) -> io::Result<()> { - match *self { - Terminal(ref mut t) => t.flush(), - Raw(ref mut w) => w.flush(), - } - } -} - -impl Emitter for EmitterWriter { - fn emit(&mut self, - cmsp: Option<(&codemap::CodeMap, Span)>, - msg: &str, code: Option<&str>, lvl: Level) { - let error = match cmsp { - Some((cm, COMMAND_LINE_SP)) => self.emit_(cm, - FileLine(COMMAND_LINE_SP), - msg, code, lvl), - Some((cm, sp)) => self.emit_(cm, FullSpan(sp), msg, code, lvl), - None => self.print_diagnostic("", lvl, msg, code), - }; - - match error { - Ok(()) => {} - Err(e) => panic!("failed to print diagnostics: {:?}", e), - } - } - - fn custom_emit(&mut self, cm: &codemap::CodeMap, - sp: RenderSpan, msg: &str, lvl: Level) { - match self.emit_(cm, sp, msg, None, lvl) { - Ok(()) => {} - Err(e) => panic!("failed to print diagnostics: {:?}", e), - } - } -} - -pub fn expect(diag: &SpanHandler, opt: Option, msg: M) -> T where - M: FnOnce() -> String, -{ - match opt { - Some(t) => t, - None => diag.handler().bug(&msg()), - } -} - -#[cfg(test)] -mod test { - use super::{EmitterWriter, Level}; - use codemap::{mk_sp, CodeMap}; - use std::sync::{Arc, Mutex}; - use std::io::{self, Write}; - use std::str::from_utf8; - - // Diagnostic doesn't align properly in span where line number increases by one digit - #[test] - fn test_hilight_suggestion_issue_11715() { - struct Sink(Arc>>); - impl Write for Sink { - fn write(&mut self, data: &[u8]) -> io::Result { - Write::write(&mut *self.0.lock().unwrap(), data) - } - fn flush(&mut self) -> io::Result<()> { Ok(()) } - } - let data = Arc::new(Mutex::new(Vec::new())); - let mut ew = EmitterWriter::new(Box::new(Sink(data.clone())), None); - let cm = CodeMap::new(); - let content = "abcdefg - koksi - line3 - line4 - cinq - line6 - line7 - line8 - line9 - line10 - e-lä-vän - tolv - dreizehn - "; - let file = cm.new_filemap_and_lines("dummy.txt", content); - let start = file.lines.borrow()[7]; - let end = file.lines.borrow()[11]; - let sp = mk_sp(start, end); - let lvl = Level::Error; - println!("span_to_lines"); - let lines = cm.span_to_lines(sp); - println!("highlight_lines"); - ew.highlight_lines(&cm, sp, lvl, lines).unwrap(); - println!("done"); - let vec = data.lock().unwrap().clone(); - let vec: &[u8] = &vec; - let str = from_utf8(vec).unwrap(); - println!("{}", str); - assert_eq!(str, "dummy.txt: 8 line8\n\ - dummy.txt: 9 line9\n\ - dummy.txt:10 line10\n\ - dummy.txt:11 e-lä-vän\n\ - dummy.txt:12 tolv\n"); - } -} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 9d62e407cb913..f198460137d5f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -720,7 +720,7 @@ impl<'a> ExtCtxt<'a> { self.parse_sess.span_diagnostic.fileline_help(sp, msg); } pub fn bug(&self, msg: &str) -> ! { - self.parse_sess.span_diagnostic.handler().bug(msg); + self.parse_sess.span_diagnostic.bug(msg); } pub fn trace_macros(&self) -> bool { self.ecfg.trace_mac diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b1afe2bb69c02..4f9888b746e86 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1301,7 +1301,7 @@ pub fn expand_crate(mut cx: ExtCtxt, let mut ret = expander.fold_crate(c); ret.exported_macros = expander.cx.exported_macros.clone(); - cx.parse_sess.span_diagnostic.handler().abort_if_errors(); + cx.parse_sess.span_diagnostic.abort_if_errors(); ret }; return (ret, cx.syntax_env.names); diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index ba781ae3cc212..29360f14838cc 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -12,7 +12,7 @@ use self::LockstepIterSize::*; use ast; use ast::{TokenTree, Ident, Name}; use codemap::{Span, DUMMY_SP}; -use diagnostic::SpanHandler; +use errors::Handler; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use parse::token::{Eof, DocComment, Interpolated, MatchNt, SubstNt}; use parse::token::{Token, NtIdent, SpecialMacroVar}; @@ -34,7 +34,7 @@ struct TtFrame { #[derive(Clone)] pub struct TtReader<'a> { - pub sp_diag: &'a SpanHandler, + pub sp_diag: &'a Handler, /// the unzipped tree: stack: Vec, /* for MBE-style macro transcription */ @@ -55,7 +55,7 @@ pub struct TtReader<'a> { /// This can do Macro-By-Example transcription. On the other hand, if /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can /// (and should) be None. -pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, +pub fn new_tt_reader<'a>(sp_diag: &'a Handler, interp: Option>>, imported_from: Option, src: Vec) @@ -69,7 +69,7 @@ pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, /// This can do Macro-By-Example transcription. On the other hand, if /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can /// (and should) be None. -pub fn new_tt_reader_with_doc_flag<'a>(sp_diag: &'a SpanHandler, +pub fn new_tt_reader_with_doc_flag<'a>(sp_diag: &'a Handler, interp: Option>>, imported_from: Option, src: Vec, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f186aff6d363a..89f318d09451b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -32,7 +32,7 @@ use ast; use attr; use attr::AttrMetaMethods; use codemap::{CodeMap, Span}; -use diagnostic::SpanHandler; +use errors::Handler; use visit; use visit::{FnKind, Visitor}; use parse::token::InternedString; @@ -446,7 +446,7 @@ impl PartialOrd for GatedCfgAttr { } impl GatedCfgAttr { - pub fn check_and_emit(&self, diagnostic: &SpanHandler, features: &Features) { + pub fn check_and_emit(&self, diagnostic: &Handler, features: &Features) { match *self { GatedCfgAttr::GatedCfg(ref cfg) => { cfg.check_and_emit(diagnostic, features); @@ -476,7 +476,7 @@ impl GatedCfg { } }) } - fn check_and_emit(&self, diagnostic: &SpanHandler, features: &Features) { + fn check_and_emit(&self, diagnostic: &Handler, features: &Features) { let (cfg, feature, has_feature) = GATED_CFGS[self.index]; if !has_feature(features) { let explain = format!("`cfg({})` is experimental and subject to change", cfg); @@ -595,21 +595,21 @@ const EXPLAIN_PUSHPOP_UNSAFE: &'static str = const EXPLAIN_STMT_ATTR_SYNTAX: &'static str = "attributes on non-item statements and expressions are experimental."; -pub fn check_for_box_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span) { +pub fn check_for_box_syntax(f: Option<&Features>, diag: &Handler, span: Span) { if let Some(&Features { allow_box: true, .. }) = f { return; } emit_feature_err(diag, "box_syntax", span, GateIssue::Language, EXPLAIN_BOX_SYNTAX); } -pub fn check_for_placement_in(f: Option<&Features>, diag: &SpanHandler, span: Span) { +pub fn check_for_placement_in(f: Option<&Features>, diag: &Handler, span: Span) { if let Some(&Features { allow_placement_in: true, .. }) = f { return; } emit_feature_err(diag, "placement_in_syntax", span, GateIssue::Language, EXPLAIN_PLACEMENT_IN); } -pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span) { +pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &Handler, span: Span) { if let Some(&Features { allow_pushpop_unsafe: true, .. }) = f { return; } @@ -618,7 +618,7 @@ pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &SpanHandler, span: struct Context<'a> { features: Vec<&'static str>, - span_handler: &'a SpanHandler, + span_handler: &'a Handler, cm: &'a CodeMap, plugin_attributes: &'a [(String, AttributeType)], } @@ -704,7 +704,7 @@ pub enum GateIssue { Library(Option) } -pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, issue: GateIssue, +pub fn emit_feature_err(diag: &Handler, feature: &str, span: Span, issue: GateIssue, explain: &str) { let issue = match issue { GateIssue::Language => find_lang_feature_issue(feature), @@ -1064,7 +1064,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } -fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, +fn check_crate_inner(cm: &CodeMap, span_handler: &Handler, krate: &ast::Crate, plugin_attributes: &[(String, AttributeType)], check: F) @@ -1161,13 +1161,13 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, } } -pub fn check_crate_macros(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate) +pub fn check_crate_macros(cm: &CodeMap, span_handler: &Handler, krate: &ast::Crate) -> Features { check_crate_inner(cm, span_handler, krate, &[] as &'static [_], |ctx, krate| visit::walk_crate(&mut MacroVisitor { context: ctx }, krate)) } -pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate, +pub fn check_crate(cm: &CodeMap, span_handler: &Handler, krate: &ast::Crate, plugin_attributes: &[(String, AttributeType)], unstable: UnstableFeatures) -> Features { @@ -1192,7 +1192,7 @@ pub enum UnstableFeatures { Cheat } -fn maybe_stage_features(span_handler: &SpanHandler, krate: &ast::Crate, +fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) { let allow_features = match unstable { UnstableFeatures::Allow => true, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 73d7025b4f155..47340d312242b 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -52,7 +52,7 @@ extern crate serialize as rustc_serialize; // used by deriving macro_rules! panictry { ($e:expr) => ({ use std::result::Result::{Ok, Err}; - use diagnostic::FatalError; + use errors::FatalError; match $e { Ok(e) => e, Err(FatalError) => panic!(FatalError) @@ -78,6 +78,8 @@ pub mod diagnostics { pub mod metadata; } +pub mod errors; + pub mod syntax { pub use ext; pub use parse; @@ -90,7 +92,6 @@ pub mod ast_util; pub mod attr; pub mod codemap; pub mod config; -pub mod diagnostic; pub mod entry; pub mod feature_gate; pub mod fold; diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index e5e2c3a986db3..d2156d7cb68d2 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -12,7 +12,7 @@ pub use self::CommentStyle::*; use ast; use codemap::{BytePos, CharPos, CodeMap, Pos}; -use diagnostic; +use errors; use parse::lexer::is_block_doc_comment; use parse::lexer::{StringReader, TokenAndSpan}; use parse::lexer::{is_whitespace, Reader}; @@ -334,7 +334,7 @@ pub struct Literal { // it appears this function is called only from pprust... that's // probably not a good thing. -pub fn gather_comments_and_literals(span_diagnostic: &diagnostic::SpanHandler, +pub fn gather_comments_and_literals(span_diagnostic: &errors::Handler, path: String, srdr: &mut Read) -> (Vec, Vec) { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index cb2181a083177..570e0882a8513 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -11,8 +11,7 @@ use ast; use codemap::{BytePos, CharPos, CodeMap, Pos, Span}; use codemap; -use diagnostic::FatalError; -use diagnostic::SpanHandler; +use errors::{FatalError, Handler}; use ext::tt::transcribe::tt_next_token; use parse::token::str_to_ident; use parse::token; @@ -58,7 +57,7 @@ pub struct TokenAndSpan { } pub struct StringReader<'a> { - pub span_diagnostic: &'a SpanHandler, + pub span_diagnostic: &'a Handler, /// The absolute offset within the codemap of the next character to read pub pos: BytePos, /// The absolute offset within the codemap of the last character read(curr) @@ -128,10 +127,10 @@ impl<'a> Reader for TtReader<'a> { impl<'a> StringReader<'a> { /// For comments.rs, which hackily pokes into pos and curr - pub fn new_raw<'b>(span_diagnostic: &'b SpanHandler, + pub fn new_raw<'b>(span_diagnostic: &'b Handler, filemap: Rc) -> StringReader<'b> { if filemap.src.is_none() { - span_diagnostic.handler.bug(&format!("Cannot lex filemap without source: {}", + span_diagnostic.bug(&format!("Cannot lex filemap without source: {}", filemap.name)[..]); } @@ -153,7 +152,7 @@ impl<'a> StringReader<'a> { sr } - pub fn new<'b>(span_diagnostic: &'b SpanHandler, + pub fn new<'b>(span_diagnostic: &'b Handler, filemap: Rc) -> StringReader<'b> { let mut sr = StringReader::new_raw(span_diagnostic, filemap); sr.advance_token(); @@ -1428,15 +1427,15 @@ mod tests { use parse::token::{str_to_ident}; use std::io; - fn mk_sh() -> diagnostic::SpanHandler { + fn mk_sh() -> diagnostic::Handler { // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let emitter = diagnostic::EmitterWriter::new(Box::new(io::sink()), None); let handler = diagnostic::Handler::with_emitter(true, Box::new(emitter)); - diagnostic::SpanHandler::new(handler, CodeMap::new()) + diagnostic::Handler::new(handler, CodeMap::new()) } // open a string reader for the given string - fn setup<'a>(span_handler: &'a diagnostic::SpanHandler, + fn setup<'a>(span_handler: &'a diagnostic::Handler, teststr: String) -> StringReader<'a> { let fm = span_handler.cm.new_filemap("zebra.rs".to_string(), teststr); StringReader::new(span_handler, fm) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index e9c8173a4d980..f74e9023ed18b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -12,7 +12,7 @@ use ast; use codemap::{self, Span, CodeMap, FileMap}; -use diagnostic::{SpanHandler, Handler, Auto, FatalError}; +use errors::{Handler, ColorConfig, FatalError}; use parse::parser::Parser; use parse::token::InternedString; use ptr::P; @@ -40,26 +40,29 @@ pub mod obsolete; /// Info about a parsing session. pub struct ParseSess { - pub span_diagnostic: SpanHandler, // better be the same as the one in the reader! + pub span_diagnostic: Handler, // better be the same as the one in the reader! /// Used to determine and report recursive mod inclusions included_mod_stack: RefCell>, + code_map: Rc, } impl ParseSess { pub fn new() -> ParseSess { - let handler = SpanHandler::new(Handler::new(Auto, None, true), CodeMap::new()); - ParseSess::with_span_handler(handler) + let cm = Rc::new(CodeMap::new()); + let handler = Handler::new(ColorConfig::Auto, None, true, cm.clone()); + ParseSess::with_span_handler(handler, cm) } - pub fn with_span_handler(sh: SpanHandler) -> ParseSess { + pub fn with_span_handler(handler: Handler, code_map: Rc) -> ParseSess { ParseSess { - span_diagnostic: sh, - included_mod_stack: RefCell::new(vec![]) + span_diagnostic: handler, + included_mod_stack: RefCell::new(vec![]), + code_map: code_map } } pub fn codemap(&self) -> &CodeMap { - &self.span_diagnostic.cm + &self.code_map } } @@ -235,7 +238,7 @@ fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option) let msg = format!("couldn't read {:?}: {}", path.display(), e); match spanopt { Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)), - None => panic!(sess.span_diagnostic.handler().fatal(&msg)) + None => panic!(sess.span_diagnostic.fatal(&msg)) } } } @@ -438,7 +441,7 @@ fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { } fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, - sd: &SpanHandler, sp: Span) -> ast::Lit_ { + sd: &Handler, sp: Span) -> ast::Lit_ { debug!("filtered_float_lit: {}, {:?}", data, suffix); match suffix.as_ref().map(|s| &**s) { Some("f32") => ast::LitFloat(data, ast::TyF32), @@ -459,7 +462,7 @@ fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, } } pub fn float_lit(s: &str, suffix: Option, - sd: &SpanHandler, sp: Span) -> ast::Lit_ { + sd: &Handler, sp: Span) -> ast::Lit_ { debug!("float_lit: {:?}, {:?}", s, suffix); // FIXME #2252: bounds checking float literals is deferred until trans let s = s.chars().filter(|&c| c != '_').collect::(); @@ -561,7 +564,7 @@ pub fn byte_str_lit(lit: &str) -> Rc> { pub fn integer_lit(s: &str, suffix: Option, - sd: &SpanHandler, + sd: &Handler, sp: Span) -> ast::Lit_ { // s can only be ascii, byte indexing is fine diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index bc355f70fb31e..5dba1e189ab15 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -66,10 +66,9 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { } if !self.obsolete_set.contains(&kind) && - (error || self.sess.span_diagnostic.handler().can_emit_warnings) { + (error || self.sess.span_diagnostic.can_emit_warnings) { self.sess .span_diagnostic - .handler() .note(&format!("{}", desc)); self.obsolete_set.insert(kind); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 9398f1a573335..04b0c0fa2735b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -60,7 +60,7 @@ use attr::{ThinAttributes, ThinAttributesExt, AttributesExt}; use ast; use ast_util::{self, ident_to_path}; use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap}; -use diagnostic; +use errors::{self, FatalError}; use ext::tt::macro_parser; use parse; use parse::classify; @@ -75,7 +75,6 @@ use print::pprust; use ptr::P; use owned_slice::OwnedSlice; use parse::PResult; -use diagnostic::FatalError; use std::collections::HashSet; use std::io::prelude::*; @@ -983,16 +982,16 @@ impl<'a> Parser<'a> { } f(&self.buffer[((self.buffer_start + dist - 1) & 3) as usize].tok) } - pub fn fatal(&self, m: &str) -> diagnostic::FatalError { + pub fn fatal(&self, m: &str) -> errors::FatalError { self.sess.span_diagnostic.span_fatal(self.span, m) } - pub fn span_fatal(&self, sp: Span, m: &str) -> diagnostic::FatalError { + pub fn span_fatal(&self, sp: Span, m: &str) -> errors::FatalError { self.sess.span_diagnostic.span_fatal(sp, m) } - pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> diagnostic::FatalError { + pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> errors::FatalError { self.span_err(sp, m); self.fileline_help(sp, help); - diagnostic::FatalError + errors::FatalError } pub fn span_note(&self, sp: Span, m: &str) { self.sess.span_diagnostic.span_note(sp, m) @@ -1022,7 +1021,7 @@ impl<'a> Parser<'a> { self.sess.span_diagnostic.span_bug(sp, m) } pub fn abort_if_errors(&self) { - self.sess.span_diagnostic.handler().abort_if_errors(); + self.sess.span_diagnostic.abort_if_errors(); } pub fn id_to_interned_str(&mut self, id: Ident) -> InternedString { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4e2289cb7f401..08448f25187c7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -20,7 +20,7 @@ use attr; use owned_slice::OwnedSlice; use attr::{AttrMetaMethods, AttributeMethods}; use codemap::{self, CodeMap, BytePos}; -use diagnostic; +use errors; use parse::token::{self, BinOpToken, Token, InternedString}; use parse::lexer::comments; use parse; @@ -99,7 +99,7 @@ pub const DEFAULT_COLUMNS: usize = 78; /// it can scan the input text for comments and literals to /// copy forward. pub fn print_crate<'a>(cm: &'a CodeMap, - span_diagnostic: &diagnostic::SpanHandler, + span_diagnostic: &errors::Handler, krate: &ast::Crate, filename: String, input: &mut Read, @@ -139,7 +139,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, impl<'a> State<'a> { pub fn new_from_input(cm: &'a CodeMap, - span_diagnostic: &diagnostic::SpanHandler, + span_diagnostic: &errors::Handler, filename: String, input: &mut Read, out: Box, diff --git a/src/libsyntax/show_span.rs b/src/libsyntax/show_span.rs index 6492cd4b095a7..014c7b2a68f4f 100644 --- a/src/libsyntax/show_span.rs +++ b/src/libsyntax/show_span.rs @@ -16,7 +16,7 @@ use std::str::FromStr; use ast; -use diagnostic; +use errors; use visit; use visit::Visitor; @@ -40,7 +40,7 @@ impl FromStr for Mode { } struct ShowSpanVisitor<'a> { - span_diagnostic: &'a diagnostic::SpanHandler, + span_diagnostic: &'a errors::Handler, mode: Mode, } @@ -71,7 +71,7 @@ impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> { } } -pub fn run(span_diagnostic: &diagnostic::SpanHandler, +pub fn run(span_diagnostic: &errors::Handler, mode: &str, krate: &ast::Crate) { let mode = match mode.parse().ok() { diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 63fbe284a09fd..9e1d80b3f0de4 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -23,7 +23,7 @@ use attr::AttrMetaMethods; use attr; use codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute}; use codemap; -use diagnostic; +use errors; use config; use entry::{self, EntryPointType}; use ext::base::ExtCtxt; @@ -55,7 +55,7 @@ struct Test { struct TestCtxt<'a> { sess: &'a ParseSess, - span_diagnostic: &'a diagnostic::SpanHandler, + span_diagnostic: &'a errors::Handler, path: Vec, ext_cx: ExtCtxt<'a>, testfns: Vec, @@ -72,7 +72,7 @@ struct TestCtxt<'a> { pub fn modify_for_testing(sess: &ParseSess, cfg: &ast::CrateConfig, krate: ast::Crate, - span_diagnostic: &diagnostic::SpanHandler) -> ast::Crate { + span_diagnostic: &errors::Handler) -> ast::Crate { // We generate the test harness when building in the 'test' // configuration, either with the '--test' or '--cfg test' // command line options. @@ -275,7 +275,7 @@ fn generate_test_harness(sess: &ParseSess, reexport_test_harness_main: Option, krate: ast::Crate, cfg: &ast::CrateConfig, - sd: &diagnostic::SpanHandler) -> ast::Crate { + sd: &errors::Handler) -> ast::Crate { // Remove the entry points let mut cleaner = EntryPointCleaner { depth: 0 }; let krate = cleaner.fold_crate(krate); @@ -315,7 +315,7 @@ fn generate_test_harness(sess: &ParseSess, return res; } -fn strip_test_functions(diagnostic: &diagnostic::SpanHandler, krate: ast::Crate) +fn strip_test_functions(diagnostic: &errors::Handler, krate: ast::Crate) -> ast::Crate { // When not compiling with --test we should not compile the // #[test] functions @@ -688,7 +688,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { Some(id) => vec![id], None => { let diag = cx.span_diagnostic; - diag.handler.bug("expected to find top-level re-export name, but found None"); + diag.bug("expected to find top-level re-export name, but found None"); } }; visible_path.extend(path); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 5977144dae708..b76384ffb4ada 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -203,7 +203,7 @@ use syntax::ext::base::{ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; use syntax::codemap::{self, DUMMY_SP}; use syntax::codemap::Span; -use syntax::diagnostic::SpanHandler; +use syntax::errors::Handler; use syntax::util::move_map::MoveMap; use syntax::owned_slice::OwnedSlice; use syntax::parse::token::{intern, InternedString}; @@ -742,7 +742,7 @@ impl<'a> TraitDef<'a> { } } -fn find_repr_type_name(diagnostic: &SpanHandler, +fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &'static str { let mut repr_type_name = "i32"; for a in type_attrs { From a47881182237201f207a4b89166a6be6903a8228 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 Dec 2015 18:15:39 +1300 Subject: [PATCH 04/13] Move a bunch of stuff from Session to syntax::errors The intention here is that Session is a very thin wrapper over the error handling infra. --- src/librustc/session/mod.rs | 71 ++++-------------------- src/librustc_trans/back/write.rs | 2 +- src/librustc_trans/trans/callee.rs | 6 +- src/librustc_trans/trans/monomorphize.rs | 6 +- src/libsyntax/parse/mod.rs | 2 +- 5 files changed, 19 insertions(+), 68 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 76d765c9626a3..7b96db4bf0a3a 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -64,14 +64,10 @@ pub struct Session { pub crate_metadata: RefCell>, pub features: RefCell, - pub delayed_span_bug: RefCell>, - /// The maximum recursion limit for potentially infinitely recursive /// operations such as auto-dereference and monomorphization. pub recursion_limit: Cell, - pub can_print_warnings: bool, - /// The metadata::creader module may inject an allocator dependency if it /// didn't already find one, and this tracks what was injected. pub injected_allocator: Cell>, @@ -85,21 +81,12 @@ pub struct Session { impl Session { pub fn span_fatal(&self, sp: Span, msg: &str) -> ! { - if self.opts.treat_err_as_bug { - self.span_bug(sp, msg); - } panic!(self.diagnostic().span_fatal(sp, msg)) } pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! { - if self.opts.treat_err_as_bug { - self.span_bug(sp, msg); - } panic!(self.diagnostic().span_fatal_with_code(sp, msg, code)) } pub fn fatal(&self, msg: &str) -> ! { - if self.opts.treat_err_as_bug { - self.bug(msg); - } panic!(self.diagnostic().fatal(msg)) } pub fn span_err_or_warn(&self, is_warning: bool, sp: Span, msg: &str) { @@ -110,9 +97,6 @@ impl Session { } } pub fn span_err(&self, sp: Span, msg: &str) { - if self.opts.treat_err_as_bug { - self.span_bug(sp, msg); - } match split_msg_into_multilines(msg) { Some(msg) => self.diagnostic().span_err(sp, &msg[..]), None => self.diagnostic().span_err(sp, msg) @@ -126,18 +110,12 @@ impl Session { See RFC 1214 for details.")); } pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) { - if self.opts.treat_err_as_bug { - self.span_bug(sp, msg); - } match split_msg_into_multilines(msg) { Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code), None => self.diagnostic().span_err_with_code(sp, msg, code) } } pub fn err(&self, msg: &str) { - if self.opts.treat_err_as_bug { - self.bug(msg); - } self.diagnostic().err(msg) } pub fn err_count(&self) -> usize { @@ -148,14 +126,6 @@ impl Session { } pub fn abort_if_errors(&self) { self.diagnostic().abort_if_errors(); - - let delayed_bug = self.delayed_span_bug.borrow(); - match *delayed_bug { - Some((span, ref errmsg)) => { - self.diagnostic().span_bug(span, errmsg); - }, - _ => {} - } } pub fn abort_if_new_errors(&self, mut f: F) where F: FnMut() @@ -167,19 +137,13 @@ impl Session { } } pub fn span_warn(&self, sp: Span, msg: &str) { - if self.can_print_warnings { - self.diagnostic().span_warn(sp, msg) - } + self.diagnostic().span_warn(sp, msg) } pub fn span_warn_with_code(&self, sp: Span, msg: &str, code: &str) { - if self.can_print_warnings { - self.diagnostic().span_warn_with_code(sp, msg, code) - } + self.diagnostic().span_warn_with_code(sp, msg, code) } pub fn warn(&self, msg: &str) { - if self.can_print_warnings { - self.diagnostic().warn(msg) - } + self.diagnostic().warn(msg) } pub fn opt_span_warn(&self, opt_sp: Option, msg: &str) { match opt_sp { @@ -223,8 +187,7 @@ impl Session { } /// Delay a span_bug() call until abort_if_errors() pub fn delay_span_bug(&self, sp: Span, msg: &str) { - let mut delayed = self.delayed_span_bug.borrow_mut(); - *delayed = Some((sp, msg.to_string())); + self.diagnostic().delay_span_bug(sp, msg) } pub fn span_bug(&self, sp: Span, msg: &str) -> ! { self.diagnostic().span_bug(sp, msg) @@ -270,8 +233,7 @@ impl Session { // This exists to help with refactoring to eliminate impossible // cases later on pub fn impossible_case(&self, sp: Span, msg: &str) -> ! { - self.span_bug(sp, - &format!("impossible case reached: {}", msg)); + self.span_bug(sp, &format!("impossible case reached: {}", msg)); } pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose } pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes } @@ -414,10 +376,15 @@ pub fn build_session(sopts: config::Options, .map(|&(_, ref level)| *level != lint::Allow) .last() .unwrap_or(true); + let treat_err_as_bug = sopts.treat_err_as_bug; let codemap = Rc::new(codemap::CodeMap::new()); let diagnostic_handler = - errors::Handler::new(sopts.color, Some(registry), can_print_warnings, codemap.clone()); + errors::Handler::new(sopts.color, + Some(registry), + can_print_warnings, + treat_err_as_bug, + codemap.clone()); build_session_(sopts, local_crate_source_file, diagnostic_handler, codemap, cstore) } @@ -450,13 +417,6 @@ pub fn build_session_(sopts: config::Options, } ); - let can_print_warnings = sopts.lint_opts - .iter() - .filter(|&&(ref key, _)| *key == "warnings") - .map(|&(_, ref level)| *level != lint::Allow) - .last() - .unwrap_or(true); - let sess = Session { target: target_cfg, host: host, @@ -477,10 +437,8 @@ pub fn build_session_(sopts: config::Options, crate_types: RefCell::new(Vec::new()), dependency_formats: RefCell::new(FnvHashMap()), crate_metadata: RefCell::new(Vec::new()), - delayed_span_bug: RefCell::new(None), features: RefCell::new(feature_gate::Features::new()), recursion_limit: Cell::new(64), - can_print_warnings: can_print_warnings, next_node_id: Cell::new(1), injected_allocator: Cell::new(None), available_macros: RefCell::new(HashSet::new()), @@ -489,13 +447,6 @@ pub fn build_session_(sopts: config::Options, sess } -// Seems out of place, but it uses session, so I'm putting it here -pub fn expect(sess: &Session, opt: Option, msg: M) -> T where - M: FnOnce() -> String, -{ - errors::expect(sess.diagnostic(), opt, msg) -} - pub fn early_error(color: errors::ColorConfig, msg: &str) -> ! { let mut emitter = BasicEmitter::stderr(color); emitter.emit(None, msg, None, errors::Level::Fatal); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 26813d89915ac..dc20b99f9a6bb 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -862,7 +862,7 @@ fn run_work_multithreaded(sess: &Session, futures.push(rx); thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || { - let diag_handler = Handler::with_emitter(true, box diag_emitter); + let diag_handler = Handler::with_emitter(true, false, box diag_emitter); // Must construct cgcx inside the proc because it has non-Send // fields. diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index a22c12588e5f7..cf82a3b72d578 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -20,7 +20,6 @@ pub use self::CallArgs::*; use arena::TypedArena; use back::link; -use session; use llvm::{self, ValueRef, get_params}; use middle::cstore::LOCAL_CRATE; use middle::def; @@ -57,6 +56,7 @@ use rustc_front::hir; use syntax::abi as synabi; use syntax::ast; +use syntax::errors; use syntax::ptr::P; #[derive(Copy, Clone)] @@ -412,8 +412,8 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( Some(n) => n, None => { return false; } }; - let map_node = session::expect( - &tcx.sess, + let map_node = errors::expect( + &tcx.sess.diagnostic(), tcx.map.find(node_id), || "local item should be in ast map".to_string()); diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 9c1fcaff7c895..4b6a0d1a50965 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -9,7 +9,6 @@ // except according to those terms. use back::link::exported_name; -use session; use llvm::ValueRef; use llvm; use middle::def_id::DefId; @@ -32,6 +31,7 @@ use rustc_front::hir; use syntax::abi; use syntax::ast; use syntax::attr; +use syntax::errors; use std::hash::{Hasher, Hash, SipHasher}; pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, @@ -83,8 +83,8 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, hash_id); - let map_node = session::expect( - ccx.sess(), + let map_node = errors::expect( + ccx.sess().diagnostic(), ccx.tcx().map.find(fn_node_id), || { format!("while monomorphizing {:?}, couldn't find it in \ diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index f74e9023ed18b..ed87961e7f3d7 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -49,7 +49,7 @@ pub struct ParseSess { impl ParseSess { pub fn new() -> ParseSess { let cm = Rc::new(CodeMap::new()); - let handler = Handler::new(ColorConfig::Auto, None, true, cm.clone()); + let handler = Handler::new(ColorConfig::Auto, None, true, false, cm.clone()); ParseSess::with_span_handler(handler, cm) } From 7a0334944b173811f4c72e29362e24252dc0ab5e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Dec 2015 14:11:27 +1300 Subject: [PATCH 05/13] Add the files I fogot about earlier d'oh --- src/libsyntax/errors/emitter.rs | 631 ++++++++++++++++++++++++++++++++ src/libsyntax/errors/mod.rs | 396 ++++++++++++++++++++ 2 files changed, 1027 insertions(+) create mode 100644 src/libsyntax/errors/emitter.rs create mode 100644 src/libsyntax/errors/mod.rs diff --git a/src/libsyntax/errors/emitter.rs b/src/libsyntax/errors/emitter.rs new file mode 100644 index 0000000000000..cbb5970bd550d --- /dev/null +++ b/src/libsyntax/errors/emitter.rs @@ -0,0 +1,631 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use self::Destination::*; + +use codemap::{self, COMMAND_LINE_SP, COMMAND_LINE_EXPN, Pos, Span}; +use diagnostics; + +use errors::{Level, RenderSpan}; +use errors::RenderSpan::*; +use errors::Level::*; + +use std::{cmp, fmt}; +use std::io::prelude::*; +use std::io; +use std::rc::Rc; +use term; + + +pub trait Emitter { + fn emit(&mut self, span: Option, msg: &str, code: Option<&str>, lvl: Level); + fn custom_emit(&mut self, sp: RenderSpan, msg: &str, lvl: Level); +} + +/// maximum number of lines we will print for each error; arbitrary. +const MAX_LINES: usize = 6; + +#[derive(Clone, Copy)] +pub enum ColorConfig { + Auto, + Always, + Never, +} + +// A basic emitter for when we don't have access to a codemap or registry. Used +// for reporting very early errors, etc. +pub struct BasicEmitter { + dst: Destination, +} + +impl Emitter for BasicEmitter { + fn emit(&mut self, + sp: Option, + msg: &str, + code: Option<&str>, + lvl: Level) { + assert!(sp.is_none(), "BasicEmitter can't handle spans"); + if let Err(e) = print_diagnostic(&mut self.dst, "", lvl, msg, code) { + panic!("failed to print diagnostics: {:?}", e); + } + + } + + fn custom_emit(&mut self, _: RenderSpan, _: &str, _: Level) { + panic!("BasicEmitter can't handle custom_emit"); + } +} + +impl BasicEmitter { + // TODO refactor + pub fn stderr(color_config: ColorConfig) -> BasicEmitter { + let stderr = io::stderr(); + + let use_color = match color_config { + ColorConfig::Always => true, + ColorConfig::Never => false, + ColorConfig::Auto => stderr_isatty(), + }; + + if use_color { + let dst = match term::stderr() { + Some(t) => Terminal(t), + None => Raw(Box::new(stderr)), + }; + BasicEmitter { dst: dst } + } else { + BasicEmitter { dst: Raw(Box::new(stderr)) } + } + } +} + +pub struct EmitterWriter { + dst: Destination, + registry: Option, + cm: Rc, +} + +impl Emitter for EmitterWriter { + fn emit(&mut self, + sp: Option, + msg: &str, + code: Option<&str>, + lvl: Level) { + let error = match sp { + Some(COMMAND_LINE_SP) => self.emit_(FileLine(COMMAND_LINE_SP), msg, code, lvl), + Some(sp) => self.emit_(FullSpan(sp), msg, code, lvl), + None => print_diagnostic(&mut self.dst, "", lvl, msg, code), + }; + + if let Err(e) = error { + panic!("failed to print diagnostics: {:?}", e); + } + } + + fn custom_emit(&mut self, + sp: RenderSpan, + msg: &str, + lvl: Level) { + match self.emit_(sp, msg, None, lvl) { + Ok(()) => {} + Err(e) => panic!("failed to print diagnostics: {:?}", e), + } + } +} + +/// Do not use this for messages that end in `\n` – use `println_maybe_styled` instead. See +/// `EmitterWriter::print_maybe_styled` for details. +macro_rules! print_maybe_styled { + ($dst: expr, $style: expr, $($arg: tt)*) => { + $dst.print_maybe_styled(format_args!($($arg)*), $style, false) + } +} + +macro_rules! println_maybe_styled { + ($dst: expr, $style: expr, $($arg: tt)*) => { + $dst.print_maybe_styled(format_args!($($arg)*), $style, true) + } +} + +impl EmitterWriter { + pub fn stderr(color_config: ColorConfig, + registry: Option, + code_map: Rc) + -> EmitterWriter { + let stderr = io::stderr(); + + let use_color = match color_config { + ColorConfig::Always => true, + ColorConfig::Never => false, + ColorConfig::Auto => stderr_isatty(), + }; + + if use_color { + let dst = match term::stderr() { + Some(t) => Terminal(t), + None => Raw(Box::new(stderr)), + }; + EmitterWriter { dst: dst, registry: registry, cm: code_map } + } else { + EmitterWriter { dst: Raw(Box::new(stderr)), registry: registry, cm: code_map } + } + } + + pub fn new(dst: Box, + registry: Option, + code_map: Rc) + -> EmitterWriter { + EmitterWriter { dst: Raw(dst), registry: registry, cm: code_map } + } + + fn emit_(&mut self, + rsp: RenderSpan, + msg: &str, + code: Option<&str>, + lvl: Level) + -> io::Result<()> { + let sp = rsp.span(); + + // We cannot check equality directly with COMMAND_LINE_SP + // since PartialEq is manually implemented to ignore the ExpnId + let ss = if sp.expn_id == COMMAND_LINE_EXPN { + "".to_string() + } else if let EndSpan(_) = rsp { + let span_end = Span { lo: sp.hi, hi: sp.hi, expn_id: sp.expn_id}; + self.cm.span_to_string(span_end) + } else { + self.cm.span_to_string(sp) + }; + + try!(print_diagnostic(&mut self.dst, &ss[..], lvl, msg, code)); + + match rsp { + FullSpan(_) => { + let lines = self.cm.span_to_lines(sp); + try!(self.highlight_lines(sp, lvl, lines)); + try!(self.print_macro_backtrace(sp)); + } + EndSpan(_) => { + let lines = self.cm.span_to_lines(sp); + try!(self.end_highlight_lines(sp, lvl, lines)); + try!(self.print_macro_backtrace(sp)); + } + Suggestion(_, ref suggestion) => { + try!(self.highlight_suggestion(sp, suggestion)); + try!(self.print_macro_backtrace(sp)); + } + FileLine(..) => { + // no source text in this case! + } + } + + match code { + Some(code) => + match self.registry.as_ref().and_then(|registry| registry.find_description(code)) { + Some(_) => { + try!(print_diagnostic(&mut self.dst, &ss[..], Help, + &format!("run `rustc --explain {}` to see a \ + detailed explanation", code), None)); + } + None => () + }, + None => (), + } + Ok(()) + } + + fn highlight_suggestion(&mut self, + sp: Span, + suggestion: &str) + -> io::Result<()> + { + let lines = self.cm.span_to_lines(sp).unwrap(); + assert!(!lines.lines.is_empty()); + + // To build up the result, we want to take the snippet from the first + // line that precedes the span, prepend that with the suggestion, and + // then append the snippet from the last line that trails the span. + let fm = &lines.file; + + let first_line = &lines.lines[0]; + let prefix = fm.get_line(first_line.line_index) + .map(|l| &l[..first_line.start_col.0]) + .unwrap_or(""); + + let last_line = lines.lines.last().unwrap(); + let suffix = fm.get_line(last_line.line_index) + .map(|l| &l[last_line.end_col.0..]) + .unwrap_or(""); + + let complete = format!("{}{}{}", prefix, suggestion, suffix); + + // print the suggestion without any line numbers, but leave + // space for them. This helps with lining up with previous + // snippets from the actual error being reported. + let fm = &*lines.file; + let mut lines = complete.lines(); + for (line, line_index) in lines.by_ref().take(MAX_LINES).zip(first_line.line_index..) { + let elided_line_num = format!("{}", line_index+1); + try!(write!(&mut self.dst, "{0}:{1:2$} {3}\n", + fm.name, "", elided_line_num.len(), line)); + } + + // if we elided some lines, add an ellipsis + if lines.next().is_some() { + let elided_line_num = format!("{}", first_line.line_index + MAX_LINES + 1); + try!(write!(&mut self.dst, "{0:1$} {0:2$} ...\n", + "", fm.name.len(), elided_line_num.len())); + } + + Ok(()) + } + + fn highlight_lines(&mut self, + sp: Span, + lvl: Level, + lines: codemap::FileLinesResult) + -> io::Result<()> + { + let lines = match lines { + Ok(lines) => lines, + Err(_) => { + try!(write!(&mut self.dst, "(internal compiler error: unprintable span)\n")); + return Ok(()); + } + }; + + let fm = &*lines.file; + + let line_strings: Option> = + lines.lines.iter() + .map(|info| fm.get_line(info.line_index)) + .collect(); + + let line_strings = match line_strings { + None => { return Ok(()); } + Some(line_strings) => line_strings + }; + + // Display only the first MAX_LINES lines. + let all_lines = lines.lines.len(); + let display_lines = cmp::min(all_lines, MAX_LINES); + let display_line_infos = &lines.lines[..display_lines]; + let display_line_strings = &line_strings[..display_lines]; + + // Calculate the widest number to format evenly and fix #11715 + assert!(display_line_infos.len() > 0); + let mut max_line_num = display_line_infos[display_line_infos.len() - 1].line_index + 1; + let mut digits = 0; + while max_line_num > 0 { + max_line_num /= 10; + digits += 1; + } + + // Print the offending lines + for (line_info, line) in display_line_infos.iter().zip(display_line_strings) { + try!(write!(&mut self.dst, "{}:{:>width$} {}\n", + fm.name, + line_info.line_index + 1, + line, + width=digits)); + } + + // If we elided something, put an ellipsis. + if display_lines < all_lines { + let last_line_index = display_line_infos.last().unwrap().line_index; + let s = format!("{}:{} ", fm.name, last_line_index + 1); + try!(write!(&mut self.dst, "{0:1$}...\n", "", s.len())); + } + + // FIXME (#3260) + // If there's one line at fault we can easily point to the problem + if lines.lines.len() == 1 { + let lo = self.cm.lookup_char_pos(sp.lo); + let mut digits = 0; + let mut num = (lines.lines[0].line_index + 1) / 10; + + // how many digits must be indent past? + while num > 0 { num /= 10; digits += 1; } + + let mut s = String::new(); + // Skip is the number of characters we need to skip because they are + // part of the 'filename:line ' part of the previous line. + let skip = fm.name.chars().count() + digits + 3; + for _ in 0..skip { + s.push(' '); + } + if let Some(orig) = fm.get_line(lines.lines[0].line_index) { + let mut col = skip; + let mut lastc = ' '; + let mut iter = orig.chars().enumerate(); + for (pos, ch) in iter.by_ref() { + lastc = ch; + if pos >= lo.col.to_usize() { break; } + // Whenever a tab occurs on the previous line, we insert one on + // the error-point-squiggly-line as well (instead of a space). + // That way the squiggly line will usually appear in the correct + // position. + match ch { + '\t' => { + col += 8 - col%8; + s.push('\t'); + }, + _ => { + col += 1; + s.push(' '); + }, + } + } + + try!(write!(&mut self.dst, "{}", s)); + let mut s = String::from("^"); + let count = match lastc { + // Most terminals have a tab stop every eight columns by default + '\t' => 8 - col%8, + _ => 1, + }; + col += count; + s.extend(::std::iter::repeat('~').take(count)); + + let hi = self.cm.lookup_char_pos(sp.hi); + if hi.col != lo.col { + for (pos, ch) in iter { + if pos >= hi.col.to_usize() { break; } + let count = match ch { + '\t' => 8 - col%8, + _ => 1, + }; + col += count; + s.extend(::std::iter::repeat('~').take(count)); + } + } + + if s.len() > 1 { + // One extra squiggly is replaced by a "^" + s.pop(); + } + + try!(println_maybe_styled!(&mut self.dst, term::Attr::ForegroundColor(lvl.color()), + "{}", s)); + } + } + Ok(()) + } + + /// Here are the differences between this and the normal `highlight_lines`: + /// `end_highlight_lines` will always put arrow on the last byte of the + /// span (instead of the first byte). Also, when the span is too long (more + /// than 6 lines), `end_highlight_lines` will print the first line, then + /// dot dot dot, then last line, whereas `highlight_lines` prints the first + /// six lines. + #[allow(deprecated)] + fn end_highlight_lines(&mut self, + sp: Span, + lvl: Level, + lines: codemap::FileLinesResult) + -> io::Result<()> { + let lines = match lines { + Ok(lines) => lines, + Err(_) => { + try!(write!(&mut self.dst, "(internal compiler error: unprintable span)\n")); + return Ok(()); + } + }; + + let fm = &*lines.file; + + let lines = &lines.lines[..]; + if lines.len() > MAX_LINES { + if let Some(line) = fm.get_line(lines[0].line_index) { + try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, + lines[0].line_index + 1, line)); + } + try!(write!(&mut self.dst, "...\n")); + let last_line_index = lines[lines.len() - 1].line_index; + if let Some(last_line) = fm.get_line(last_line_index) { + try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, + last_line_index + 1, last_line)); + } + } else { + for line_info in lines { + if let Some(line) = fm.get_line(line_info.line_index) { + try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, + line_info.line_index + 1, line)); + } + } + } + let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1].line_index + 1); + let hi = self.cm.lookup_char_pos(sp.hi); + let skip = last_line_start.chars().count(); + let mut s = String::new(); + for _ in 0..skip { + s.push(' '); + } + if let Some(orig) = fm.get_line(lines[0].line_index) { + let iter = orig.chars().enumerate(); + for (pos, ch) in iter { + // Span seems to use half-opened interval, so subtract 1 + if pos >= hi.col.to_usize() - 1 { break; } + // Whenever a tab occurs on the previous line, we insert one on + // the error-point-squiggly-line as well (instead of a space). + // That way the squiggly line will usually appear in the correct + // position. + match ch { + '\t' => s.push('\t'), + _ => s.push(' '), + } + } + } + s.push('^'); + println_maybe_styled!(&mut self.dst, term::Attr::ForegroundColor(lvl.color()), + "{}", s) + } + + fn print_macro_backtrace(&mut self, + sp: Span) + -> io::Result<()> { + let mut last_span = codemap::DUMMY_SP; + let mut span = sp; + + loop { + let span_name_span = self.cm.with_expn_info(span.expn_id, |expn_info| { + match expn_info { + Some(ei) => { + let (pre, post) = match ei.callee.format { + codemap::MacroAttribute(..) => ("#[", "]"), + codemap::MacroBang(..) => ("", "!"), + }; + let macro_decl_name = format!("in this expansion of {}{}{}", + pre, + ei.callee.name(), + post); + let def_site_span = ei.callee.span; + Some((ei.call_site, macro_decl_name, def_site_span)) + } + // TODO map + None => None, + } + }); + let (macro_decl_name, def_site_span) = match span_name_span { + None => break, + Some((sp, macro_decl_name, def_site_span)) => { + span = sp; + (macro_decl_name, def_site_span) + } + }; + + // Don't print recursive invocations + if span != last_span { + let mut diag_string = macro_decl_name; + if let Some(def_site_span) = def_site_span { + diag_string.push_str(&format!(" (defined in {})", + self.cm.span_to_filename(def_site_span))); + } + + let snippet = self.cm.span_to_string(span); + try!(print_diagnostic(&mut self.dst, &snippet, Note, &diag_string, None)); + } + last_span = span; + } + + Ok(()) + } +} + +fn print_diagnostic(dst: &mut Destination, + topic: &str, + lvl: Level, + msg: &str, + code: Option<&str>) + -> io::Result<()> { + if !topic.is_empty() { + try!(write!(dst, "{} ", topic)); + } + + try!(print_maybe_styled!(dst, term::Attr::ForegroundColor(lvl.color()), + "{}: ", lvl.to_string())); + try!(print_maybe_styled!(dst, term::Attr::Bold, "{}", msg)); + + match code { + Some(code) => { + let style = term::Attr::ForegroundColor(term::color::BRIGHT_MAGENTA); + try!(print_maybe_styled!(dst, style, " [{}]", code.clone())); + } + None => () + } + try!(write!(dst, "\n")); + Ok(()) +} + +#[cfg(unix)] +fn stderr_isatty() -> bool { + use libc; + unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } +} +#[cfg(windows)] +fn stderr_isatty() -> bool { + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; + extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, + lpMode: *mut DWORD) -> BOOL; + } + unsafe { + let handle = GetStdHandle(STD_ERROR_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + +enum Destination { + Terminal(Box), + Raw(Box), +} + +impl Destination { + fn print_maybe_styled(&mut self, + args: fmt::Arguments, + color: term::Attr, + print_newline_at_end: bool) + -> io::Result<()> { + match *self { + Terminal(ref mut t) => { + try!(t.attr(color)); + // If `msg` ends in a newline, we need to reset the color before + // the newline. We're making the assumption that we end up writing + // to a `LineBufferedWriter`, which means that emitting the reset + // after the newline ends up buffering the reset until we print + // another line or exit. Buffering the reset is a problem if we're + // sharing the terminal with any other programs (e.g. other rustc + // instances via `make -jN`). + // + // Note that if `msg` contains any internal newlines, this will + // result in the `LineBufferedWriter` flushing twice instead of + // once, which still leaves the opportunity for interleaved output + // to be miscolored. We assume this is rare enough that we don't + // have to worry about it. + try!(t.write_fmt(args)); + try!(t.reset()); + if print_newline_at_end { + t.write_all(b"\n") + } else { + Ok(()) + } + } + Raw(ref mut w) => { + try!(w.write_fmt(args)); + if print_newline_at_end { + w.write_all(b"\n") + } else { + Ok(()) + } + } + } + } +} + +impl Write for Destination { + fn write(&mut self, bytes: &[u8]) -> io::Result { + match *self { + Terminal(ref mut t) => t.write(bytes), + Raw(ref mut w) => w.write(bytes), + } + } + fn flush(&mut self) -> io::Result<()> { + match *self { + Terminal(ref mut t) => t.flush(), + Raw(ref mut w) => w.flush(), + } + } +} + diff --git a/src/libsyntax/errors/mod.rs b/src/libsyntax/errors/mod.rs new file mode 100644 index 0000000000000..920fd2fdb0049 --- /dev/null +++ b/src/libsyntax/errors/mod.rs @@ -0,0 +1,396 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use errors::emitter::ColorConfig; + +use self::Level::*; +use self::RenderSpan::*; + +use codemap::{self, Span}; +use diagnostics; +use errors::emitter::{Emitter, EmitterWriter}; + +use std::cell::{RefCell, Cell}; +use std::{error, fmt}; +use std::io::prelude::*; +use std::rc::Rc; +use term; + +pub mod emitter; + +#[derive(Clone)] +pub enum RenderSpan { + /// A FullSpan renders with both with an initial line for the + /// message, prefixed by file:linenum, followed by a summary of + /// the source code covered by the span. + FullSpan(Span), + + /// Similar to a FullSpan, but the cited position is the end of + /// the span, instead of the start. Used, at least, for telling + /// compiletest/runtest to look at the last line of the span + /// (since `end_highlight_lines` displays an arrow to the end + /// of the span). + EndSpan(Span), + + /// A suggestion renders with both with an initial line for the + /// message, prefixed by file:linenum, followed by a summary + /// of hypothetical source code, where the `String` is spliced + /// into the lines in place of the code covered by the span. + Suggestion(Span, String), + + /// A FileLine renders with just a line for the message prefixed + /// by file:linenum. + FileLine(Span), +} + +impl RenderSpan { + fn span(&self) -> Span { + match *self { + FullSpan(s) | + Suggestion(s, _) | + EndSpan(s) | + FileLine(s) => + s + } + } +} + +/// Used as a return value to signify a fatal error occurred. (It is also +/// used as the argument to panic at the moment, but that will eventually +/// not be true.) +#[derive(Copy, Clone, Debug)] +#[must_use] +pub struct FatalError; + +impl fmt::Display for FatalError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "parser fatal error") + } +} + +impl error::Error for FatalError { + fn description(&self) -> &str { + "The parser has encountered a fatal error" + } +} + +/// Signifies that the compiler died with an explicit call to `.bug` +/// or `.span_bug` rather than a failed assertion, etc. +#[derive(Copy, Clone, Debug)] +pub struct ExplicitBug; + +impl fmt::Display for ExplicitBug { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "parser internal bug") + } +} + +impl error::Error for ExplicitBug { + fn description(&self) -> &str { + "The parser has encountered an internal bug" + } +} + +/// A handler deals with errors; certain errors +/// (fatal, bug, unimpl) may cause immediate exit, +/// others log errors for later reporting. +pub struct Handler { + err_count: Cell, + emit: RefCell>, + pub can_emit_warnings: bool, + treat_err_as_bug: bool, + delayed_span_bug: RefCell>, +} + +impl Handler { + pub fn new(color_config: ColorConfig, + registry: Option, + can_emit_warnings: bool, + treat_err_as_bug: bool, + cm: Rc) + -> Handler { + let emitter = Box::new(EmitterWriter::stderr(color_config, registry, cm)); + Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter) + } + + pub fn with_emitter(can_emit_warnings: bool, + treat_err_as_bug: bool, + e: Box) -> Handler { + Handler { + err_count: Cell::new(0), + emit: RefCell::new(e), + can_emit_warnings: can_emit_warnings, + treat_err_as_bug: treat_err_as_bug, + delayed_span_bug: RefCell::new(None), + } + } + + pub fn span_fatal(&self, sp: Span, msg: &str) -> FatalError { + if self.treat_err_as_bug { + self.span_bug(sp, msg); + } + self.emit(Some(sp), msg, Fatal); + return FatalError; + } + pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> FatalError { + if self.treat_err_as_bug { + self.span_bug(sp, msg); + } + self.emit_with_code(Some(sp), msg, code, Fatal); + return FatalError; + } + pub fn span_err(&self, sp: Span, msg: &str) { + if self.treat_err_as_bug { + self.span_bug(sp, msg); + } + self.emit(Some(sp), msg, Error); + self.bump_err_count(); + } + pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) { + if self.treat_err_as_bug { + self.span_bug(sp, msg); + } + self.emit_with_code(Some(sp), msg, code, Error); + self.bump_err_count(); + } + pub fn span_warn(&self, sp: Span, msg: &str) { + self.emit(Some(sp), msg, Warning); + } + pub fn span_warn_with_code(&self, sp: Span, msg: &str, code: &str) { + self.emit_with_code(Some(sp), msg, code, Warning); + } + pub fn span_note(&self, sp: Span, msg: &str) { + self.emit(Some(sp), msg, Note); + } + pub fn span_end_note(&self, sp: Span, msg: &str) { + self.custom_emit(EndSpan(sp), msg, Note); + } + pub fn span_help(&self, sp: Span, msg: &str) { + self.emit(Some(sp), msg, Help); + } + /// Prints out a message with a suggested edit of the code. + /// + /// See `diagnostic::RenderSpan::Suggestion` for more information. + pub fn span_suggestion(&self, sp: Span, msg: &str, suggestion: String) { + self.custom_emit(Suggestion(sp, suggestion), msg, Help); + } + pub fn fileline_note(&self, sp: Span, msg: &str) { + self.custom_emit(FileLine(sp), msg, Note); + } + pub fn fileline_help(&self, sp: Span, msg: &str) { + self.custom_emit(FileLine(sp), msg, Help); + } + pub fn span_bug(&self, sp: Span, msg: &str) -> ! { + self.emit(Some(sp), msg, Bug); + panic!(ExplicitBug); + } + pub fn delay_span_bug(&self, sp: Span, msg: &str) { + let mut delayed = self.delayed_span_bug.borrow_mut(); + *delayed = Some((sp, msg.to_string())); + } + pub fn span_bug_no_panic(&self, sp: Span, msg: &str) { + self.emit(Some(sp), msg, Bug); + self.bump_err_count(); + } + pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! { + self.span_bug(sp, &format!("unimplemented {}", msg)); + } + pub fn fatal(&self, msg: &str) -> FatalError { + if self.treat_err_as_bug { + self.bug(msg); + } + self.emit.borrow_mut().emit(None, msg, None, Fatal); + FatalError + } + pub fn err(&self, msg: &str) { + if self.treat_err_as_bug { + self.bug(msg); + } + self.emit.borrow_mut().emit(None, msg, None, Error); + self.bump_err_count(); + } + pub fn warn(&self, msg: &str) { + self.emit.borrow_mut().emit(None, msg, None, Warning); + } + pub fn note(&self, msg: &str) { + self.emit.borrow_mut().emit(None, msg, None, Note); + } + pub fn help(&self, msg: &str) { + self.emit.borrow_mut().emit(None, msg, None, Help); + } + pub fn bug(&self, msg: &str) -> ! { + self.emit.borrow_mut().emit(None, msg, None, Bug); + panic!(ExplicitBug); + } + pub fn unimpl(&self, msg: &str) -> ! { + self.bug(&format!("unimplemented {}", msg)); + } + + pub fn bump_err_count(&self) { + self.err_count.set(self.err_count.get() + 1); + } + + pub fn err_count(&self) -> usize { + self.err_count.get() + } + + pub fn has_errors(&self) -> bool { + self.err_count.get() > 0 + } + + pub fn abort_if_errors(&self) { + let s; + match self.err_count.get() { + 0 => { + let delayed_bug = self.delayed_span_bug.borrow(); + match *delayed_bug { + Some((span, ref errmsg)) => { + self.span_bug(span, errmsg); + }, + _ => {} + } + + return; + } + 1 => s = "aborting due to previous error".to_string(), + _ => { + s = format!("aborting due to {} previous errors", + self.err_count.get()); + } + } + + panic!(self.fatal(&s[..])); + } + + pub fn emit(&self, + sp: Option, + msg: &str, + lvl: Level) { + if lvl == Warning && !self.can_emit_warnings { return } + self.emit.borrow_mut().emit(sp, msg, None, lvl); + } + + pub fn emit_with_code(&self, + sp: Option, + msg: &str, + code: &str, + lvl: Level) { + if lvl == Warning && !self.can_emit_warnings { return } + self.emit.borrow_mut().emit(sp, msg, Some(code), lvl); + } + + pub fn custom_emit(&self, sp: RenderSpan, msg: &str, lvl: Level) { + if lvl == Warning && !self.can_emit_warnings { return } + self.emit.borrow_mut().custom_emit(sp, msg, lvl); + } +} + + +#[derive(Copy, PartialEq, Clone, Debug)] +pub enum Level { + Bug, + Fatal, + Error, + Warning, + Note, + Help, +} + +impl fmt::Display for Level { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use std::fmt::Display; + + match *self { + Bug => "error: internal compiler error".fmt(f), + Fatal | Error => "error".fmt(f), + Warning => "warning".fmt(f), + Note => "note".fmt(f), + Help => "help".fmt(f), + } + } +} + +impl Level { + fn color(self) -> term::color::Color { + match self { + Bug | Fatal | Error => term::color::BRIGHT_RED, + Warning => term::color::BRIGHT_YELLOW, + Note => term::color::BRIGHT_GREEN, + Help => term::color::BRIGHT_CYAN, + } + } +} + +pub fn expect(diag: &Handler, opt: Option, msg: M) -> T where + M: FnOnce() -> String, +{ + match opt { + Some(t) => t, + None => diag.bug(&msg()), + } +} + +#[cfg(test)] +mod test { + use super::Level; + use emitter::EmitterWriter; + use codemap::{mk_sp, CodeMap}; + use std::sync::{Arc, Mutex}; + use std::io::{self, Write}; + use std::str::from_utf8; + + // Diagnostic doesn't align properly in span where line number increases by one digit + #[test] + fn test_hilight_suggestion_issue_11715() { + struct Sink(Arc>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + let data = Arc::new(Mutex::new(Vec::new())); + let mut ew = EmitterWriter::new(Box::new(Sink(data.clone())), None); + let cm = CodeMap::new(); + let content = "abcdefg + koksi + line3 + line4 + cinq + line6 + line7 + line8 + line9 + line10 + e-lä-vän + tolv + dreizehn + "; + let file = cm.new_filemap_and_lines("dummy.txt", content); + let start = file.lines.borrow()[7]; + let end = file.lines.borrow()[11]; + let sp = mk_sp(start, end); + let lvl = Level::Error; + println!("span_to_lines"); + let lines = cm.span_to_lines(sp); + println!("highlight_lines"); + ew.highlight_lines(&cm, sp, lvl, lines).unwrap(); + println!("done"); + let vec = data.lock().unwrap().clone(); + let vec: &[u8] = &vec; + let str = from_utf8(vec).unwrap(); + println!("{}", str); + assert_eq!(str, "dummy.txt: 8 line8\n\ + dummy.txt: 9 line9\n\ + dummy.txt:10 line10\n\ + dummy.txt:11 e-lä-vän\n\ + dummy.txt:12 tolv\n"); + } +} From e2371518c4b03e1770948d9d2429cfeb46e25a20 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Dec 2015 16:42:05 +1300 Subject: [PATCH 06/13] A little more refactoring inside emitter.rs --- src/libsyntax/errors/emitter.rs | 80 +++++++++++++++------------------ 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/src/libsyntax/errors/emitter.rs b/src/libsyntax/errors/emitter.rs index cbb5970bd550d..e65eab58d9af5 100644 --- a/src/libsyntax/errors/emitter.rs +++ b/src/libsyntax/errors/emitter.rs @@ -39,6 +39,16 @@ pub enum ColorConfig { Never, } +impl ColorConfig { + fn use_color(&self) -> bool { + match *self { + ColorConfig::Always => true, + ColorConfig::Never => false, + ColorConfig::Auto => stderr_isatty(), + } + } +} + // A basic emitter for when we don't have access to a codemap or registry. Used // for reporting very early errors, etc. pub struct BasicEmitter { @@ -64,24 +74,12 @@ impl Emitter for BasicEmitter { } impl BasicEmitter { - // TODO refactor pub fn stderr(color_config: ColorConfig) -> BasicEmitter { - let stderr = io::stderr(); - - let use_color = match color_config { - ColorConfig::Always => true, - ColorConfig::Never => false, - ColorConfig::Auto => stderr_isatty(), - }; - - if use_color { - let dst = match term::stderr() { - Some(t) => Terminal(t), - None => Raw(Box::new(stderr)), - }; + if color_config.use_color() { + let dst = Destination::from_stderr(); BasicEmitter { dst: dst } } else { - BasicEmitter { dst: Raw(Box::new(stderr)) } + BasicEmitter { dst: Raw(Box::new(io::stderr())) } } } } @@ -139,22 +137,11 @@ impl EmitterWriter { registry: Option, code_map: Rc) -> EmitterWriter { - let stderr = io::stderr(); - - let use_color = match color_config { - ColorConfig::Always => true, - ColorConfig::Never => false, - ColorConfig::Auto => stderr_isatty(), - }; - - if use_color { - let dst = match term::stderr() { - Some(t) => Terminal(t), - None => Raw(Box::new(stderr)), - }; + if color_config.use_color() { + let dst = Destination::from_stderr(); EmitterWriter { dst: dst, registry: registry, cm: code_map } } else { - EmitterWriter { dst: Raw(Box::new(stderr)), registry: registry, cm: code_map } + EmitterWriter { dst: Raw(Box::new(io::stderr())), registry: registry, cm: code_map } } } @@ -476,22 +463,18 @@ impl EmitterWriter { loop { let span_name_span = self.cm.with_expn_info(span.expn_id, |expn_info| { - match expn_info { - Some(ei) => { - let (pre, post) = match ei.callee.format { - codemap::MacroAttribute(..) => ("#[", "]"), - codemap::MacroBang(..) => ("", "!"), - }; - let macro_decl_name = format!("in this expansion of {}{}{}", - pre, - ei.callee.name(), - post); - let def_site_span = ei.callee.span; - Some((ei.call_site, macro_decl_name, def_site_span)) - } - // TODO map - None => None, - } + expn_info.map(|ei| { + let (pre, post) = match ei.callee.format { + codemap::MacroAttribute(..) => ("#[", "]"), + codemap::MacroBang(..) => ("", "!"), + }; + let macro_decl_name = format!("in this expansion of {}{}{}", + pre, + ei.callee.name(), + post); + let def_site_span = ei.callee.span; + (ei.call_site, macro_decl_name, def_site_span) + }) }); let (macro_decl_name, def_site_span) = match span_name_span { None => break, @@ -573,6 +556,13 @@ enum Destination { } impl Destination { + fn from_stderr() -> Destination { + match term::stderr() { + Some(t) => Terminal(t), + None => Raw(Box::new(io::stderr())), + } + } + fn print_maybe_styled(&mut self, args: fmt::Arguments, color: term::Attr, From ff0c74f7d47f5261ebda7cb3b9a637e0cfc69104 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Dec 2015 16:51:13 +1300 Subject: [PATCH 07/13] test errors --- src/librustc/session/config.rs | 6 +- src/librustc_driver/test.rs | 30 +++---- src/librustdoc/test.rs | 4 +- src/libsyntax/errors/emitter.rs | 61 ++++++++++++++- src/libsyntax/errors/mod.rs | 58 -------------- src/libsyntax/parse/lexer/mod.rs | 78 ++++++++++++------- src/libsyntax_ext/lib.rs | 2 +- .../run-pass-fulldeps/ast_stmt_expr_attr.rs | 2 +- src/test/run-pass-fulldeps/compiler-calls.rs | 4 +- 9 files changed, 131 insertions(+), 114 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 75761dbc15ade..e33fe9570c024 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1224,7 +1224,7 @@ mod tests { let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry, Rc::new(DummyCrateStore)); - assert!(!sess.can_print_warnings); + assert!(!sess.diagnostic().can_emit_warnings); } { @@ -1236,7 +1236,7 @@ mod tests { let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry, Rc::new(DummyCrateStore)); - assert!(sess.can_print_warnings); + assert!(sess.diagnostic().can_emit_warnings); } { @@ -1247,7 +1247,7 @@ mod tests { let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry, Rc::new(DummyCrateStore)); - assert!(sess.can_print_warnings); + assert!(sess.diagnostic().can_emit_warnings); } } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 2fb23c943c76a..df9294a9d5bfb 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -10,8 +10,6 @@ //! # Standalone Tests for the Inference Module -use diagnostic; -use diagnostic::Emitter; use driver; use rustc_lint; use rustc_resolve as resolve; @@ -34,9 +32,10 @@ use rustc::front::map as hir_map; use rustc::session::{self, config}; use std::rc::Rc; use syntax::{abi, ast}; -use syntax::codemap; use syntax::codemap::{Span, CodeMap, DUMMY_SP}; -use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help}; +use syntax::errors; +use syntax::errors::emitter::Emitter; +use syntax::errors::{Level, RenderSpan}; use syntax::parse::token; use syntax::feature_gate::UnstableFeatures; @@ -60,8 +59,8 @@ struct ExpectErrorEmitter { fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) { match lvl { - Bug | Fatal | Error => {} - Warning | Note | Help => { + Level::Bug | Level::Fatal | Level::Error => {} + Level::Warning | Level::Note | Level::Help => { return; } } @@ -79,14 +78,14 @@ fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) { impl Emitter for ExpectErrorEmitter { fn emit(&mut self, - _cmsp: Option<(&codemap::CodeMap, Span)>, + _sp: Option, msg: &str, _: Option<&str>, lvl: Level) { remove_message(self, msg, lvl); } - fn custom_emit(&mut self, _cm: &codemap::CodeMap, _sp: RenderSpan, msg: &str, lvl: Level) { + fn custom_emit(&mut self, _sp: RenderSpan, msg: &str, lvl: Level) { remove_message(self, msg, lvl); } } @@ -105,13 +104,11 @@ fn test_env(source_string: &str, let mut options = config::basic_options(); options.debugging_opts.verbose = true; options.unstable_features = UnstableFeatures::Allow; - let codemap = CodeMap::new(); - let diagnostic_handler = diagnostic::Handler::with_emitter(true, emitter); - let span_diagnostic_handler = diagnostic::SpanHandler::new(diagnostic_handler, codemap); + let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter); let cstore = Rc::new(CStore::new(token::get_ident_interner())); - let sess = session::build_session_(options, None, span_diagnostic_handler, - cstore.clone()); + let sess = session::build_session_(options, None, diagnostic_handler, + Rc::new(CodeMap::new()), cstore.clone()); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let krate_config = Vec::new(); let input = config::Input::Str(source_string.to_string()); @@ -366,13 +363,6 @@ impl<'a, 'tcx> Env<'a, 'tcx> { self.infcx.glb(true, trace) } - pub fn make_lub_ty(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> Ty<'tcx> { - match self.lub().relate(&t1, &t2) { - Ok(t) => t, - Err(ref e) => panic!("unexpected error computing LUB: {}", e), - } - } - /// Checks that `t1 <: t2` is true (this may register additional /// region checks). pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 4ac20ba001b9f..fde8299d2d2e6 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -225,7 +225,9 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, } let data = Arc::new(Mutex::new(Vec::new())); let codemap = Rc::new(CodeMap::new()); - let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()), None, codemap.clone()); + let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()), + None, + codemap.clone()); let old = io::set_panic(box Sink(data.clone())); let _bomb = Bomb(data, old.unwrap_or(box io::stdout())); diff --git a/src/libsyntax/errors/emitter.rs b/src/libsyntax/errors/emitter.rs index e65eab58d9af5..7fef85a833e25 100644 --- a/src/libsyntax/errors/emitter.rs +++ b/src/libsyntax/errors/emitter.rs @@ -45,7 +45,7 @@ impl ColorConfig { ColorConfig::Always => true, ColorConfig::Never => false, ColorConfig::Auto => stderr_isatty(), - } + } } } @@ -619,3 +619,62 @@ impl Write for Destination { } } + +#[cfg(test)] +mod test { + use errors::Level; + use super::EmitterWriter; + use codemap::{mk_sp, CodeMap}; + use std::sync::{Arc, Mutex}; + use std::io::{self, Write}; + use std::str::from_utf8; + use std::rc::Rc; + + // Diagnostic doesn't align properly in span where line number increases by one digit + #[test] + fn test_hilight_suggestion_issue_11715() { + struct Sink(Arc>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + let data = Arc::new(Mutex::new(Vec::new())); + let cm = Rc::new(CodeMap::new()); + let mut ew = EmitterWriter::new(Box::new(Sink(data.clone())), None, cm.clone()); + let content = "abcdefg + koksi + line3 + line4 + cinq + line6 + line7 + line8 + line9 + line10 + e-lä-vän + tolv + dreizehn + "; + let file = cm.new_filemap_and_lines("dummy.txt", content); + let start = file.lines.borrow()[7]; + let end = file.lines.borrow()[11]; + let sp = mk_sp(start, end); + let lvl = Level::Error; + println!("span_to_lines"); + let lines = cm.span_to_lines(sp); + println!("highlight_lines"); + ew.highlight_lines(sp, lvl, lines).unwrap(); + println!("done"); + let vec = data.lock().unwrap().clone(); + let vec: &[u8] = &vec; + let str = from_utf8(vec).unwrap(); + println!("{}", str); + assert_eq!(str, "dummy.txt: 8 line8\n\ + dummy.txt: 9 line9\n\ + dummy.txt:10 line10\n\ + dummy.txt:11 e-lä-vän\n\ + dummy.txt:12 tolv\n"); + } +} diff --git a/src/libsyntax/errors/mod.rs b/src/libsyntax/errors/mod.rs index 920fd2fdb0049..f2e61090ba23c 100644 --- a/src/libsyntax/errors/mod.rs +++ b/src/libsyntax/errors/mod.rs @@ -336,61 +336,3 @@ pub fn expect(diag: &Handler, opt: Option, msg: M) -> T where None => diag.bug(&msg()), } } - -#[cfg(test)] -mod test { - use super::Level; - use emitter::EmitterWriter; - use codemap::{mk_sp, CodeMap}; - use std::sync::{Arc, Mutex}; - use std::io::{self, Write}; - use std::str::from_utf8; - - // Diagnostic doesn't align properly in span where line number increases by one digit - #[test] - fn test_hilight_suggestion_issue_11715() { - struct Sink(Arc>>); - impl Write for Sink { - fn write(&mut self, data: &[u8]) -> io::Result { - Write::write(&mut *self.0.lock().unwrap(), data) - } - fn flush(&mut self) -> io::Result<()> { Ok(()) } - } - let data = Arc::new(Mutex::new(Vec::new())); - let mut ew = EmitterWriter::new(Box::new(Sink(data.clone())), None); - let cm = CodeMap::new(); - let content = "abcdefg - koksi - line3 - line4 - cinq - line6 - line7 - line8 - line9 - line10 - e-lä-vän - tolv - dreizehn - "; - let file = cm.new_filemap_and_lines("dummy.txt", content); - let start = file.lines.borrow()[7]; - let end = file.lines.borrow()[11]; - let sp = mk_sp(start, end); - let lvl = Level::Error; - println!("span_to_lines"); - let lines = cm.span_to_lines(sp); - println!("highlight_lines"); - ew.highlight_lines(&cm, sp, lvl, lines).unwrap(); - println!("done"); - let vec = data.lock().unwrap().clone(); - let vec: &[u8] = &vec; - let str = from_utf8(vec).unwrap(); - println!("{}", str); - assert_eq!(str, "dummy.txt: 8 line8\n\ - dummy.txt: 9 line9\n\ - dummy.txt:10 line10\n\ - dummy.txt:11 e-lä-vän\n\ - dummy.txt:12 tolv\n"); - } -} diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 570e0882a8513..4619410ada727 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1422,28 +1422,30 @@ mod tests { use super::*; use codemap::{BytePos, CodeMap, Span, NO_EXPANSION}; - use diagnostic; + use errors; use parse::token; use parse::token::{str_to_ident}; use std::io; + use std::rc::Rc; - fn mk_sh() -> diagnostic::Handler { + fn mk_sh(cm: Rc) -> errors::Handler { // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - let emitter = diagnostic::EmitterWriter::new(Box::new(io::sink()), None); - let handler = diagnostic::Handler::with_emitter(true, Box::new(emitter)); - diagnostic::Handler::new(handler, CodeMap::new()) + let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), None, cm); + errors::Handler::with_emitter(true, false, Box::new(emitter)) } // open a string reader for the given string - fn setup<'a>(span_handler: &'a diagnostic::Handler, + fn setup<'a>(cm: &CodeMap, + span_handler: &'a errors::Handler, teststr: String) -> StringReader<'a> { - let fm = span_handler.cm.new_filemap("zebra.rs".to_string(), teststr); + let fm = cm.new_filemap("zebra.rs".to_string(), teststr); StringReader::new(span_handler, fm) } #[test] fn t1 () { - let span_handler = mk_sh(); - let mut string_reader = setup(&span_handler, + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + let mut string_reader = setup(&cm, &sh, "/* my source file */ \ fn main() { println!(\"zebra\"); }\n".to_string()); let id = str_to_ident("fn"); @@ -1481,21 +1483,27 @@ mod tests { } #[test] fn doublecolonparsing () { - check_tokenization(setup(&mk_sh(), "a b".to_string()), + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + check_tokenization(setup(&cm, &sh, "a b".to_string()), vec![mk_ident("a", token::Plain), token::Whitespace, mk_ident("b", token::Plain)]); } #[test] fn dcparsing_2 () { - check_tokenization(setup(&mk_sh(), "a::b".to_string()), + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + check_tokenization(setup(&cm, &sh, "a::b".to_string()), vec![mk_ident("a",token::ModName), token::ModSep, mk_ident("b", token::Plain)]); } #[test] fn dcparsing_3 () { - check_tokenization(setup(&mk_sh(), "a ::b".to_string()), + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + check_tokenization(setup(&cm, &sh, "a ::b".to_string()), vec![mk_ident("a", token::Plain), token::Whitespace, token::ModSep, @@ -1503,7 +1511,9 @@ mod tests { } #[test] fn dcparsing_4 () { - check_tokenization(setup(&mk_sh(), "a:: b".to_string()), + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + check_tokenization(setup(&cm, &sh, "a:: b".to_string()), vec![mk_ident("a",token::ModName), token::ModSep, token::Whitespace, @@ -1511,40 +1521,52 @@ mod tests { } #[test] fn character_a() { - assert_eq!(setup(&mk_sh(), "'a'".to_string()).next_token().tok, + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + assert_eq!(setup(&cm, &sh, "'a'".to_string()).next_token().tok, token::Literal(token::Char(token::intern("a")), None)); } #[test] fn character_space() { - assert_eq!(setup(&mk_sh(), "' '".to_string()).next_token().tok, + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + assert_eq!(setup(&cm, &sh, "' '".to_string()).next_token().tok, token::Literal(token::Char(token::intern(" ")), None)); } #[test] fn character_escaped() { - assert_eq!(setup(&mk_sh(), "'\\n'".to_string()).next_token().tok, + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + assert_eq!(setup(&cm, &sh, "'\\n'".to_string()).next_token().tok, token::Literal(token::Char(token::intern("\\n")), None)); } #[test] fn lifetime_name() { - assert_eq!(setup(&mk_sh(), "'abc".to_string()).next_token().tok, + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + assert_eq!(setup(&cm, &sh, "'abc".to_string()).next_token().tok, token::Lifetime(token::str_to_ident("'abc"))); } #[test] fn raw_string() { - assert_eq!(setup(&mk_sh(), + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + assert_eq!(setup(&cm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()).next_token() .tok, token::Literal(token::StrRaw(token::intern("\"#a\\b\x00c\""), 3), None)); } #[test] fn literal_suffixes() { + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); macro_rules! test { ($input: expr, $tok_type: ident, $tok_contents: expr) => {{ - assert_eq!(setup(&mk_sh(), format!("{}suffix", $input)).next_token().tok, + assert_eq!(setup(&cm, &sh, format!("{}suffix", $input)).next_token().tok, token::Literal(token::$tok_type(token::intern($tok_contents)), Some(token::intern("suffix")))); // with a whitespace separator: - assert_eq!(setup(&mk_sh(), format!("{} suffix", $input)).next_token().tok, + assert_eq!(setup(&cm, &sh, format!("{} suffix", $input)).next_token().tok, token::Literal(token::$tok_type(token::intern($tok_contents)), None)); }} @@ -1560,13 +1582,13 @@ mod tests { test!("1.0", Float, "1.0"); test!("1.0e10", Float, "1.0e10"); - assert_eq!(setup(&mk_sh(), "2us".to_string()).next_token().tok, + assert_eq!(setup(&cm, &sh, "2us".to_string()).next_token().tok, token::Literal(token::Integer(token::intern("2")), Some(token::intern("us")))); - assert_eq!(setup(&mk_sh(), "r###\"raw\"###suffix".to_string()).next_token().tok, + assert_eq!(setup(&cm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok, token::Literal(token::StrRaw(token::intern("raw"), 3), Some(token::intern("suffix")))); - assert_eq!(setup(&mk_sh(), "br###\"raw\"###suffix".to_string()).next_token().tok, + assert_eq!(setup(&cm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok, token::Literal(token::ByteStrRaw(token::intern("raw"), 3), Some(token::intern("suffix")))); } @@ -1578,8 +1600,9 @@ mod tests { } #[test] fn nested_block_comments() { - let sh = mk_sh(); - let mut lexer = setup(&sh, "/* /* */ */'a'".to_string()); + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + let mut lexer = setup(&cm, &sh, "/* /* */ */'a'".to_string()); match lexer.next_token().tok { token::Comment => { }, _ => panic!("expected a comment!") @@ -1588,8 +1611,9 @@ mod tests { } #[test] fn crlf_comments() { - let sh = mk_sh(); - let mut lexer = setup(&sh, "// test\r\n/// test\r\n".to_string()); + let cm = Rc::new(CodeMap::new()); + let sh = mk_sh(cm.clone()); + let mut lexer = setup(&cm, &sh, "// test\r\n/// test\r\n".to_string()); let comment = lexer.next_token(); assert_eq!(comment.tok, token::Comment); assert_eq!(comment.sp, ::codemap::mk_sp(BytePos(0), BytePos(7))); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index f4dd621c97ecd..01dc9662588bf 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -39,7 +39,7 @@ use syntax::parse::token::intern; macro_rules! panictry { ($e:expr) => ({ use std::result::Result::{Ok, Err}; - use syntax::diagnostic::FatalError; + use syntax::errors::FatalError; match $e { Ok(e) => e, Err(FatalError) => panic!(FatalError) diff --git a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs index e40abe0502333..7c1a45d020b22 100644 --- a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs @@ -44,7 +44,7 @@ fn with_error_checking_parse(s: String, f: F) -> PResult where let mut p = string_to_parser(&ps, s); let x = f(&mut p); - if ps.span_diagnostic.handler().has_errors() || p.token != token::Eof { + if ps.span_diagnostic.has_errors() || p.token != token::Eof { return Err(p.fatal("parse error")); } diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 8850f6e6d2a6e..e3eeeb8635688 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -23,7 +23,7 @@ extern crate syntax; use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; -use syntax::{diagnostics, diagnostic}; +use syntax::{diagnostics, errors}; use std::path::PathBuf; @@ -35,7 +35,7 @@ impl<'a> CompilerCalls<'a> for TestCalls { fn early_callback(&mut self, _: &getopts::Matches, _: &diagnostics::registry::Registry, - _: diagnostic::ColorConfig) + _: errors::emitter::ColorConfig) -> Compilation { self.count *= 2; Compilation::Continue From ccb218616b1f07724ddf46841ac83882e06bc73d Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Thu, 17 Dec 2015 00:36:31 -0500 Subject: [PATCH 08/13] Trivial cleanup Remove a needless variable and simply a cfg(). --- src/libstd/rand/os.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index d1bd013e67b79..c4f59d51f5dad 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -42,7 +42,7 @@ mod imp { const NR_GETRANDOM: libc::c_long = 355; #[cfg(any(target_arch = "arm", target_arch = "powerpc"))] const NR_GETRANDOM: libc::c_long = 384; - #[cfg(any(target_arch = "aarch64"))] + #[cfg(target_arch = "aarch64")] const NR_GETRANDOM: libc::c_long = 278; unsafe { @@ -60,8 +60,7 @@ mod imp { fn getrandom_fill_bytes(v: &mut [u8]) { let mut read = 0; - let len = v.len(); - while read < len { + while read < v.len() { let result = getrandom(&mut v[read..]); if result == -1 { let err = errno() as libc::c_int; From 09d4a436a748a39f13d2d6d6c6ba56a885bb0d0c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 16 Dec 2015 20:58:26 +0300 Subject: [PATCH 09/13] libsyntax: Merge OwnedSlice into ptr::P --- src/libsyntax/owned_slice.rs | 99 +------------------------------- src/libsyntax/ptr.rs | 106 +++++++++++++++++++++++++++++------ 2 files changed, 90 insertions(+), 115 deletions(-) diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 83369689a94de..820c7e7e4a663 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -8,100 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::default::Default; -use std::fmt; -use std::iter::{IntoIterator, FromIterator}; -use std::ops::Deref; -use std::slice; -use std::vec; -use serialize::{Encodable, Decodable, Encoder, Decoder}; - -/// A non-growable owned slice. This is a separate type to allow the -/// representation to change. -#[derive(Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct OwnedSlice { - data: Box<[T]> -} - -impl fmt::Debug for OwnedSlice { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - self.data.fmt(fmt) - } -} - -impl OwnedSlice { - pub fn empty() -> OwnedSlice { - OwnedSlice { data: Box::new([]) } - } - - #[inline(never)] - pub fn from_vec(v: Vec) -> OwnedSlice { - OwnedSlice { data: v.into_boxed_slice() } - } - - #[inline(never)] - pub fn into_vec(self) -> Vec { - self.data.into_vec() - } - - pub fn as_slice<'a>(&'a self) -> &'a [T] { - &*self.data - } - - pub fn move_iter(self) -> vec::IntoIter { - self.into_vec().into_iter() - } - - pub fn map U>(&self, f: F) -> OwnedSlice { - self.iter().map(f).collect() - } -} - -impl Deref for OwnedSlice { - type Target = [T]; - - fn deref(&self) -> &[T] { - self.as_slice() - } -} - -impl Default for OwnedSlice { - fn default() -> OwnedSlice { - OwnedSlice::empty() - } -} - -impl Clone for OwnedSlice { - fn clone(&self) -> OwnedSlice { - OwnedSlice::from_vec(self.to_vec()) - } -} - -impl FromIterator for OwnedSlice { - fn from_iter>(iter: I) -> OwnedSlice { - OwnedSlice::from_vec(iter.into_iter().collect()) - } -} - -impl<'a, T> IntoIterator for &'a OwnedSlice { - type Item = &'a T; - type IntoIter = slice::Iter<'a, T>; - fn into_iter(self) -> Self::IntoIter { - self.data.into_iter() - } -} - -impl Encodable for OwnedSlice { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - Encodable::encode(&**self, s) - } -} - -impl Decodable for OwnedSlice { - fn decode(d: &mut D) -> Result, D::Error> { - Ok(OwnedSlice::from_vec(match Decodable::decode(d) { - Ok(t) => t, - Err(e) => return Err(e) - })) - } -} +/// A non-growable owned slice. +pub type OwnedSlice = ::ptr::P<[T]>; diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 83e321f110c58..1be0b08086d9c 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -37,14 +37,15 @@ //! Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated. use std::fmt::{self, Display, Debug}; -use std::hash::{Hash, Hasher}; +use std::iter::FromIterator; use std::ops::Deref; -use std::ptr; +use std::{ptr, slice, vec}; use serialize::{Encodable, Decodable, Encoder, Decoder}; /// An owned smart pointer. -pub struct P { +#[derive(Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct P { ptr: Box } @@ -92,14 +93,6 @@ impl Clone for P { } } -impl PartialEq for P { - fn eq(&self, other: &P) -> bool { - **self == **other - } -} - -impl Eq for P {} - impl Debug for P { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&**self, f) @@ -111,19 +104,12 @@ impl Display for P { } } -#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Pointer for P { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.ptr, f) } } -impl Hash for P { - fn hash(&self, state: &mut H) { - (**self).hash(state); - } -} - impl Decodable for P { fn decode(d: &mut D) -> Result, D::Error> { Decodable::decode(d).map(P) @@ -135,3 +121,87 @@ impl Encodable for P { (**self).encode(s) } } + + +impl fmt::Debug for P<[T]> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + self.ptr.fmt(fmt) + } +} + +impl P<[T]> { + pub fn empty() -> P<[T]> { + P { ptr: Default::default() } + } + + #[inline(never)] + pub fn from_vec(v: Vec) -> P<[T]> { + P { ptr: v.into_boxed_slice() } + } + + #[inline(never)] + pub fn into_vec(self) -> Vec { + self.ptr.into_vec() + } + + pub fn as_slice<'a>(&'a self) -> &'a [T] { + &*self.ptr + } + + pub fn move_iter(self) -> vec::IntoIter { + self.into_vec().into_iter() + } + + pub fn map U>(&self, f: F) -> P<[U]> { + self.iter().map(f).collect() + } +} + +impl Deref for P<[T]> { + type Target = [T]; + + fn deref(&self) -> &[T] { + self.as_slice() + } +} + +impl Default for P<[T]> { + fn default() -> P<[T]> { + P::empty() + } +} + +impl Clone for P<[T]> { + fn clone(&self) -> P<[T]> { + P::from_vec(self.to_vec()) + } +} + +impl FromIterator for P<[T]> { + fn from_iter>(iter: I) -> P<[T]> { + P::from_vec(iter.into_iter().collect()) + } +} + +impl<'a, T> IntoIterator for &'a P<[T]> { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + fn into_iter(self) -> Self::IntoIter { + self.ptr.into_iter() + } +} + +impl Encodable for P<[T]> { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + Encodable::encode(&**self, s) + } +} + +impl Decodable for P<[T]> { + fn decode(d: &mut D) -> Result, D::Error> { + Ok(P::from_vec(match Decodable::decode(d) { + Ok(t) => t, + Err(e) => return Err(e) + })) + } +} From 0d298f9904468b8f668cb9b505c19d64fdeb7633 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 16 Dec 2015 21:44:33 +0300 Subject: [PATCH 10/13] Deprecate name `OwnedSlice` and don't use it --- src/librustc/middle/infer/error_reporting.rs | 11 +++---- src/librustc/middle/ty/structural_impls.rs | 6 ++-- src/librustc_front/fold.rs | 17 +++++----- src/librustc_front/hir.rs | 15 +++++---- src/librustc_front/lowering.rs | 13 ++++---- src/librustc_front/print/pprust.rs | 5 ++- src/librustc_front/util.rs | 7 ++--- src/librustc_trans/save/dump_csv.rs | 3 +- src/librustc_typeck/check/mod.rs | 3 +- src/librustdoc/clean/mod.rs | 2 +- src/libsyntax/ast.rs | 17 +++++----- src/libsyntax/ast_util.rs | 5 ++- src/libsyntax/ext/build.rs | 25 +++++++-------- src/libsyntax/fold.rs | 19 ++++++----- src/libsyntax/owned_slice.rs | 2 ++ src/libsyntax/parse/mod.rs | 3 +- src/libsyntax/parse/parser.rs | 33 ++++++++++---------- src/libsyntax/print/pprust.rs | 5 ++- src/libsyntax/test.rs | 1 - src/libsyntax/util/move_map.rs | 6 ++-- src/libsyntax_ext/deriving/generic/mod.rs | 9 +++--- src/libsyntax_ext/deriving/generic/ty.rs | 3 +- 22 files changed, 96 insertions(+), 114 deletions(-) diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index e894878e43ce1..d5ecb3f2e863f 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -90,7 +90,6 @@ use std::cell::{Cell, RefCell}; use std::char::from_u32; use std::fmt; use syntax::ast; -use syntax::owned_slice::OwnedSlice; use syntax::codemap::{self, Pos, Span}; use syntax::parse::token; use syntax::ptr::P; @@ -1154,10 +1153,10 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } fn rebuild_ty_params(&self, - ty_params: OwnedSlice, + ty_params: P<[hir::TyParam]>, lifetime: hir::Lifetime, region_names: &HashSet) - -> OwnedSlice { + -> P<[hir::TyParam]> { ty_params.map(|ty_param| { let bounds = self.rebuild_ty_param_bounds(ty_param.bounds.clone(), lifetime, @@ -1173,10 +1172,10 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } fn rebuild_ty_param_bounds(&self, - ty_param_bounds: OwnedSlice, + ty_param_bounds: hir::TyParamBounds, lifetime: hir::Lifetime, region_names: &HashSet) - -> OwnedSlice { + -> hir::TyParamBounds { ty_param_bounds.map(|tpb| { match tpb { &hir::RegionTyParamBound(lt) => { @@ -1249,7 +1248,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { add: &Vec, keep: &HashSet, remove: &HashSet, - ty_params: OwnedSlice, + ty_params: P<[hir::TyParam]>, where_clause: hir::WhereClause) -> hir::Generics { let mut lifetimes = Vec::new(); diff --git a/src/librustc/middle/ty/structural_impls.rs b/src/librustc/middle/ty/structural_impls.rs index e6007809af5e9..ecb2b85fd7744 100644 --- a/src/librustc/middle/ty/structural_impls.rs +++ b/src/librustc/middle/ty/structural_impls.rs @@ -16,7 +16,7 @@ use middle::ty::fold::{TypeFoldable, TypeFolder}; use std::rc::Rc; use syntax::abi; -use syntax::owned_slice::OwnedSlice; +use syntax::ptr::P; use rustc_front::hir; @@ -555,8 +555,8 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for OwnedSlice { - fn fold_with>(&self, folder: &mut F) -> OwnedSlice { +impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for P<[T]> { + fn fold_with>(&self, folder: &mut F) -> P<[T]> { self.iter().map(|t| t.fold_with(folder)).collect() } } diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index 88a34b27c3189..0978c3f78e82f 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -17,7 +17,6 @@ use syntax::ast::{MetaWord, MetaList, MetaNameValue}; use syntax::attr::ThinAttributesExt; use hir; use syntax::codemap::{respan, Span, Spanned}; -use syntax::owned_slice::OwnedSlice; use syntax::ptr::P; use syntax::parse::token; use syntax::util::move_map::MoveMap; @@ -211,7 +210,7 @@ pub trait Folder : Sized { noop_fold_ty_param(tp, self) } - fn fold_ty_params(&mut self, tps: OwnedSlice) -> OwnedSlice { + fn fold_ty_params(&mut self, tps: P<[TyParam]>) -> P<[TyParam]> { noop_fold_ty_params(tps, self) } @@ -220,12 +219,12 @@ pub trait Folder : Sized { } fn fold_opt_bounds(&mut self, - b: Option>) - -> Option> { + b: Option) + -> Option { noop_fold_opt_bounds(b, self) } - fn fold_bounds(&mut self, b: OwnedSlice) -> OwnedSlice { + fn fold_bounds(&mut self, b: TyParamBounds) -> TyParamBounds { noop_fold_bounds(b, self) } @@ -576,9 +575,9 @@ pub fn noop_fold_ty_param(tp: TyParam, fld: &mut T) -> TyParam { } } -pub fn noop_fold_ty_params(tps: OwnedSlice, +pub fn noop_fold_ty_params(tps: P<[TyParam]>, fld: &mut T) - -> OwnedSlice { + -> P<[TyParam]> { tps.move_map(|tp| fld.fold_ty_param(tp)) } @@ -726,9 +725,9 @@ pub fn noop_fold_mt(MutTy { ty, mutbl }: MutTy, folder: &mut T) -> Mu } } -pub fn noop_fold_opt_bounds(b: Option>, +pub fn noop_fold_opt_bounds(b: Option, folder: &mut T) - -> Option> { + -> Option { b.map(|bounds| folder.fold_bounds(bounds)) } diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index d1cb82dbeccbc..1491ecc89af1f 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -42,7 +42,6 @@ use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, CrateConfig}; use syntax::attr::ThinAttributes; -use syntax::owned_slice::OwnedSlice; use syntax::parse::token::InternedString; use syntax::ptr::P; @@ -193,8 +192,8 @@ impl PathParameters { pub fn none() -> PathParameters { AngleBracketedParameters(AngleBracketedParameterData { lifetimes: Vec::new(), - types: OwnedSlice::empty(), - bindings: OwnedSlice::empty(), + types: P::empty(), + bindings: P::empty(), }) } @@ -267,10 +266,10 @@ pub struct AngleBracketedParameterData { /// The lifetime parameters for this path segment. pub lifetimes: Vec, /// The type parameters for this path segment, if present. - pub types: OwnedSlice>, + pub types: P<[P]>, /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo`. - pub bindings: OwnedSlice, + pub bindings: P<[TypeBinding]>, } impl AngleBracketedParameterData { @@ -310,7 +309,7 @@ pub enum TraitBoundModifier { Maybe, } -pub type TyParamBounds = OwnedSlice; +pub type TyParamBounds = P<[TyParamBound]>; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct TyParam { @@ -326,7 +325,7 @@ pub struct TyParam { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Generics { pub lifetimes: Vec, - pub ty_params: OwnedSlice, + pub ty_params: P<[TyParam]>, pub where_clause: WhereClause, } @@ -369,7 +368,7 @@ pub struct WhereBoundPredicate { /// The type being bounded pub bounded_ty: P, /// Trait and lifetime bounds (`Clone+Send+'static`) - pub bounds: OwnedSlice, + pub bounds: TyParamBounds, } /// A lifetime predicate, e.g. `'a: 'b+'c` diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index c0b10fb89124a..614f6f0bd36dd 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -70,7 +70,6 @@ use syntax::attr::{ThinAttributes, ThinAttributesExt}; use syntax::ext::mtwt; use syntax::ptr::P; use syntax::codemap::{respan, Spanned, Span}; -use syntax::owned_slice::OwnedSlice; use syntax::parse::token; use syntax::std_inject; use syntax::visit::{self, Visitor}; @@ -430,8 +429,8 @@ pub fn lower_ty_param(lctx: &LoweringContext, tp: &TyParam) -> hir::TyParam { } pub fn lower_ty_params(lctx: &LoweringContext, - tps: &OwnedSlice) - -> OwnedSlice { + tps: &P<[TyParam]>) + -> P<[hir::TyParam]> { tps.iter().map(|tp| lower_ty_param(lctx, tp)).collect() } @@ -583,8 +582,8 @@ pub fn lower_mt(lctx: &LoweringContext, mt: &MutTy) -> hir::MutTy { } pub fn lower_opt_bounds(lctx: &LoweringContext, - b: &Option>) - -> Option> { + b: &Option) + -> Option { b.as_ref().map(|ref bounds| lower_bounds(lctx, bounds)) } @@ -1795,8 +1794,8 @@ fn path_all(sp: Span, identifier: last_identifier, parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { lifetimes: lifetimes, - types: OwnedSlice::from_vec(types), - bindings: OwnedSlice::from_vec(bindings), + types: P::from_vec(types), + bindings: P::from_vec(bindings), }), }); hir::Path { diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index 81076b6e40276..a3bb005dfbdca 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -12,7 +12,6 @@ pub use self::AnnNode::*; use syntax::abi; use syntax::ast; -use syntax::owned_slice::OwnedSlice; use syntax::codemap::{self, CodeMap, BytePos, Spanned}; use syntax::diagnostic; use syntax::parse::token::{self, BinOpToken}; @@ -519,7 +518,7 @@ impl<'a> State<'a> { hir::TyBareFn(ref f) => { let generics = hir::Generics { lifetimes: f.lifetimes.clone(), - ty_params: OwnedSlice::empty(), + ty_params: P::empty(), where_clause: hir::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), @@ -2258,7 +2257,7 @@ impl<'a> State<'a> { } let generics = hir::Generics { lifetimes: Vec::new(), - ty_params: OwnedSlice::empty(), + ty_params: P::empty(), where_clause: hir::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), diff --git a/src/librustc_front/util.rs b/src/librustc_front/util.rs index 4dc08f7a0485a..f85eb2bb4011e 100644 --- a/src/librustc_front/util.rs +++ b/src/librustc_front/util.rs @@ -15,7 +15,6 @@ use syntax::ast_util; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID}; use syntax::codemap::Span; use syntax::ptr::P; -use syntax::owned_slice::OwnedSlice; pub fn walk_pat(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool @@ -336,7 +335,7 @@ pub fn is_path(e: P) -> bool { pub fn empty_generics() -> Generics { Generics { lifetimes: Vec::new(), - ty_params: OwnedSlice::empty(), + ty_params: P::empty(), where_clause: WhereClause { id: DUMMY_NODE_ID, predicates: Vec::new(), @@ -354,8 +353,8 @@ pub fn ident_to_path(s: Span, ident: Ident) -> Path { identifier: ident, parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { lifetimes: Vec::new(), - types: OwnedSlice::empty(), - bindings: OwnedSlice::empty(), + types: P::empty(), + bindings: P::empty(), }), }), } diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 747b76ae57f1e..9c6b54e13796d 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -41,7 +41,6 @@ use std::fs::File; use syntax::ast::{self, NodeId}; use syntax::codemap::*; use syntax::parse::token::{self, keywords}; -use syntax::owned_slice::OwnedSlice; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{path_to_string, ty_to_string}; use syntax::ptr::P; @@ -572,7 +571,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { fn process_trait(&mut self, item: &ast::Item, generics: &ast::Generics, - trait_refs: &OwnedSlice, + trait_refs: &ast::TyParamBounds, methods: &[P]) { let qualname = format!("::{}", self.tcx.map.path_to_string(item.id)); let val = self.span.snippet(item.span); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9f453362d24bd..bddf0e9ffb0cb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -119,7 +119,6 @@ use syntax::ast; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::codemap::{self, Span, Spanned}; -use syntax::owned_slice::OwnedSlice; use syntax::parse::token::{self, InternedString}; use syntax::ptr::P; use syntax::util::lev_distance::lev_distance; @@ -4907,7 +4906,7 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &hir::Block) -> bool { } pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - tps: &OwnedSlice, + tps: &P<[hir::TyParam]>, ty: Ty<'tcx>) { debug!("check_bounds_are_used(n_tps={}, ty={:?})", tps.len(), ty); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 52eeb781b31cc..e217e7afad737 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -112,7 +112,7 @@ impl Clean for ty::Binder where T: Clean { } } -impl, U> Clean> for syntax::owned_slice::OwnedSlice { +impl, U> Clean> for P<[T]> { fn clean(&self, cx: &DocContext) -> Vec { self.iter().map(|x| x.clean(cx)).collect() } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index de5595eebee71..4b0ec8578c12e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -50,7 +50,6 @@ use codemap::{Span, Spanned, DUMMY_SP, ExpnId}; use abi::Abi; use ext::base; use ext::tt::macro_parser; -use owned_slice::OwnedSlice; use parse::token::InternedString; use parse::token; use parse::lexer; @@ -261,8 +260,8 @@ impl PathParameters { pub fn none() -> PathParameters { AngleBracketedParameters(AngleBracketedParameterData { lifetimes: Vec::new(), - types: OwnedSlice::empty(), - bindings: OwnedSlice::empty(), + types: P::empty(), + bindings: P::empty(), }) } @@ -334,10 +333,10 @@ pub struct AngleBracketedParameterData { /// The lifetime parameters for this path segment. pub lifetimes: Vec, /// The type parameters for this path segment, if present. - pub types: OwnedSlice>, + pub types: P<[P]>, /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo`. - pub bindings: OwnedSlice>, + pub bindings: P<[P]>, } impl AngleBracketedParameterData { @@ -394,7 +393,7 @@ pub enum TraitBoundModifier { Maybe, } -pub type TyParamBounds = OwnedSlice; +pub type TyParamBounds = P<[TyParamBound]>; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct TyParam { @@ -410,7 +409,7 @@ pub struct TyParam { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Generics { pub lifetimes: Vec, - pub ty_params: OwnedSlice, + pub ty_params: P<[TyParam]>, pub where_clause: WhereClause, } @@ -430,7 +429,7 @@ impl Default for Generics { fn default() -> Generics { Generics { lifetimes: Vec::new(), - ty_params: OwnedSlice::empty(), + ty_params: P::empty(), where_clause: WhereClause { id: DUMMY_NODE_ID, predicates: Vec::new(), @@ -466,7 +465,7 @@ pub struct WhereBoundPredicate { /// The type being bounded pub bounded_ty: P, /// Trait and lifetime bounds (`Clone+Send+'static`) - pub bounds: OwnedSlice, + pub bounds: TyParamBounds, } /// A lifetime predicate, e.g. `'a: 'b+'c` diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 3d3d53477494d..d38b771814c28 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -12,7 +12,6 @@ use ast::*; use ast; use codemap; use codemap::Span; -use owned_slice::OwnedSlice; use parse::token; use print::pprust; use ptr::P; @@ -43,8 +42,8 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path { identifier: identifier, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: Vec::new(), - types: OwnedSlice::empty(), - bindings: OwnedSlice::empty(), + types: P::empty(), + bindings: P::empty(), }) } ), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index cdc9cb024530d..46a39b98058a2 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -14,7 +14,6 @@ use ast; use attr; use codemap::{Span, respan, Spanned, DUMMY_SP, Pos}; use ext::base::ExtCtxt; -use owned_slice::OwnedSlice; use parse::token::special_idents; use parse::token::InternedString; use parse::token; @@ -56,7 +55,7 @@ pub trait AstBuilder { fn ty(&self, span: Span, ty: ast::Ty_) -> P; fn ty_path(&self, ast::Path) -> P; - fn ty_sum(&self, ast::Path, OwnedSlice) -> P; + fn ty_sum(&self, ast::Path, ast::TyParamBounds) -> P; fn ty_ident(&self, span: Span, idents: ast::Ident) -> P; fn ty_rptr(&self, span: Span, @@ -70,13 +69,13 @@ pub trait AstBuilder { fn ty_option(&self, ty: P) -> P; fn ty_infer(&self, sp: Span) -> P; - fn ty_vars(&self, ty_params: &OwnedSlice) -> Vec> ; - fn ty_vars_global(&self, ty_params: &OwnedSlice) -> Vec> ; + fn ty_vars(&self, ty_params: &P<[ast::TyParam]>) -> Vec> ; + fn ty_vars_global(&self, ty_params: &P<[ast::TyParam]>) -> Vec> ; fn typaram(&self, span: Span, id: ast::Ident, - bounds: OwnedSlice, + bounds: ast::TyParamBounds, default: Option>) -> ast::TyParam; fn trait_ref(&self, path: ast::Path) -> ast::TraitRef; @@ -331,8 +330,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { identifier: last_identifier, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, - types: OwnedSlice::from_vec(types), - bindings: OwnedSlice::from_vec(bindings), + types: P::from_vec(types), + bindings: P::from_vec(bindings), }) }); ast::Path { @@ -369,8 +368,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { identifier: ident, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, - types: OwnedSlice::from_vec(types), - bindings: OwnedSlice::from_vec(bindings), + types: P::from_vec(types), + bindings: P::from_vec(bindings), }) }); @@ -399,7 +398,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.ty(path.span, ast::TyPath(None, path)) } - fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice) -> P { + fn ty_sum(&self, path: ast::Path, bounds: ast::TyParamBounds) -> P { self.ty(path.span, ast::TyObjectSum(self.ty_path(path), bounds)) @@ -448,7 +447,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn typaram(&self, span: Span, id: ast::Ident, - bounds: OwnedSlice, + bounds: ast::TyParamBounds, default: Option>) -> ast::TyParam { ast::TyParam { ident: id, @@ -462,11 +461,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> { // these are strange, and probably shouldn't be used outside of // pipes. Specifically, the global version possible generates // incorrect code. - fn ty_vars(&self, ty_params: &OwnedSlice) -> Vec> { + fn ty_vars(&self, ty_params: &P<[ast::TyParam]>) -> Vec> { ty_params.iter().map(|p| self.ty_ident(DUMMY_SP, p.ident)).collect() } - fn ty_vars_global(&self, ty_params: &OwnedSlice) -> Vec> { + fn ty_vars_global(&self, ty_params: &P<[ast::TyParam]>) -> Vec> { ty_params .iter() .map(|p| self.ty_path(self.path_global(DUMMY_SP, vec!(p.ident)))) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index cd976884d2fad..cd2210c71b895 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -23,7 +23,6 @@ use ast; use attr::{ThinAttributes, ThinAttributesExt}; use ast_util; use codemap::{respan, Span, Spanned}; -use owned_slice::OwnedSlice; use parse::token; use ptr::P; use util::small_vector::SmallVector; @@ -233,7 +232,7 @@ pub trait Folder : Sized { noop_fold_ty_param(tp, self) } - fn fold_ty_params(&mut self, tps: OwnedSlice) -> OwnedSlice { + fn fold_ty_params(&mut self, tps: P<[TyParam]>) -> P<[TyParam]> { noop_fold_ty_params(tps, self) } @@ -257,13 +256,13 @@ pub trait Folder : Sized { noop_fold_opt_lifetime(o_lt, self) } - fn fold_opt_bounds(&mut self, b: Option>) - -> Option> { + fn fold_opt_bounds(&mut self, b: Option) + -> Option { noop_fold_opt_bounds(b, self) } - fn fold_bounds(&mut self, b: OwnedSlice) - -> OwnedSlice { + fn fold_bounds(&mut self, b: TyParamBounds) + -> TyParamBounds { noop_fold_bounds(b, self) } @@ -714,8 +713,8 @@ pub fn noop_fold_ty_param(tp: TyParam, fld: &mut T) -> TyParam { } } -pub fn noop_fold_ty_params(tps: OwnedSlice, fld: &mut T) - -> OwnedSlice { +pub fn noop_fold_ty_params(tps: P<[TyParam]>, fld: &mut T) + -> P<[TyParam]> { tps.move_map(|tp| fld.fold_ty_param(tp)) } @@ -871,8 +870,8 @@ pub fn noop_fold_mt(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutT } } -pub fn noop_fold_opt_bounds(b: Option>, folder: &mut T) - -> Option> { +pub fn noop_fold_opt_bounds(b: Option, folder: &mut T) + -> Option { b.map(|bounds| folder.fold_bounds(bounds)) } diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 820c7e7e4a663..33a3d5785981a 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -9,4 +9,6 @@ // except according to those terms. /// A non-growable owned slice. +#[unstable(feature = "rustc_private", issue = "0")] +#[rustc_deprecated(since = "1.7.0", reason = "use `ptr::P<[T]>` instead")] pub type OwnedSlice = ::ptr::P<[T]>; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index e9c8173a4d980..df2a9f30c7acf 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -668,7 +668,6 @@ mod tests { use super::*; use std::rc::Rc; use codemap::{Span, BytePos, Pos, Spanned, NO_EXPANSION}; - use owned_slice::OwnedSlice; use ast::{self, TokenTree}; use abi; use attr::{first_attr_value_str_by_name, AttrMetaMethods}; @@ -944,7 +943,7 @@ mod tests { abi::Rust, ast::Generics{ // no idea on either of these: lifetimes: Vec::new(), - ty_params: OwnedSlice::empty(), + ty_params: P::empty(), where_clause: ast::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 712f4e3801275..8cf8533c3aaaa 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -50,7 +50,7 @@ use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; use ast::{Ty, Ty_, TypeBinding, TyMac}; use ast::{TyFixedLengthVec, TyBareFn, TyTypeof, TyInfer}; -use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPtr}; +use ast::{TyParam, TyParamBounds, TyParen, TyPath, TyPtr}; use ast::{TyRptr, TyTup, TyU32, TyVec}; use ast::TypeTraitItem; use ast::{UnnamedField, UnsafeBlock}; @@ -73,7 +73,6 @@ use parse::{new_sub_parser_from_file, ParseSess}; use util::parser::{AssocOp, Fixity}; use print::pprust; use ptr::P; -use owned_slice::OwnedSlice; use parse::PResult; use diagnostic::FatalError; @@ -752,7 +751,7 @@ impl<'a> Parser<'a> { pub fn parse_seq_to_before_gt_or_return(&mut self, sep: Option, mut f: F) - -> PResult<(OwnedSlice, bool)> where + -> PResult<(P<[T]>, bool)> where F: FnMut(&mut Parser) -> PResult>, { let mut v = Vec::new(); @@ -773,7 +772,7 @@ impl<'a> Parser<'a> { if i % 2 == 0 { match try!(f(self)) { Some(result) => v.push(result), - None => return Ok((OwnedSlice::from_vec(v), true)) + None => return Ok((P::from_vec(v), true)) } } else { if let Some(t) = sep.as_ref() { @@ -782,7 +781,7 @@ impl<'a> Parser<'a> { } } - return Ok((OwnedSlice::from_vec(v), false)); + return Ok((P::from_vec(v), false)); } /// Parse a sequence bracketed by '<' and '>', stopping @@ -790,7 +789,7 @@ impl<'a> Parser<'a> { pub fn parse_seq_to_before_gt(&mut self, sep: Option, mut f: F) - -> PResult> where + -> PResult> where F: FnMut(&mut Parser) -> PResult, { let (result, returned) = try!(self.parse_seq_to_before_gt_or_return(sep, @@ -802,7 +801,7 @@ impl<'a> Parser<'a> { pub fn parse_seq_to_gt(&mut self, sep: Option, f: F) - -> PResult> where + -> PResult> where F: FnMut(&mut Parser) -> PResult, { let v = try!(self.parse_seq_to_before_gt(sep, f)); @@ -813,7 +812,7 @@ impl<'a> Parser<'a> { pub fn parse_seq_to_gt_or_return(&mut self, sep: Option, f: F) - -> PResult<(OwnedSlice, bool)> where + -> PResult<(P<[T]>, bool)> where F: FnMut(&mut Parser) -> PResult>, { let (v, returned) = try!(self.parse_seq_to_before_gt_or_return(sep, f)); @@ -1077,7 +1076,7 @@ impl<'a> Parser<'a> { let other_bounds = if try!(self.eat(&token::BinOp(token::Plus)) ){ try!(self.parse_ty_param_bounds(BoundParsingMode::Bare)) } else { - OwnedSlice::empty() + P::empty() }; let all_bounds = Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter() @@ -1710,8 +1709,8 @@ impl<'a> Parser<'a> { ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, - types: OwnedSlice::from_vec(types), - bindings: OwnedSlice::from_vec(bindings), + types: P::from_vec(types), + bindings: P::from_vec(bindings), }) } else if try!(self.eat(&token::OpenDelim(token::Paren)) ){ let lo = self.last_span.lo; @@ -1774,8 +1773,8 @@ impl<'a> Parser<'a> { identifier: identifier, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, - types: OwnedSlice::from_vec(types), - bindings: OwnedSlice::from_vec(bindings), + types: P::from_vec(types), + bindings: P::from_vec(bindings), }), }); @@ -3883,10 +3882,10 @@ impl<'a> Parser<'a> { // otherwise returns empty list. fn parse_colon_then_ty_param_bounds(&mut self, mode: BoundParsingMode) - -> PResult> + -> PResult { if !try!(self.eat(&token::Colon) ){ - Ok(OwnedSlice::empty()) + Ok(P::empty()) } else { self.parse_ty_param_bounds(mode) } @@ -3898,7 +3897,7 @@ impl<'a> Parser<'a> { // and bound = 'region | trait_ref fn parse_ty_param_bounds(&mut self, mode: BoundParsingMode) - -> PResult> + -> PResult { let mut result = vec!(); loop { @@ -3940,7 +3939,7 @@ impl<'a> Parser<'a> { } } - return Ok(OwnedSlice::from_vec(result)); + return Ok(P::from_vec(result)); } /// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )? diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4e2289cb7f401..457d7d150dd9c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -17,7 +17,6 @@ use ast::Attribute; use attr::ThinAttributesExt; use util::parser::AssocOp; use attr; -use owned_slice::OwnedSlice; use attr::{AttrMetaMethods, AttributeMethods}; use codemap::{self, CodeMap, BytePos}; use diagnostic; @@ -1001,7 +1000,7 @@ impl<'a> State<'a> { ast::TyBareFn(ref f) => { let generics = ast::Generics { lifetimes: f.lifetimes.clone(), - ty_params: OwnedSlice::empty(), + ty_params: P::empty(), where_clause: ast::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), @@ -3024,7 +3023,7 @@ impl<'a> State<'a> { } let generics = ast::Generics { lifetimes: Vec::new(), - ty_params: OwnedSlice::empty(), + ty_params: P::empty(), where_clause: ast::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 63fbe284a09fd..e9581b9e05c57 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -32,7 +32,6 @@ use ext::expand::ExpansionConfig; use fold::Folder; use util::move_map::MoveMap; use fold; -use owned_slice::OwnedSlice; use parse::token::{intern, InternedString}; use parse::{token, ParseSess}; use print::pprust; diff --git a/src/libsyntax/util/move_map.rs b/src/libsyntax/util/move_map.rs index 95c24c66630f0..e1078b719bf06 100644 --- a/src/libsyntax/util/move_map.rs +++ b/src/libsyntax/util/move_map.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use owned_slice::OwnedSlice; - use std::ptr; pub trait MoveMap: Sized { @@ -69,11 +67,11 @@ impl MoveMap for Vec { } } -impl MoveMap for OwnedSlice { +impl MoveMap for ::ptr::P<[T]> { fn move_flat_map(self, f: F) -> Self where F: FnMut(T) -> I, I: IntoIterator { - OwnedSlice::from_vec(self.into_vec().move_flat_map(f)) + ::ptr::P::from_vec(self.into_vec().move_flat_map(f)) } } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 5977144dae708..852458422685b 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -205,7 +205,6 @@ use syntax::codemap::{self, DUMMY_SP}; use syntax::codemap::Span; use syntax::diagnostic::SpanHandler; use syntax::util::move_map::MoveMap; -use syntax::owned_slice::OwnedSlice; use syntax::parse::token::{intern, InternedString}; use syntax::parse::token::special_idents; use syntax::ptr::P; @@ -516,7 +515,7 @@ impl<'a> TraitDef<'a> { cx.typaram(self.span, ty_param.ident, - OwnedSlice::from_vec(bounds), + P::from_vec(bounds), None) })); @@ -528,7 +527,7 @@ impl<'a> TraitDef<'a> { span: self.span, bound_lifetimes: wb.bound_lifetimes.clone(), bounded_ty: wb.bounded_ty.clone(), - bounds: OwnedSlice::from_vec(wb.bounds.iter().cloned().collect()) + bounds: P::from_vec(wb.bounds.iter().cloned().collect()) }) } ast::WherePredicate::RegionPredicate(ref rb) => { @@ -579,7 +578,7 @@ impl<'a> TraitDef<'a> { span: self.span, bound_lifetimes: vec![], bounded_ty: ty, - bounds: OwnedSlice::from_vec(bounds), + bounds: P::from_vec(bounds), }; let predicate = ast::WherePredicate::BoundPredicate(predicate); @@ -590,7 +589,7 @@ impl<'a> TraitDef<'a> { let trait_generics = Generics { lifetimes: lifetimes, - ty_params: OwnedSlice::from_vec(ty_params), + ty_params: P::from_vec(ty_params), where_clause: where_clause }; diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 0c4a81361aef2..10564b5f6985b 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -19,7 +19,6 @@ use syntax::ast::{Expr,Generics,Ident}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::codemap::{Span,respan}; -use syntax::owned_slice::OwnedSlice; use syntax::parse::token::special_idents; use syntax::ptr::P; @@ -209,7 +208,7 @@ fn mk_generics(lifetimes: Vec, ty_params: Vec) -> Generics { Generics { lifetimes: lifetimes, - ty_params: OwnedSlice::from_vec(ty_params), + ty_params: P::from_vec(ty_params), where_clause: ast::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), From 6c87b191580be9ecd5a99a34ef97375af0b9d659 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 17 Dec 2015 20:41:28 +0300 Subject: [PATCH 11/13] Abstract away differences between Vec and ptr::P in HIR --- src/librustc/middle/check_match.rs | 8 +- src/librustc/middle/const_eval.rs | 4 +- src/librustc/middle/expr_use_visitor.rs | 6 +- src/librustc/middle/infer/error_reporting.rs | 12 +- src/librustc/middle/resolve_lifetime.rs | 10 +- src/librustc/middle/stability.rs | 2 +- src/librustc_front/fold.rs | 22 ++-- src/librustc_front/hir.rs | 132 +++++++++++-------- src/librustc_front/lib.rs | 1 + src/librustc_front/lowering.rs | 118 +++++++++-------- src/librustc_front/print/pprust.rs | 6 +- src/librustc_front/util.rs | 10 +- src/librustc_mir/hair/cx/pattern.rs | 6 +- src/librustc_trans/trans/consts.rs | 2 +- src/librustdoc/clean/mod.rs | 9 +- src/librustdoc/doctree.rs | 42 +++--- src/librustdoc/visit_ast.rs | 8 +- 17 files changed, 214 insertions(+), 184 deletions(-) diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index ba4bdccb20b80..cab7e45ee6283 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -517,7 +517,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => { let v = adt.variant_of_ctor(ctor); if let VariantKind::Struct = v.kind() { - let field_pats: Vec<_> = v.fields.iter() + let field_pats: hir::HirVec<_> = v.fields.iter() .zip(pats) .filter(|&(_, ref pat)| pat.node != hir::PatWild) .map(|(field, pat)| Spanned { @@ -540,14 +540,14 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, ty::TyArray(_, n) => match ctor { &Single => { assert_eq!(pats_len, n); - hir::PatVec(pats.collect(), None, vec!()) + hir::PatVec(pats.collect(), None, hir::HirVec::new()) }, _ => unreachable!() }, ty::TySlice(_) => match ctor { &Slice(n) => { assert_eq!(pats_len, n); - hir::PatVec(pats.collect(), None, vec!()) + hir::PatVec(pats.collect(), None, hir::HirVec::new()) }, _ => unreachable!() }, @@ -562,7 +562,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, ty::TyArray(_, len) => { assert_eq!(pats_len, len); - hir::PatVec(pats.collect(), None, vec![]) + hir::PatVec(pats.collect(), None, hir::HirVec::new()) } _ => { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index f0cfd900fd75a..fb471fb6aaa4f 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -357,14 +357,14 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P hir::ExprVec(ref exprs) => { let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect(); - hir::PatVec(pats, None, vec![]) + hir::PatVec(pats, None, hir::HirVec::new()) } hir::ExprPath(_, ref path) => { let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()); match opt_def { Some(def::DefStruct(..)) => - hir::PatStruct(path.clone(), vec![], false), + hir::PatStruct(path.clone(), hir::HirVec::new(), false), Some(def::DefVariant(..)) => hir::PatEnum(path.clone(), None), _ => { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 4861f0a6b6436..73776304bc846 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -324,7 +324,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { self.delegate.consume(consume_id, consume_span, cmt, mode); } - fn consume_exprs(&mut self, exprs: &Vec>) { + fn consume_exprs(&mut self, exprs: &[P]) { for expr in exprs { self.consume_expr(&**expr); } @@ -651,7 +651,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { fn walk_struct_expr(&mut self, _expr: &hir::Expr, - fields: &Vec, + fields: &[hir::Field], opt_with: &Option>) { // Consume the expressions supplying values for each field. for field in fields { @@ -697,7 +697,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { self.walk_expr(with_expr); fn contains_field_named(field: ty::FieldDef, - fields: &Vec) + fields: &[hir::Field]) -> bool { fields.iter().any( diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index d5ecb3f2e863f..2abf499185690 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1254,7 +1254,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { let mut lifetimes = Vec::new(); for lt in add { lifetimes.push(hir::LifetimeDef { lifetime: *lt, - bounds: Vec::new() }); + bounds: hir::HirVec::new() }); } for lt in &generics.lifetimes { if keep.contains(<.lifetime.name) || @@ -1263,7 +1263,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } } hir::Generics { - lifetimes: lifetimes, + lifetimes: lifetimes.into(), ty_params: ty_params, where_clause: where_clause, } @@ -1274,7 +1274,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { lifetime: hir::Lifetime, anon_nums: &HashSet, region_names: &HashSet) - -> Vec { + -> hir::HirVec { let mut new_inputs = Vec::new(); for arg in inputs { let new_ty = self.rebuild_arg_ty_or_output(&*arg.ty, lifetime, @@ -1286,7 +1286,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { }; new_inputs.push(possibly_new_arg); } - new_inputs + new_inputs.into() } fn rebuild_output(&self, ty: &hir::FunctionRetTy, @@ -1513,7 +1513,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } }); hir::AngleBracketedParameters(hir::AngleBracketedParameterData { - lifetimes: new_lts, + lifetimes: new_lts.into(), types: new_types, bindings: new_bindings, }) @@ -1529,7 +1529,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { hir::Path { span: path.span, global: path.global, - segments: new_segs + segments: new_segs.into() } } } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 89fa76f2fa769..9b133c5401519 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -79,10 +79,10 @@ struct LifetimeContext<'a> { enum ScopeChain<'a> { /// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound /// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc. - EarlyScope(subst::ParamSpace, &'a Vec, Scope<'a>), + EarlyScope(subst::ParamSpace, &'a [hir::LifetimeDef], Scope<'a>), /// LateScope(['a, 'b, ...], s) extends s with late-bound /// lifetimes introduced by the declaration binder_id. - LateScope(&'a Vec, Scope<'a>), + LateScope(&'a [hir::LifetimeDef], Scope<'a>), /// lifetimes introduced by a fn are scoped to the call-site for that fn. FnScope { fn_id: ast::NodeId, body_id: ast::NodeId, s: Scope<'a> }, @@ -206,7 +206,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { // a trait ref, which introduces a binding scope. match self.def_map.get(&ty.id).map(|d| (d.base_def, d.depth)) { Some((def::DefTrait(..), 0)) => { - self.with(LateScope(&Vec::new(), self.scope), |_, this| { + self.with(LateScope(&[], self.scope), |_, this| { this.visit_path(path, ty.id); }); } @@ -661,7 +661,7 @@ impl<'a> LifetimeContext<'a> { lifetime_ref.name); } - fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &Vec) { + fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &[hir::LifetimeDef]) { for i in 0..lifetimes.len() { let lifetime_i = &lifetimes[i]; @@ -753,7 +753,7 @@ impl<'a> LifetimeContext<'a> { } } -fn search_lifetimes<'a>(lifetimes: &'a Vec, +fn search_lifetimes<'a>(lifetimes: &'a [hir::LifetimeDef], lifetime_ref: &hir::Lifetime) -> Option<(u32, &'a hir::Lifetime)> { for (i, lifetime_decl) in lifetimes.iter().enumerate() { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 8104d53fc936f..a41ee51fb5546 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -82,7 +82,7 @@ struct Annotator<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { // Determine the stability for a node based on its attributes and inherited // stability. The stability is recorded in the index and used as the parent. - fn annotate(&mut self, id: NodeId, attrs: &Vec, + fn annotate(&mut self, id: NodeId, attrs: &[Attribute], item_sp: Span, kind: AnnotationKind, visit_children: F) where F: FnOnce(&mut Annotator) { diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index 0978c3f78e82f..784428cc114dc 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -34,7 +34,7 @@ pub trait Folder : Sized { noop_fold_crate(c, self) } - fn fold_meta_items(&mut self, meta_items: Vec>) -> Vec> { + fn fold_meta_items(&mut self, meta_items: HirVec>) -> HirVec> { noop_fold_meta_items(meta_items, self) } @@ -198,11 +198,11 @@ pub trait Folder : Sized { noop_fold_variant_data(vdata, self) } - fn fold_lifetimes(&mut self, lts: Vec) -> Vec { + fn fold_lifetimes(&mut self, lts: HirVec) -> HirVec { noop_fold_lifetimes(lts, self) } - fn fold_lifetime_defs(&mut self, lts: Vec) -> Vec { + fn fold_lifetime_defs(&mut self, lts: HirVec) -> HirVec { noop_fold_lifetime_defs(lts, self) } @@ -263,9 +263,9 @@ pub trait Folder : Sized { } } -pub fn noop_fold_meta_items(meta_items: Vec>, +pub fn noop_fold_meta_items(meta_items: HirVec>, fld: &mut T) - -> Vec> { + -> HirVec> { meta_items.move_map(|x| fld.fold_meta_item(x)) } @@ -304,7 +304,7 @@ pub fn noop_fold_view_path(view_path: P, fld: &mut T) -> P< }) } -pub fn fold_attrs(attrs: Vec, fld: &mut T) -> Vec { +pub fn fold_attrs(attrs: HirVec, fld: &mut T) -> HirVec { attrs.move_flat_map(|x| fld.fold_attribute(x)) } @@ -477,7 +477,7 @@ pub fn noop_fold_local(l: P, fld: &mut T) -> P { pat: fld.fold_pat(pat), init: init.map(|e| fld.fold_expr(e)), span: fld.new_span(span), - attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs, fld)), + attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs.into(), fld).into()), } }) } @@ -596,11 +596,13 @@ pub fn noop_fold_lifetime_def(l: LifetimeDef, fld: &mut T) -> Lifetim } } -pub fn noop_fold_lifetimes(lts: Vec, fld: &mut T) -> Vec { +pub fn noop_fold_lifetimes(lts: HirVec, fld: &mut T) -> HirVec { lts.move_map(|l| fld.fold_lifetime(l)) } -pub fn noop_fold_lifetime_defs(lts: Vec, fld: &mut T) -> Vec { +pub fn noop_fold_lifetime_defs(lts: HirVec, + fld: &mut T) + -> HirVec { lts.move_map(|l| fld.fold_lifetime_def(l)) } @@ -1139,7 +1141,7 @@ pub fn noop_fold_expr(Expr { id, node, span, attrs }: Expr, folder: & } }, span: folder.new_span(span), - attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs, folder)), + attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs.into(), folder).into()), } } diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index 1491ecc89af1f..6b2664af60ba5 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -40,7 +40,7 @@ use std::collections::BTreeMap; use syntax::codemap::{self, Span, Spanned, DUMMY_SP, ExpnId}; use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect}; -use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, CrateConfig}; +use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; use syntax::attr::ThinAttributes; use syntax::parse::token::InternedString; use syntax::ptr::P; @@ -52,6 +52,22 @@ use std::fmt; use std::hash::{Hash, Hasher}; use serialize::{Encodable, Decodable, Encoder, Decoder}; +/// HIR doesn't commit to a concrete storage type and have its own alias for a vector. +/// It can be `Vec`, `P<[T]>` or potentially `Box<[T]>`, or some other container with similar +/// behavior. Unlike AST, HIR is mostly a static structure, so we can use an owned slice instead +/// of `Vec` to avoid keeping extra capacity. +pub type HirVec = Vec; + +macro_rules! hir_vec { + ($elem:expr; $n:expr) => ( + $crate::hir::HirVec::from(vec![$elem; $n]) + ); + ($($x:expr),*) => ( + $crate::hir::HirVec::from(vec![$($x),*]) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + /// Identifier in HIR #[derive(Clone, Copy, Eq)] pub struct Ident { @@ -129,7 +145,7 @@ impl fmt::Debug for Lifetime { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct LifetimeDef { pub lifetime: Lifetime, - pub bounds: Vec, + pub bounds: HirVec, } /// A "Path" is essentially Rust's notion of a name; for instance: @@ -142,7 +158,7 @@ pub struct Path { /// module (like paths in an import). pub global: bool, /// The segments in the path: the things separated by `::`. - pub segments: Vec, + pub segments: HirVec, } impl fmt::Debug for Path { @@ -191,7 +207,7 @@ pub enum PathParameters { impl PathParameters { pub fn none() -> PathParameters { AngleBracketedParameters(AngleBracketedParameterData { - lifetimes: Vec::new(), + lifetimes: HirVec::new(), types: P::empty(), bindings: P::empty(), }) @@ -223,7 +239,7 @@ impl PathParameters { /// Returns the types that the user wrote. Note that these do not necessarily map to the type /// parameters in the parenthesized case. - pub fn types(&self) -> Vec<&P> { + pub fn types(&self) -> HirVec<&P> { match *self { AngleBracketedParameters(ref data) => { data.types.iter().collect() @@ -237,24 +253,24 @@ impl PathParameters { } } - pub fn lifetimes(&self) -> Vec<&Lifetime> { + pub fn lifetimes(&self) -> HirVec<&Lifetime> { match *self { AngleBracketedParameters(ref data) => { data.lifetimes.iter().collect() } ParenthesizedParameters(_) => { - Vec::new() + HirVec::new() } } } - pub fn bindings(&self) -> Vec<&TypeBinding> { + pub fn bindings(&self) -> HirVec<&TypeBinding> { match *self { AngleBracketedParameters(ref data) => { data.bindings.iter().collect() } ParenthesizedParameters(_) => { - Vec::new() + HirVec::new() } } } @@ -264,7 +280,7 @@ impl PathParameters { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct AngleBracketedParameterData { /// The lifetime parameters for this path segment. - pub lifetimes: Vec, + pub lifetimes: HirVec, /// The type parameters for this path segment, if present. pub types: P<[P]>, /// Bindings (equality constraints) on associated types, if present. @@ -285,7 +301,7 @@ pub struct ParenthesizedParameterData { pub span: Span, /// `(A,B)` - pub inputs: Vec>, + pub inputs: HirVec>, /// `C` pub output: Option>, @@ -324,7 +340,7 @@ pub struct TyParam { /// of a function, enum, trait, etc. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Generics { - pub lifetimes: Vec, + pub lifetimes: HirVec, pub ty_params: P<[TyParam]>, pub where_clause: WhereClause, } @@ -345,7 +361,7 @@ impl Generics { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereClause { pub id: NodeId, - pub predicates: Vec, + pub predicates: HirVec, } /// A single predicate in a `where` clause @@ -364,7 +380,7 @@ pub enum WherePredicate { pub struct WhereBoundPredicate { pub span: Span, /// Any lifetimes from a `for` binding - pub bound_lifetimes: Vec, + pub bound_lifetimes: HirVec, /// The type being bounded pub bounded_ty: P, /// Trait and lifetime bounds (`Clone+Send+'static`) @@ -376,7 +392,7 @@ pub struct WhereBoundPredicate { pub struct WhereRegionPredicate { pub span: Span, pub lifetime: Lifetime, - pub bounds: Vec, + pub bounds: HirVec, } /// An equality predicate (unsupported), e.g. `T=int` @@ -388,13 +404,15 @@ pub struct WhereEqPredicate { pub ty: P, } +pub type CrateConfig = HirVec>; + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] pub struct Crate { pub module: Mod, - pub attrs: Vec, + pub attrs: HirVec, pub config: CrateConfig, pub span: Span, - pub exported_macros: Vec, + pub exported_macros: HirVec, // NB: We use a BTreeMap here so that `visit_all_items` iterates // over the ids in increasing order. In principle it should not @@ -431,20 +449,20 @@ impl Crate { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct MacroDef { pub name: Name, - pub attrs: Vec, + pub attrs: HirVec, pub id: NodeId, pub span: Span, pub imported_from: Option, pub export: bool, pub use_locally: bool, pub allow_internal_unstable: bool, - pub body: Vec, + pub body: HirVec, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Block { /// Statements in a block - pub stmts: Vec, + pub stmts: HirVec, /// An expression at the end of the block /// without a semicolon, if any pub expr: Option>, @@ -503,7 +521,7 @@ pub enum Pat_ { PatIdent(BindingMode, Spanned, Option>), /// "None" means a `Variant(..)` pattern where we don't bind the fields to names. - PatEnum(Path, Option>>), + PatEnum(Path, Option>>), /// An associated const named using the qualified path `::CONST` or /// `::CONST`. Associated consts from inherent impls can be @@ -513,9 +531,9 @@ pub enum Pat_ { /// Destructuring of a struct, e.g. `Foo {x, y, ..}` /// The `bool` is `true` in the presence of a `..` - PatStruct(Path, Vec>, bool), + PatStruct(Path, HirVec>, bool), /// A tuple pattern `(a, b)` - PatTup(Vec>), + PatTup(HirVec>), /// A `box` pattern PatBox(P), /// A reference pattern, e.g. `&mut (a, b)` @@ -526,7 +544,7 @@ pub enum Pat_ { PatRange(P, P), /// `[a, b, ..i, y, z]` is represented as: /// `PatVec(box [a, b], Some(i), box [y, z])` - PatVec(Vec>, Option>, Vec>), + PatVec(HirVec>, Option>, HirVec>), } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -640,8 +658,8 @@ pub enum Decl_ { /// represents one arm of a 'match' #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Arm { - pub attrs: Vec, - pub pats: Vec>, + pub attrs: HirVec, + pub pats: HirVec>, pub guard: Option>, pub body: P, } @@ -690,12 +708,12 @@ pub enum Expr_ { /// A `box x` expression. ExprBox(P), /// An array (`[a, b, c, d]`) - ExprVec(Vec>), + ExprVec(HirVec>), /// A function call /// /// The first field resolves to the function itself, /// and the second field is the list of arguments - ExprCall(P, Vec>), + ExprCall(P, HirVec>), /// A method call (`x.foo::(a, b, c, d)`) /// /// The `Spanned` is the identifier for the method name. @@ -708,9 +726,9 @@ pub enum Expr_ { /// /// Thus, `x.foo::(a, b, c, d)` is represented as /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. - ExprMethodCall(Spanned, Vec>, Vec>), + ExprMethodCall(Spanned, HirVec>, HirVec>), /// A tuple (`(a, b, c ,d)`) - ExprTup(Vec>), + ExprTup(HirVec>), /// A binary operation (For example: `a + b`, `a * b`) ExprBinary(BinOp, P, P), /// A unary operation (For example: `!x`, `*x`) @@ -733,7 +751,7 @@ pub enum Expr_ { ExprLoop(P, Option), /// A `match` block, with a source that indicates whether or not it is /// the result of a desugaring, and if so, which kind. - ExprMatch(P, Vec, MatchSource), + ExprMatch(P, HirVec, MatchSource), /// A closure (for example, `move |a, b, c| {a + b + c}`) ExprClosure(CaptureClause, P, P), /// A block (`{ ... }`) @@ -760,7 +778,7 @@ pub enum Expr_ { /// parameters, e.g. foo::bar::. /// /// Optionally "qualified", - /// e.g. ` as SomeTrait>::SomeType`. + /// e.g. ` as SomeTrait>::SomeType`. ExprPath(Option, Path), /// A referencing operation (`&a` or `&mut a`) @@ -779,7 +797,7 @@ pub enum Expr_ { /// /// For example, `Foo {x: 1, y: 2}`, or /// `Foo {x: 1, .. base}`, where `base` is the `Option`. - ExprStruct(Path, Vec, Option>), + ExprStruct(Path, HirVec, Option>), /// A vector literal constructed from one repeated element. /// @@ -793,11 +811,11 @@ pub enum Expr_ { /// separately. `position` represents the index of the associated /// item qualified with this Self type. /// -/// as a::b::Trait>::AssociatedItem +/// as a::b::Trait>::AssociatedItem /// ^~~~~ ~~~~~~~~~~~~~~^ /// ty position = 3 /// -/// >::AssociatedItem +/// >::AssociatedItem /// ^~~~~ ^ /// ty position = 0 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -850,7 +868,7 @@ pub struct MethodSig { pub struct TraitItem { pub id: NodeId, pub name: Name, - pub attrs: Vec, + pub attrs: HirVec, pub node: TraitItem_, pub span: Span, } @@ -867,7 +885,7 @@ pub struct ImplItem { pub id: NodeId, pub name: Name, pub vis: Visibility, - pub attrs: Vec, + pub attrs: HirVec, pub node: ImplItemKind, pub span: Span, } @@ -918,7 +936,7 @@ pub enum PrimTy { pub struct BareFnTy { pub unsafety: Unsafety, pub abi: Abi, - pub lifetimes: Vec, + pub lifetimes: HirVec, pub decl: P, } @@ -935,9 +953,9 @@ pub enum Ty_ { /// A bare function (e.g. `fn(usize) -> bool`) TyBareFn(P), /// A tuple (`(A, B, C, D,...)`) - TyTup(Vec>), + TyTup(HirVec>), /// A path (`module::module::...::Type`), optionally - /// "qualified", e.g. ` as SomeTrait>::SomeType`. + /// "qualified", e.g. ` as SomeTrait>::SomeType`. /// /// Type parameters are stored in the Path itself TyPath(Option, Path), @@ -964,9 +982,9 @@ pub struct InlineAsmOutput { pub struct InlineAsm { pub asm: InternedString, pub asm_str_style: StrStyle, - pub outputs: Vec, - pub inputs: Vec<(InternedString, P)>, - pub clobbers: Vec, + pub outputs: HirVec, + pub inputs: HirVec<(InternedString, P)>, + pub clobbers: HirVec, pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, @@ -1007,7 +1025,7 @@ impl Arg { /// Represents the header (not the body) of a function declaration #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct FnDecl { - pub inputs: Vec, + pub inputs: HirVec, pub output: FunctionRetTy, pub variadic: bool, } @@ -1098,24 +1116,24 @@ pub struct Mod { /// For `mod foo;`, the inner span ranges from the first token /// to the last token in the external file. pub inner: Span, - pub item_ids: Vec, + pub item_ids: HirVec, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct ForeignMod { pub abi: Abi, - pub items: Vec, + pub items: HirVec, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct EnumDef { - pub variants: Vec, + pub variants: HirVec, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Variant_ { pub name: Name, - pub attrs: Vec, + pub attrs: HirVec, pub data: VariantData, /// Explicit discriminant, eg `Foo = 1` pub disr_expr: Option>, @@ -1176,7 +1194,7 @@ pub enum ViewPath_ { ViewPathGlob(Path), /// `foo::bar::{a,b,c}` - ViewPathList(Path, Vec), + ViewPathList(Path, HirVec), } /// TraitRef's appear in impls. @@ -1194,7 +1212,7 @@ pub struct TraitRef { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct PolyTraitRef { /// The `'a` in `<'a> Foo<&'a T>` - pub bound_lifetimes: Vec, + pub bound_lifetimes: HirVec, /// The `Foo<&'a T>` in `<'a> Foo<&'a T>` pub trait_ref: TraitRef, @@ -1222,7 +1240,7 @@ pub struct StructField_ { pub kind: StructFieldKind, pub id: NodeId, pub ty: P, - pub attrs: Vec, + pub attrs: HirVec, } impl StructField_ { @@ -1271,8 +1289,8 @@ impl StructFieldKind { /// Id of the whole struct lives in `Item`. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum VariantData { - Struct(Vec, NodeId), - Tuple(Vec, NodeId), + Struct(HirVec, NodeId), + Tuple(HirVec, NodeId), Unit(NodeId), } @@ -1327,7 +1345,7 @@ pub struct ItemId { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Item { pub name: Name, - pub attrs: Vec, + pub attrs: HirVec, pub id: NodeId, pub node: Item_, pub vis: Visibility, @@ -1360,7 +1378,7 @@ pub enum Item_ { /// A struct definition, e.g. `struct Foo {x: A}` ItemStruct(VariantData, Generics), /// Represents a Trait Declaration - ItemTrait(Unsafety, Generics, TyParamBounds, Vec), + ItemTrait(Unsafety, Generics, TyParamBounds, HirVec), // Default trait implementations /// @@ -1372,7 +1390,7 @@ pub enum Item_ { Generics, Option, // (optional) trait this impl implements P, // self - Vec), + HirVec), } impl Item_ { @@ -1398,7 +1416,7 @@ impl Item_ { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct ForeignItem { pub name: Name, - pub attrs: Vec, + pub attrs: HirVec, pub node: ForeignItem_, pub id: NodeId, pub span: Span, diff --git a/src/librustc_front/lib.rs b/src/librustc_front/lib.rs index 3bfa645afc7d9..60080854a6f17 100644 --- a/src/librustc_front/lib.rs +++ b/src/librustc_front/lib.rs @@ -47,6 +47,7 @@ extern crate rustc_bitflags; extern crate serialize as rustc_serialize; // used by deriving +#[macro_use] pub mod hir; pub mod lowering; pub mod fold; diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index 614f6f0bd36dd..db30ee9a5d2d3 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -147,6 +147,10 @@ pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident { } } +pub fn lower_attrs(_lctx: &LoweringContext, attrs: &Vec) -> hir::HirVec { + attrs.clone().into() +} + pub fn lower_view_path(lctx: &LoweringContext, view_path: &ViewPath) -> P { P(Spanned { node: match view_path.node { @@ -186,7 +190,7 @@ pub fn lower_view_path(lctx: &LoweringContext, view_path: &ViewPath) -> P hir::Arm { hir::Arm { - attrs: arm.attrs.clone(), + attrs: lower_attrs(lctx, &arm.attrs), pats: arm.pats.iter().map(|x| lower_pat(lctx, x)).collect(), guard: arm.guard.as_ref().map(|ref x| lower_expr(lctx, x)), body: lower_expr(lctx, &arm.body), @@ -275,7 +279,7 @@ pub fn lower_variant(lctx: &LoweringContext, v: &Variant) -> hir::Variant { Spanned { node: hir::Variant_ { name: v.node.name.name, - attrs: v.node.attrs.clone(), + attrs: lower_attrs(lctx, &v.node.attrs), data: lower_variant_data(lctx, &v.node.data), disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(lctx, e)), }, @@ -449,13 +453,13 @@ pub fn lower_lifetime_def(lctx: &LoweringContext, l: &LifetimeDef) -> hir::Lifet } } -pub fn lower_lifetimes(lctx: &LoweringContext, lts: &Vec) -> Vec { +pub fn lower_lifetimes(lctx: &LoweringContext, lts: &Vec) -> hir::HirVec { lts.iter().map(|l| lower_lifetime(lctx, l)).collect() } pub fn lower_lifetime_defs(lctx: &LoweringContext, lts: &Vec) - -> Vec { + -> hir::HirVec { lts.iter().map(|l| lower_lifetime_def(lctx, l)).collect() } @@ -560,7 +564,7 @@ pub fn lower_struct_field(lctx: &LoweringContext, f: &StructField) -> hir::Struc id: f.node.id, kind: lower_struct_field_kind(lctx, &f.node.kind), ty: lower_ty(lctx, &f.node.ty), - attrs: f.node.attrs.clone(), + attrs: lower_attrs(lctx, &f.node.attrs), }, span: f.span, } @@ -673,7 +677,7 @@ pub fn lower_trait_item(lctx: &LoweringContext, i: &TraitItem) -> hir::TraitItem hir::TraitItem { id: i.id, name: i.ident.name, - attrs: i.attrs.clone(), + attrs: lower_attrs(lctx, &i.attrs), node: match i.node { ConstTraitItem(ref ty, ref default) => { hir::ConstTraitItem(lower_ty(lctx, ty), @@ -696,7 +700,7 @@ pub fn lower_impl_item(lctx: &LoweringContext, i: &ImplItem) -> hir::ImplItem { hir::ImplItem { id: i.id, name: i.ident.name, - attrs: i.attrs.clone(), + attrs: lower_attrs(lctx, &i.attrs), vis: lower_visibility(lctx, i.vis), node: match i.node { ImplItemKind::Const(ref ty, ref expr) => { @@ -740,25 +744,25 @@ pub fn lower_crate(lctx: &LoweringContext, c: &Crate) -> hir::Crate { hir::Crate { module: lower_mod(lctx, &c.module), - attrs: c.attrs.clone(), - config: c.config.clone(), + attrs: lower_attrs(lctx, &c.attrs), + config: c.config.clone().into(), span: c.span, exported_macros: c.exported_macros.iter().map(|m| lower_macro_def(lctx, m)).collect(), items: items, } } -pub fn lower_macro_def(_lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef { +pub fn lower_macro_def(lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef { hir::MacroDef { name: m.ident.name, - attrs: m.attrs.clone(), + attrs: lower_attrs(lctx, &m.attrs), id: m.id, span: m.span, imported_from: m.imported_from.map(|x| x.name), export: m.export, use_locally: m.use_locally, allow_internal_unstable: m.allow_internal_unstable, - body: m.body.clone(), + body: m.body.clone().into(), } } @@ -772,7 +776,7 @@ pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item { hir::Item { id: i.id, name: i.ident.name, - attrs: i.attrs.clone(), + attrs: lower_attrs(lctx, &i.attrs), node: node, vis: lower_visibility(lctx, i.vis), span: i.span, @@ -783,7 +787,7 @@ pub fn lower_foreign_item(lctx: &LoweringContext, i: &ForeignItem) -> hir::Forei hir::ForeignItem { id: i.id, name: i.ident.name, - attrs: i.attrs.clone(), + attrs: lower_attrs(lctx, &i.attrs), node: match i.node { ForeignItemFn(ref fdec, ref generics) => { hir::ForeignItemFn(lower_fn_decl(lctx, fdec), lower_generics(lctx, generics)) @@ -1020,7 +1024,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { // let placer = ; let s1 = { let placer_expr = signal_block_expr(lctx, - vec![], + hir_vec![], placer_expr, e.span, hir::PopUnstableBlock, @@ -1031,14 +1035,14 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { // let mut place = Placer::make_place(placer); let s2 = { let placer = expr_ident(lctx, e.span, placer_ident, None); - let call = make_call(lctx, &make_place, vec![placer]); + let call = make_call(lctx, &make_place, hir_vec![placer]); mk_stmt_let_mut(lctx, place_ident, call) }; // let p_ptr = Place::pointer(&mut place); let s3 = { let agent = expr_ident(lctx, e.span, place_ident, None); - let args = vec![expr_mut_addr_of(lctx, e.span, agent, None)]; + let args = hir_vec![expr_mut_addr_of(lctx, e.span, agent, None)]; let call = make_call(lctx, &place_pointer, args); mk_stmt_let(lctx, p_ptr_ident, call) }; @@ -1046,13 +1050,13 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { // pop_unsafe!(EXPR)); let pop_unsafe_expr = { let value_expr = signal_block_expr(lctx, - vec![], + hir_vec![], value_expr, e.span, hir::PopUnstableBlock, None); signal_block_expr(lctx, - vec![], + hir_vec![], value_expr, e.span, hir::PopUnsafeBlock(hir::CompilerGenerated), None) @@ -1066,21 +1070,21 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let ptr = expr_ident(lctx, e.span, p_ptr_ident, None); let call_move_val_init = hir::StmtSemi( - make_call(lctx, &move_val_init, vec![ptr, pop_unsafe_expr]), + make_call(lctx, &move_val_init, hir_vec![ptr, pop_unsafe_expr]), lctx.next_id()); let call_move_val_init = respan(e.span, call_move_val_init); let place = expr_ident(lctx, e.span, place_ident, None); - let call = make_call(lctx, &inplace_finalize, vec![place]); + let call = make_call(lctx, &inplace_finalize, hir_vec![place]); signal_block_expr(lctx, - vec![call_move_val_init], + hir_vec![call_move_val_init], call, e.span, hir::PushUnsafeBlock(hir::CompilerGenerated), None) }; signal_block_expr(lctx, - vec![s1, s2, s3], + hir_vec![s1, s2, s3], expr, e.span, hir::PushUnstableBlock, @@ -1141,7 +1145,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let els = lower_expr(lctx, els); let id = lctx.next_id(); let blk = P(hir::Block { - stmts: vec![], + stmts: hir_vec![], expr: Some(els), id: id, rules: hir::DefaultBlock, @@ -1238,7 +1242,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { .collect(), asm: asm.clone(), asm_str_style: asm_str_style, - clobbers: clobbers.clone(), + clobbers: clobbers.clone().into(), volatile: volatile, alignstack: alignstack, dialect: dialect, @@ -1275,7 +1279,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let pat_arm = { let body = lower_block(lctx, body); let body_expr = expr_block(lctx, body, None); - arm(vec![lower_pat(lctx, pat)], body_expr) + arm(hir_vec![lower_pat(lctx, pat)], body_expr) }; // `[_ if => ,]` @@ -1290,8 +1294,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { hir::ExprIf(cond, then, else_opt) => { let pat_under = pat_wild(lctx, e.span); arms.push(hir::Arm { - attrs: vec![], - pats: vec![pat_under], + attrs: hir_vec![], + pats: hir_vec![pat_under], guard: Some(cond), body: expr_block(lctx, then, None), }); @@ -1325,8 +1329,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let pat_under = pat_wild(lctx, e.span); let else_expr = else_opt.unwrap_or_else( - || expr_tuple(lctx, e.span, vec![], None)); - arm(vec![pat_under], else_expr) + || expr_tuple(lctx, e.span, hir_vec![], None)); + arm(hir_vec![pat_under], else_expr) }; let mut arms = Vec::with_capacity(else_if_arms.len() + 2); @@ -1339,7 +1343,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { expr(lctx, e.span, hir::ExprMatch(sub_expr, - arms, + arms.into(), hir::MatchSource::IfLetDesugar { contains_else_clause: contains_else_clause, }), @@ -1364,18 +1368,18 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let pat_arm = { let body = lower_block(lctx, body); let body_expr = expr_block(lctx, body, None); - arm(vec![lower_pat(lctx, pat)], body_expr) + arm(hir_vec![lower_pat(lctx, pat)], body_expr) }; // `_ => break` let break_arm = { let pat_under = pat_wild(lctx, e.span); let break_expr = expr_break(lctx, e.span, None); - arm(vec![pat_under], break_expr) + arm(hir_vec![pat_under], break_expr) }; // `match { ... }` - let arms = vec![pat_arm, break_arm]; + let arms = hir_vec![pat_arm, break_arm]; let sub_expr = lower_expr(lctx, sub_expr); let match_expr = expr(lctx, e.span, @@ -1431,14 +1435,14 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let pat = lower_pat(lctx, pat); let some_pat = pat_some(lctx, e.span, pat); - arm(vec![some_pat], body_expr) + arm(hir_vec![some_pat], body_expr) }; // `::std::option::Option::None => break` let break_arm = { let break_expr = expr_break(lctx, e.span, None); - arm(vec![pat_none(lctx, e.span)], break_expr) + arm(hir_vec![pat_none(lctx, e.span)], break_expr) }; // `match ::std::iter::Iterator::next(&mut iter) { ... }` @@ -1454,9 +1458,9 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let next_expr = expr_call(lctx, e.span, next_path, - vec![ref_mut_iter], + hir_vec![ref_mut_iter], None); - let arms = vec![pat_arm, break_arm]; + let arms = hir_vec![pat_arm, break_arm]; expr(lctx, e.span, @@ -1476,7 +1480,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { e.span, iter, hir::BindByValue(hir::MutMutable)); - arm(vec![iter_pat], loop_expr) + arm(hir_vec![iter_pat], loop_expr) }; // `match ::std::iter::IntoIterator::into_iter() { ... }` @@ -1488,13 +1492,13 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { }; let into_iter = expr_path(lctx, into_iter_path, None); - expr_call(lctx, e.span, into_iter, vec![head], None) + expr_call(lctx, e.span, into_iter, hir_vec![head], None) }; let match_expr = expr_match(lctx, e.span, into_iter_expr, - vec![iter_arm], + hir_vec![iter_arm], hir::MatchSource::ForLoopDesugar, None); @@ -1502,7 +1506,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let result_ident = lctx.str_to_ident("result"); let let_stmt = stmt_let(lctx, e.span, false, result_ident, match_expr, None); let result = expr_ident(lctx, e.span, result_ident, None); - let block = block_all(lctx, e.span, vec![let_stmt], Some(result)); + let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result)); // add the attributes to the outer returned expr node expr_block(lctx, block, e.attrs.clone()) }); @@ -1601,9 +1605,9 @@ pub fn lower_trait_bound_modifier(_lctx: &LoweringContext, // Helper methods for building HIR. -fn arm(pats: Vec>, expr: P) -> hir::Arm { +fn arm(pats: hir::HirVec>, expr: P) -> hir::Arm { hir::Arm { - attrs: vec![], + attrs: hir_vec![], pats: pats, guard: None, body: expr, @@ -1618,7 +1622,7 @@ fn expr_break(lctx: &LoweringContext, span: Span, fn expr_call(lctx: &LoweringContext, span: Span, e: P, - args: Vec>, + args: hir::HirVec>, attrs: ThinAttributes) -> P { expr(lctx, span, hir::ExprCall(e, args), attrs) @@ -1642,7 +1646,7 @@ fn expr_path(lctx: &LoweringContext, path: hir::Path, fn expr_match(lctx: &LoweringContext, span: Span, arg: P, - arms: Vec, + arms: hir::HirVec, source: hir::MatchSource, attrs: ThinAttributes) -> P { @@ -1654,7 +1658,7 @@ fn expr_block(lctx: &LoweringContext, b: P, expr(lctx, b.span, hir::ExprBlock(b), attrs) } -fn expr_tuple(lctx: &LoweringContext, sp: Span, exprs: Vec>, +fn expr_tuple(lctx: &LoweringContext, sp: Span, exprs: hir::HirVec>, attrs: ThinAttributes) -> P { expr(lctx, sp, hir::ExprTup(exprs), attrs) } @@ -1694,12 +1698,12 @@ fn stmt_let(lctx: &LoweringContext, } fn block_expr(lctx: &LoweringContext, expr: P) -> P { - block_all(lctx, expr.span, Vec::new(), Some(expr)) + block_all(lctx, expr.span, hir::HirVec::new(), Some(expr)) } fn block_all(lctx: &LoweringContext, span: Span, - stmts: Vec, + stmts: hir::HirVec, expr: Option>) -> P { P(hir::Block { @@ -1714,19 +1718,19 @@ fn block_all(lctx: &LoweringContext, fn pat_some(lctx: &LoweringContext, span: Span, pat: P) -> P { let some = std_path(lctx, &["option", "Option", "Some"]); let path = path_global(span, some); - pat_enum(lctx, span, path, vec![pat]) + pat_enum(lctx, span, path, hir_vec![pat]) } fn pat_none(lctx: &LoweringContext, span: Span) -> P { let none = std_path(lctx, &["option", "Option", "None"]); let path = path_global(span, none); - pat_enum(lctx, span, path, vec![]) + pat_enum(lctx, span, path, hir_vec![]) } fn pat_enum(lctx: &LoweringContext, span: Span, path: hir::Path, - subpats: Vec>) + subpats: hir::HirVec>) -> P { let pt = hir::PatEnum(path, Some(subpats)); pat(lctx, span, pt) @@ -1767,17 +1771,17 @@ fn path_ident(span: Span, id: hir::Ident) -> hir::Path { } fn path(span: Span, strs: Vec) -> hir::Path { - path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new()) + path_all(span, false, strs, hir::HirVec::new(), Vec::new(), Vec::new()) } fn path_global(span: Span, strs: Vec) -> hir::Path { - path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) + path_all(span, true, strs, hir::HirVec::new(), Vec::new(), Vec::new()) } fn path_all(sp: Span, global: bool, mut idents: Vec, - lifetimes: Vec, + lifetimes: hir::HirVec, types: Vec>, bindings: Vec) -> hir::Path { @@ -1801,7 +1805,7 @@ fn path_all(sp: Span, hir::Path { span: sp, global: global, - segments: segments, + segments: segments.into(), } } @@ -1822,7 +1826,7 @@ fn core_path(lctx: &LoweringContext, span: Span, components: &[&str]) -> hir::Pa } fn signal_block_expr(lctx: &LoweringContext, - stmts: Vec, + stmts: hir::HirVec, expr: P, span: Span, rule: hir::BlockCheckMode, diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index a3bb005dfbdca..c4c5b9170f6bf 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -521,7 +521,7 @@ impl<'a> State<'a> { ty_params: P::empty(), where_clause: hir::WhereClause { id: ast::DUMMY_NODE_ID, - predicates: Vec::new(), + predicates: hir::HirVec::new(), }, }; try!(self.print_ty_fn(f.abi, f.unsafety, &*f.decl, None, &generics, None)); @@ -2256,11 +2256,11 @@ impl<'a> State<'a> { try!(self.print_generics(generics)); } let generics = hir::Generics { - lifetimes: Vec::new(), + lifetimes: hir::HirVec::new(), ty_params: P::empty(), where_clause: hir::WhereClause { id: ast::DUMMY_NODE_ID, - predicates: Vec::new(), + predicates: hir::HirVec::new(), }, }; try!(self.print_fn(decl, diff --git a/src/librustc_front/util.rs b/src/librustc_front/util.rs index f85eb2bb4011e..298904d1e0d7a 100644 --- a/src/librustc_front/util.rs +++ b/src/librustc_front/util.rs @@ -334,11 +334,11 @@ pub fn is_path(e: P) -> bool { pub fn empty_generics() -> Generics { Generics { - lifetimes: Vec::new(), + lifetimes: HirVec::new(), ty_params: P::empty(), where_clause: WhereClause { id: DUMMY_NODE_ID, - predicates: Vec::new(), + predicates: HirVec::new(), }, } } @@ -349,13 +349,13 @@ pub fn ident_to_path(s: Span, ident: Ident) -> Path { hir::Path { span: s, global: false, - segments: vec!(hir::PathSegment { + segments: hir_vec![hir::PathSegment { identifier: ident, parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { - lifetimes: Vec::new(), + lifetimes: HirVec::new(), types: P::empty(), bindings: P::empty(), }), - }), + }], } } diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 74fef68400656..64a86373ee1e5 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -252,7 +252,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { } } - fn to_pats(&mut self, pats: &'tcx Vec>) -> Vec> { + fn to_pats(&mut self, pats: &'tcx [P]) -> Vec> { pats.iter().map(|p| self.to_pat(p)).collect() } @@ -263,9 +263,9 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { fn slice_or_array_pattern(&mut self, pat: &'tcx hir::Pat, ty: Ty<'tcx>, - prefix: &'tcx Vec>, + prefix: &'tcx [P], slice: &'tcx Option>, - suffix: &'tcx Vec>) + suffix: &'tcx [P]) -> PatternKind<'tcx> { match ty.sty { ty::TySlice(..) => { diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 77664f19aac2a..2a9b675d8767d 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -1038,7 +1038,7 @@ pub fn trans_static(ccx: &CrateContext, m: hir::Mutability, expr: &hir::Expr, id: ast::NodeId, - attrs: &Vec) + attrs: &[ast::Attribute]) -> Result { unsafe { let _icx = push_ctxt("trans_static"); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e217e7afad737..675eef637b10b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1584,8 +1584,13 @@ impl Clean for hir::Ty { resolve_type(cx, p.clean(cx), self.id) } TyPath(Some(ref qself), ref p) => { - let mut trait_path = p.clone(); - trait_path.segments.pop(); + let mut segments: Vec<_> = p.segments.clone().into(); + segments.pop(); + let trait_path = hir::Path { + span: p.span, + global: p.global, + segments: segments.into(), + }; Type::QPath { name: p.segments.last().unwrap().identifier.name.clean(cx), self_type: box qself.ty.clean(cx), diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index d1030a6fcb07c..fc0422b3a3f03 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -24,7 +24,7 @@ use rustc_front::hir; pub struct Module { pub name: Option, - pub attrs: Vec, + pub attrs: hir::HirVec, pub where_outer: Span, pub where_inner: Span, pub extern_crates: Vec, @@ -58,7 +58,7 @@ impl Module { depr: None, where_outer: syntax::codemap::DUMMY_SP, where_inner: syntax::codemap::DUMMY_SP, - attrs : Vec::new(), + attrs : hir::HirVec::new(), extern_crates: Vec::new(), imports : Vec::new(), structs : Vec::new(), @@ -103,8 +103,8 @@ pub struct Struct { pub struct_type: StructType, pub name: Name, pub generics: hir::Generics, - pub attrs: Vec, - pub fields: Vec, + pub attrs: hir::HirVec, + pub fields: hir::HirVec, pub whence: Span, } @@ -112,9 +112,9 @@ pub struct Enum { pub vis: hir::Visibility, pub stab: Option, pub depr: Option, - pub variants: Vec, + pub variants: hir::HirVec, pub generics: hir::Generics, - pub attrs: Vec, + pub attrs: hir::HirVec, pub id: NodeId, pub whence: Span, pub name: Name, @@ -122,7 +122,7 @@ pub struct Enum { pub struct Variant { pub name: Name, - pub attrs: Vec, + pub attrs: hir::HirVec, pub def: hir::VariantData, pub stab: Option, pub depr: Option, @@ -131,7 +131,7 @@ pub struct Variant { pub struct Function { pub decl: hir::FnDecl, - pub attrs: Vec, + pub attrs: hir::HirVec, pub id: NodeId, pub name: Name, pub vis: hir::Visibility, @@ -149,7 +149,7 @@ pub struct Typedef { pub gen: hir::Generics, pub name: Name, pub id: ast::NodeId, - pub attrs: Vec, + pub attrs: hir::HirVec, pub whence: Span, pub vis: hir::Visibility, pub stab: Option, @@ -162,7 +162,7 @@ pub struct Static { pub mutability: hir::Mutability, pub expr: P, pub name: Name, - pub attrs: Vec, + pub attrs: hir::HirVec, pub vis: hir::Visibility, pub stab: Option, pub depr: Option, @@ -174,7 +174,7 @@ pub struct Constant { pub type_: P, pub expr: P, pub name: Name, - pub attrs: Vec, + pub attrs: hir::HirVec, pub vis: hir::Visibility, pub stab: Option, pub depr: Option, @@ -185,10 +185,10 @@ pub struct Constant { pub struct Trait { pub unsafety: hir::Unsafety, pub name: Name, - pub items: Vec, + pub items: hir::HirVec, pub generics: hir::Generics, - pub bounds: Vec, - pub attrs: Vec, + pub bounds: hir::HirVec, + pub attrs: hir::HirVec, pub id: ast::NodeId, pub whence: Span, pub vis: hir::Visibility, @@ -202,8 +202,8 @@ pub struct Impl { pub generics: hir::Generics, pub trait_: Option, pub for_: P, - pub items: Vec, - pub attrs: Vec, + pub items: hir::HirVec, + pub attrs: hir::HirVec, pub whence: Span, pub vis: hir::Visibility, pub stab: Option, @@ -215,16 +215,16 @@ pub struct DefaultImpl { pub unsafety: hir::Unsafety, pub trait_: hir::TraitRef, pub id: ast::NodeId, - pub attrs: Vec, + pub attrs: hir::HirVec, pub whence: Span, } pub struct Macro { pub name: Name, pub id: ast::NodeId, - pub attrs: Vec, + pub attrs: hir::HirVec, pub whence: Span, - pub matchers: Vec, + pub matchers: hir::HirVec, pub stab: Option, pub depr: Option, pub imported_from: Option, @@ -234,14 +234,14 @@ pub struct ExternCrate { pub name: Name, pub path: Option, pub vis: hir::Visibility, - pub attrs: Vec, + pub attrs: hir::HirVec, pub whence: Span, } pub struct Import { pub id: NodeId, pub vis: hir::Visibility, - pub attrs: Vec, + pub attrs: hir::HirVec, pub node: hir::ViewPath_, pub whence: Span, } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index d95a4553bf1f5..ba389bc42b78c 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -38,7 +38,7 @@ use doctree::*; pub struct RustdocVisitor<'a, 'tcx: 'a> { pub module: Module, - pub attrs: Vec, + pub attrs: hir::HirVec, pub cx: &'a core::DocContext<'a, 'tcx>, pub analysis: Option<&'a core::CrateAnalysis>, view_item_stack: HashSet, @@ -53,7 +53,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { stack.insert(ast::CRATE_NODE_ID); RustdocVisitor { module: Module::new(None), - attrs: Vec::new(), + attrs: hir::HirVec::new(), cx: cx, analysis: analysis, view_item_stack: stack, @@ -157,7 +157,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - pub fn visit_mod_contents(&mut self, span: Span, attrs: Vec , + pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec, vis: hir::Visibility, id: ast::NodeId, m: &hir::Mod, name: Option) -> Module { @@ -192,7 +192,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let mine = paths.into_iter().filter(|path| { !self.resolve_id(path.node.id(), None, false, om, please_inline) - }).collect::>(); + }).collect::>(); if mine.is_empty() { None From 2a23e4a5b02bfb80d71becd8397e467838c94424 Mon Sep 17 00:00:00 2001 From: Xmasreturns Date: Thu, 17 Dec 2015 13:05:00 -0800 Subject: [PATCH 12/13] Clarified shadowing example Added some additional descriptive sentences and changed x to an int in the example --- src/doc/book/patterns.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/doc/book/patterns.md b/src/doc/book/patterns.md index 8f4a7a439553b..43f1bd2529fd2 100644 --- a/src/doc/book/patterns.md +++ b/src/doc/book/patterns.md @@ -27,7 +27,7 @@ There’s one pitfall with patterns: like anything that introduces a new binding they introduce shadowing. For example: ```rust -let x = 'x'; +let x = 1; let c = 'c'; match c { @@ -41,12 +41,14 @@ This prints: ```text x: c c: c -x: x +x: 1 ``` In other words, `x =>` matches the pattern and introduces a new binding named -`x` that’s in scope for the match arm. Because we already have a binding named -`x`, this new `x` shadows it. +`x`. This new binding is in scope for the match arm and takes on the value of +`c`. Notice that the value of `x` outside the scope of the match has no bearing +on the value of `x` within it. Because we already have a binding named `x`, this +new `x` shadows it. # Multiple patterns From 88ffb26cf50cff64c7ec0f4fc269a377a5b2918a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Fri, 18 Dec 2015 01:24:40 +0100 Subject: [PATCH 13/13] Fix emitting asm and object file output at the same time LLVM doesn't really support reusing the same module to emit more than one file. One bug this causes is that the IR is invalidated by the stack coloring pass when emitting the first file, and then the IR verifier complains by the time we try to emit the second file. Also, we get different binaries with --emit=asm,link than with just --emit=link. In some cases leading to segfaults. Unfortunately, it seems that at this point in time, the most sensible option to circumvent this problem is to just clone the whole llvm module for the asm output if we need both, asm and obj file output. Fixes #24876 Fixes #26235 --- src/librustc_llvm/lib.rs | 1 + src/librustc_trans/back/write.rs | 12 ++++++ src/test/run-make/emit/Makefile | 15 ++++++++ src/test/run-make/emit/test-24876.rs | 19 ++++++++++ src/test/run-make/emit/test-26235.rs | 56 ++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 src/test/run-make/emit/Makefile create mode 100644 src/test/run-make/emit/test-24876.rs create mode 100644 src/test/run-make/emit/test-26235.rs diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 0f05db86742eb..8dcaa4b5064c1 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -616,6 +616,7 @@ extern { C: ContextRef) -> ModuleRef; pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef; + pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef; pub fn LLVMDisposeModule(M: ModuleRef); /// Data layout. See Module::getDataLayout. diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 4815a399d9913..5b38004396bac 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -545,10 +545,22 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_asm { let path = output_names.with_extension(&format!("{}.s", name_extra)); + + // We can't use the same module for asm and binary output, because that triggers + // various errors like invalid IR or broken binaries, so we might have to clone the + // module to produce the asm output + let llmod = if config.emit_obj { + llvm::LLVMCloneModule(llmod) + } else { + llmod + }; with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType); }); + if config.emit_obj { + llvm::LLVMDisposeModule(llmod); + } } if config.emit_obj { diff --git a/src/test/run-make/emit/Makefile b/src/test/run-make/emit/Makefile new file mode 100644 index 0000000000000..be34028fe1d01 --- /dev/null +++ b/src/test/run-make/emit/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +all: + $(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs + $(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 + $(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 + $(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 + $(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs + $(call RUN,test-26235) || exit 1 diff --git a/src/test/run-make/emit/test-24876.rs b/src/test/run-make/emit/test-24876.rs new file mode 100644 index 0000000000000..ab69decbf007e --- /dev/null +++ b/src/test/run-make/emit/test-24876.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks for issue #24876 + +fn main() { + let mut v = 0; + for i in 0..0 { + v += i; + } + println!("{}", v) +} diff --git a/src/test/run-make/emit/test-26235.rs b/src/test/run-make/emit/test-26235.rs new file mode 100644 index 0000000000000..97b58a3671bf3 --- /dev/null +++ b/src/test/run-make/emit/test-26235.rs @@ -0,0 +1,56 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks for issue #26235 + +fn main() { + use std::thread; + + type Key = u32; + const NUM_THREADS: usize = 2; + + #[derive(Clone,Copy)] + struct Stats { + upsert: S, + delete: S, + insert: S, + update: S + }; + + impl Stats where S: Copy { + fn dot(self, s: Stats, f: F) -> Stats where F: Fn(S, T) -> B { + let Stats { upsert: u1, delete: d1, insert: i1, update: p1 } = self; + let Stats { upsert: u2, delete: d2, insert: i2, update: p2 } = s; + Stats { upsert: f(u1, u2), delete: f(d1, d2), insert: f(i1, i2), update: f(p1, p2) } + } + + fn new(init: S) -> Self { + Stats { upsert: init, delete: init, insert: init, update: init } + } + } + + fn make_threads() -> Vec> { + let mut t = Vec::with_capacity(NUM_THREADS); + for _ in 0..NUM_THREADS { + t.push(thread::spawn(move || {})); + } + t + } + + let stats = [Stats::new(0); NUM_THREADS]; + make_threads(); + + { + let Stats { ref upsert, ref delete, ref insert, ref update } = stats.iter().fold( + Stats::new(0), |res, &s| res.dot(s, |x: Key, y: Key| x.wrapping_add(y))); + println!("upserts: {}, deletes: {}, inserts: {}, updates: {}", + upsert, delete, insert, update); + } +}