From 3248bc5bd0384712e70f67eb90daa38ae5e5a21f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 9 Dec 2014 15:14:01 +0530 Subject: [PATCH 1/8] librustc::session : Make cgoptions macro more generic --- src/librustc/session/config.rs | 115 +++++++++++++++++---------------- 1 file changed, 60 insertions(+), 55 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 72b1669843a67..a108982f03124 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -370,7 +370,7 @@ impl Passes { } } -/// Declare a macro that will define all CodegenOptions fields and parsers all +/// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all /// at once. The goal of this macro is to define an interface that can be /// programmatically used by the option parser in order to initialize the struct /// without hardcoding field names all over the place. @@ -380,23 +380,67 @@ impl Passes { /// cgsetters module which is a bunch of generated code to parse an option into /// its respective field in the struct. There are a few hand-written parsers for /// parsing specific types of values in this module. -macro_rules! cgoptions { - ($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) => +macro_rules! options { + ($struct_name:ident, $setter_name:ident, $defaultfn:ident, + $buildfn:ident, $prefix:expr, $outputname:expr, + $stat:ident, $mod_desc:ident, $mod_set:ident, + $($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) => ( #[derive(Clone)] - pub struct CodegenOptions { $(pub $opt: $t),* } + pub struct $struct_name { $(pub $opt: $t),* } - pub fn basic_codegen_options() -> CodegenOptions { - CodegenOptions { $($opt: $init),* } + pub fn $defaultfn() -> $struct_name { + $struct_name { $($opt: $init),* } } - pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool; - pub const CG_OPTIONS: &'static [(&'static str, CodegenSetter, + pub fn $buildfn(matches: &getopts::Matches) -> $struct_name + { + let mut op = $defaultfn(); + for option in matches.opt_strs($prefix).into_iter() { + let mut iter = option.splitn(1, '='); + let key = iter.next().unwrap(); + let value = iter.next(); + let option_to_lookup = key.replace("-", "_"); + let mut found = false; + for &(candidate, setter, opt_type_desc, _) in $stat.iter() { + if option_to_lookup != candidate { continue } + if !setter(&mut op, value) { + match (value, opt_type_desc) { + (Some(..), None) => { + early_error(format!("{} option `{}` takes no \ + value", $outputname, key)[]) + } + (None, Some(type_desc)) => { + early_error(format!("{0} option `{1}` requires \ + {2} ({3} {1}=)", + $outputname, key, type_desc, $prefix)[]) + } + (Some(value), Some(type_desc)) => { + early_error(format!("incorrect value `{}` for {} \ + option `{}` - {} was expected", + value, $outputname, key, type_desc)[]) + } + (None, None) => unreachable!() + } + } + found = true; + break; + } + if !found { + early_error(format!("unknown codegen option: `{}`", + key)[]); + } + } + return op; + } + + pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool; + pub const $stat: &'static [(&'static str, $setter_name, Option<&'static str>, &'static str)] = - &[ $( (stringify!($opt), cgsetters::$opt, cg_type_descs::$parse, $desc) ),* ]; + &[ $( (stringify!($opt), $mod_set::$opt, $mod_desc::$parse, $desc) ),* ]; #[allow(non_upper_case_globals)] - mod cg_type_descs { + mod $mod_desc { pub const parse_bool: Option<&'static str> = None; pub const parse_opt_bool: Option<&'static str> = None; pub const parse_string: Option<&'static str> = Some("a string"); @@ -410,11 +454,11 @@ macro_rules! cgoptions { Some("a number"); } - mod cgsetters { - use super::{CodegenOptions, Passes, SomePasses, AllPasses}; + mod $mod_set { + use super::{$struct_name, Passes, SomePasses, AllPasses}; $( - pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool { + pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { $parse(&mut cg.$opt, v) } )* @@ -506,7 +550,9 @@ macro_rules! cgoptions { } ) } -cgoptions! { +options! {CodegenOptions, CodegenSetter, basic_codegen_options, + build_codegen_options, "C", "codegen", + CG_OPTIONS, cg_type_desc, cgsetters, ar: Option = (None, parse_opt_string, "tool to assemble archives with"), linker: Option = (None, parse_opt_string, @@ -562,47 +608,6 @@ cgoptions! { "Optimize with possible levels 0-3"), } -pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions -{ - let mut cg = basic_codegen_options(); - for option in matches.opt_strs("C").into_iter() { - let mut iter = option.splitn(1, '='); - let key = iter.next().unwrap(); - let value = iter.next(); - let option_to_lookup = key.replace("-", "_"); - let mut found = false; - for &(candidate, setter, opt_type_desc, _) in CG_OPTIONS.iter() { - if option_to_lookup != candidate { continue } - if !setter(&mut cg, value) { - match (value, opt_type_desc) { - (Some(..), None) => { - early_error(&format!("codegen option `{}` takes no \ - value", key)[]) - } - (None, Some(type_desc)) => { - early_error(&format!("codegen option `{0}` requires \ - {1} (-C {0}=)", - key, type_desc)[]) - } - (Some(value), Some(type_desc)) => { - early_error(&format!("incorrect value `{}` for codegen \ - option `{}` - {} was expected", - value, key, type_desc)[]) - } - (None, None) => unreachable!() - } - } - found = true; - break; - } - if !found { - early_error(&format!("unknown codegen option: `{}`", - key)[]); - } - } - return cg; -} - pub fn default_lib_output() -> CrateType { CrateTypeRlib } From 7e87ea9fc5c3ab5d6c853e6d3ae0603f19526eb4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 9 Dec 2014 15:25:49 +0530 Subject: [PATCH 2/8] librustc::session : Make DebuggingOpts use the options! macro --- .../middle/infer/region_inference/graphviz.rs | 3 +- src/librustc/session/config.rs | 202 +++++++----------- src/librustc/session/mod.rs | 31 ++- src/librustc_borrowck/borrowck/fragments.rs | 3 +- src/librustc_driver/driver.rs | 10 +- src/librustc_driver/lib.rs | 14 +- src/librustc_driver/pretty.rs | 17 +- src/librustc_driver/test.rs | 2 +- src/librustc_trans/back/link.rs | 2 +- src/librustc_trans/back/write.rs | 2 +- 10 files changed, 118 insertions(+), 168 deletions(-) diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index 29feaf358e2e2..0d6ab9c273b75 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -22,7 +22,6 @@ use middle::ty; use super::Constraint; use middle::infer::SubregionOrigin; use middle::infer::region_inference::RegionVarBindings; -use session::config; use util::nodemap::{FnvHashMap, FnvHashSet}; use util::ppaux::Repr; @@ -55,7 +54,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, subject_node: ast::NodeId) { let tcx = region_vars.tcx; - if !region_vars.tcx.sess.debugging_opt(config::PRINT_REGION_GRAPH) { + if !region_vars.tcx.sess.opts.debugging_opts.print_region_graph { return; } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index a108982f03124..ca24c1f56a091 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -99,7 +99,7 @@ pub struct Options { pub parse_only: bool, pub no_trans: bool, pub no_analysis: bool, - pub debugging_opts: u64, + pub debugging_opts: DebuggingOptions, /// Whether to write dependency files. It's (enabled, optional filename). pub write_dependency_info: (bool, Option), pub prints: Vec, @@ -224,7 +224,7 @@ pub fn basic_options() -> Options { parse_only: false, no_trans: false, no_analysis: false, - debugging_opts: 0, + debugging_opts: basic_debugging_options(), write_dependency_info: (false, None), prints: Vec::new(), cg: basic_codegen_options(), @@ -257,103 +257,6 @@ pub enum CrateType { CrateTypeStaticlib, } -macro_rules! debugging_opts { - ([ $opt:ident ] $cnt:expr ) => ( - pub const $opt: u64 = 1 << $cnt; - ); - ([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => ( - pub const $opt: u64 = 1 << $cnt; - debugging_opts! { [ $($rest),* ] $cnt + 1 } - ) -} - -debugging_opts! { - [ - VERBOSE, - TIME_PASSES, - COUNT_LLVM_INSNS, - TIME_LLVM_PASSES, - TRANS_STATS, - ASM_COMMENTS, - NO_VERIFY, - BORROWCK_STATS, - NO_LANDING_PADS, - DEBUG_LLVM, - COUNT_TYPE_SIZES, - META_STATS, - GC, - PRINT_LINK_ARGS, - PRINT_LLVM_PASSES, - AST_JSON, - AST_JSON_NOEXPAND, - LS, - SAVE_ANALYSIS, - PRINT_MOVE_FRAGMENTS, - FLOWGRAPH_PRINT_LOANS, - FLOWGRAPH_PRINT_MOVES, - FLOWGRAPH_PRINT_ASSIGNS, - FLOWGRAPH_PRINT_ALL, - PRINT_REGION_GRAPH, - PARSE_ONLY, - NO_TRANS, - NO_ANALYSIS, - UNSTABLE_OPTIONS, - PRINT_ENUM_SIZES - ] - 0 -} - -pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> { - vec![("verbose", "in general, enable more debug printouts", VERBOSE), - ("time-passes", "measure time of each rustc pass", TIME_PASSES), - ("count-llvm-insns", "count where LLVM \ - instrs originate", COUNT_LLVM_INSNS), - ("time-llvm-passes", "measure time of each LLVM pass", - TIME_LLVM_PASSES), - ("trans-stats", "gather trans statistics", TRANS_STATS), - ("asm-comments", "generate comments into the assembly (may change behavior)", - ASM_COMMENTS), - ("no-verify", "skip LLVM verification", NO_VERIFY), - ("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS), - ("no-landing-pads", "omit landing pads for unwinding", - NO_LANDING_PADS), - ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM), - ("count-type-sizes", "count the sizes of aggregate types", - COUNT_TYPE_SIZES), - ("meta-stats", "gather metadata statistics", META_STATS), - ("print-link-args", "Print the arguments passed to the linker", - PRINT_LINK_ARGS), - ("gc", "Garbage collect shared data (experimental)", GC), - ("print-llvm-passes", - "Prints the llvm optimization passes being run", - PRINT_LLVM_PASSES), - ("ast-json", "Print the AST as JSON and halt", AST_JSON), - ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND), - ("ls", "List the symbols defined by a library crate", LS), - ("save-analysis", "Write syntax and type analysis information \ - in addition to normal output", SAVE_ANALYSIS), - ("print-move-fragments", "Print out move-fragment data for every fn", - PRINT_MOVE_FRAGMENTS), - ("flowgraph-print-loans", "Include loan analysis data in \ - --pretty flowgraph output", FLOWGRAPH_PRINT_LOANS), - ("flowgraph-print-moves", "Include move analysis data in \ - --pretty flowgraph output", FLOWGRAPH_PRINT_MOVES), - ("flowgraph-print-assigns", "Include assignment analysis data in \ - --pretty flowgraph output", FLOWGRAPH_PRINT_ASSIGNS), - ("flowgraph-print-all", "Include all dataflow analysis data in \ - --pretty flowgraph output", FLOWGRAPH_PRINT_ALL), - ("print-region-graph", "Prints region inference graph. \ - Use with RUST_REGION_GRAPH=help for more info", - PRINT_REGION_GRAPH), - ("parse-only", "Parse only; do not compile, assemble, or link", PARSE_ONLY), - ("no-trans", "Run all passes except translation; no output", NO_TRANS), - ("no-analysis", "Parse and expand the source, but run no analysis and", - NO_ANALYSIS), - ("unstable-options", "Adds unstable command line options to rustc interface", - UNSTABLE_OPTIONS), - ("print-enum-sizes", "Print the size of enums and their variants", PRINT_ENUM_SIZES), - ] -} #[derive(Clone)] pub enum Passes { @@ -387,6 +290,7 @@ macro_rules! options { $($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) => ( #[derive(Clone)] + #[allow(missing_copy_implementations)] pub struct $struct_name { $(pub $opt: $t),* } pub fn $defaultfn() -> $struct_name { @@ -439,7 +343,7 @@ macro_rules! options { Option<&'static str>, &'static str)] = &[ $( (stringify!($opt), $mod_set::$opt, $mod_desc::$parse, $desc) ),* ]; - #[allow(non_upper_case_globals)] + #[allow(non_upper_case_globals, dead_code)] mod $mod_desc { pub const parse_bool: Option<&'static str> = None; pub const parse_opt_bool: Option<&'static str> = None; @@ -454,6 +358,7 @@ macro_rules! options { Some("a number"); } + #[allow(dead_code)] mod $mod_set { use super::{$struct_name, Passes, SomePasses, AllPasses}; @@ -608,6 +513,73 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "Optimize with possible levels 0-3"), } + +options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, + build_debugging_options, "Z", "debugging", + DB_OPTIONS, db_type_desc, dbsetters, + verbose: bool = (false, parse_bool, + "in general, enable more debug printouts"), + time_passes: bool = (false, parse_bool, + "measure time of each rustc pass"), + count_llvm_insns: bool = (false, parse_bool, + "count where LLVM instrs originate"), + time_llvm_passes: bool = (false, parse_bool, + "measure time of each LLVM pass"), + trans_stats: bool = (false, parse_bool, + "gather trans statistics"), + asm_comments: bool = (false, parse_bool, + "generate comments into the assembly (may change behavior)"), + no_verify: bool = (false, parse_bool, + "skip LLVM verification"), + borrowck_stats: bool = (false, parse_bool, + "gather borrowck statistics"), + no_landing_pads: bool = (false, parse_bool, + "omit landing pads for unwinding"), + debug_llvm: bool = (false, parse_bool, + "enable debug output from LLVM"), + count_type_sizes: bool = (false, parse_bool, + "count the sizes of aggregate types"), + meta_stats: bool = (false, parse_bool, + "gather metadata statistics"), + print_link_args: bool = (false, parse_bool, + "Print the arguments passed to the linker"), + gc: bool = (false, parse_bool, + "Garbage collect shared data (experimental)"), + print_llvm_passes: bool = (false, parse_bool, + "Prints the llvm optimization passes being run"), + ast_json: bool = (false, parse_bool, + "Print the AST as JSON and halt"), + ast_json_noexpand: bool = (false, parse_bool, + "Print the pre-expansion AST as JSON and halt"), + ls: bool = (false, parse_bool, + "List the symbols defined by a library crate"), + save_analysis: bool = (false, parse_bool, + "Write syntax and type analysis information in addition to normal output"), + print_move_fragments: bool = (false, parse_bool, + "Print out move-fragment data for every fn"), + flowgraph_print_loans: bool = (false, parse_bool, + "Include loan analysis data in --pretty flowgraph output"), + flowgraph_print_moves: bool = (false, parse_bool, + "Include move analysis data in --pretty flowgraph output"), + flowgraph_print_assigns: bool = (false, parse_bool, + "Include assignment analysis data in --pretty flowgraph output"), + flowgraph_print_all: bool = (false, parse_bool, + "Include all dataflow analysis data in --pretty flowgraph output"), + print_region_graph: bool = (false, parse_bool, + "Prints region inference graph. \ + Use with RUST_REGION_GRAPH=help for more info"), + parse_only: bool = (false, parse_bool, + "Parse only; do not compile, assemble, or link"), + no_trans: bool = (false, parse_bool, + "Run all passes except translation; no output"), + no_analysis: bool = (false, parse_bool, + "Parse and expand the source, but run no analysis"), + unstable_options: bool = (false, parse_bool, + "Adds unstable command line options to rustc interface"), + print_enum_sizes: bool = (false, parse_bool, + "Print the size of enums and their variants"), +} + pub fn default_lib_output() -> CrateType { CrateTypeRlib } @@ -883,52 +855,36 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } - let mut debugging_opts = 0; - let debug_flags = matches.opt_strs("Z"); - let debug_map = debugging_opts_map(); - for debug_flag in debug_flags.iter() { - let mut this_bit = 0; - for &(name, _, bit) in debug_map.iter() { - if name == *debug_flag { - this_bit = bit; - break; - } - } - if this_bit == 0 { - early_error(&format!("unknown debug flag: {}", - *debug_flag)[]) - } - debugging_opts |= this_bit; - } + let debugging_opts = build_debugging_options(matches); let parse_only = if matches.opt_present("parse-only") { // FIXME(acrichto) remove this eventually early_warn("--parse-only is deprecated in favor of -Z parse-only"); true } else { - debugging_opts & PARSE_ONLY != 0 + debugging_opts.parse_only }; let no_trans = if matches.opt_present("no-trans") { // FIXME(acrichto) remove this eventually early_warn("--no-trans is deprecated in favor of -Z no-trans"); true } else { - debugging_opts & NO_TRANS != 0 + debugging_opts.no_trans }; let no_analysis = if matches.opt_present("no-analysis") { // FIXME(acrichto) remove this eventually early_warn("--no-analysis is deprecated in favor of -Z no-analysis"); true } else { - debugging_opts & NO_ANALYSIS != 0 + debugging_opts.no_analysis }; - if debugging_opts & DEBUG_LLVM != 0 { + if debugging_opts.debug_llvm { unsafe { llvm::LLVMSetDebug(1); } } let mut output_types = Vec::new(); - if !parse_only && !no_trans { + if !debugging_opts.parse_only && !no_trans { let unparsed_output_types = matches.opt_strs("emit"); for unparsed_output_type in unparsed_output_types.iter() { for part in unparsed_output_type.split(',') { @@ -998,7 +954,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } }; - let gc = debugging_opts & GC != 0; + let gc = debugging_opts.gc; let debuginfo = if matches.opt_present("g") { if matches.opt_present("debuginfo") { early_error("-g and --debuginfo both provided"); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 65dac1a5fac88..79e4d0f7aea30 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -164,9 +164,6 @@ impl Session { pub fn diagnostic<'a>(&'a self) -> &'a diagnostic::SpanHandler { &self.parse_sess.span_diagnostic } - pub fn debugging_opt(&self, opt: u64) -> bool { - (self.opts.debugging_opts & opt) != 0 - } pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { &self.parse_sess.span_diagnostic.cm } @@ -176,36 +173,36 @@ impl Session { self.span_bug(sp, &format!("impossible case reached: {}", msg)[]); } - pub fn verbose(&self) -> bool { self.debugging_opt(config::VERBOSE) } - pub fn time_passes(&self) -> bool { self.debugging_opt(config::TIME_PASSES) } + pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose } + pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes } pub fn count_llvm_insns(&self) -> bool { - self.debugging_opt(config::COUNT_LLVM_INSNS) + self.opts.debugging_opts.count_llvm_insns } pub fn count_type_sizes(&self) -> bool { - self.debugging_opt(config::COUNT_TYPE_SIZES) + self.opts.debugging_opts.count_type_sizes } pub fn time_llvm_passes(&self) -> bool { - self.debugging_opt(config::TIME_LLVM_PASSES) + self.opts.debugging_opts.time_llvm_passes } - pub fn trans_stats(&self) -> bool { self.debugging_opt(config::TRANS_STATS) } - pub fn meta_stats(&self) -> bool { self.debugging_opt(config::META_STATS) } - pub fn asm_comments(&self) -> bool { self.debugging_opt(config::ASM_COMMENTS) } - pub fn no_verify(&self) -> bool { self.debugging_opt(config::NO_VERIFY) } - pub fn borrowck_stats(&self) -> bool { self.debugging_opt(config::BORROWCK_STATS) } + pub fn trans_stats(&self) -> bool { self.opts.debugging_opts.trans_stats } + pub fn meta_stats(&self) -> bool { self.opts.debugging_opts.meta_stats } + pub fn asm_comments(&self) -> bool { self.opts.debugging_opts.asm_comments } + pub fn no_verify(&self) -> bool { self.opts.debugging_opts.no_verify } + pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats } pub fn print_llvm_passes(&self) -> bool { - self.debugging_opt(config::PRINT_LLVM_PASSES) + self.opts.debugging_opts.print_llvm_passes } pub fn lto(&self) -> bool { self.opts.cg.lto } pub fn no_landing_pads(&self) -> bool { - self.debugging_opt(config::NO_LANDING_PADS) + self.opts.debugging_opts.no_landing_pads } pub fn unstable_options(&self) -> bool { - self.debugging_opt(config::UNSTABLE_OPTIONS) + self.opts.debugging_opts.unstable_options } pub fn print_enum_sizes(&self) -> bool { - self.debugging_opt(config::PRINT_ENUM_SIZES) + self.opts.debugging_opts.print_enum_sizes } pub fn sysroot<'a>(&'a self) -> &'a Path { match self.opts.maybe_sysroot { diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index 1b12020821771..e2942719f2a47 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -19,7 +19,6 @@ use borrowck::LoanPathKind::{LpVar, LpUpvar, LpDowncast, LpExtend}; use borrowck::LoanPathElem::{LpDeref, LpInterior}; use borrowck::move_data::{InvalidMovePathIndex}; use borrowck::move_data::{MoveData, MovePathIndex}; -use rustc::session::config; use rustc::middle::ty; use rustc::middle::mem_categorization as mc; use rustc::util::ppaux::{Repr, UserString}; @@ -133,7 +132,7 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>, let span_err = attrs.iter().any(|a| a.check_name("rustc_move_fragments")); - let print = tcx.sess.debugging_opt(config::PRINT_MOVE_FRAGMENTS); + let print = tcx.sess.opts.debugging_opts.print_move_fragments; (span_err, print) }; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 019691c1e1027..c5ade686dfb46 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -142,7 +142,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) } }); - if sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0 { + if sess.opts.debugging_opts.ast_json_noexpand { println!("{}", json::as_json(&krate)); } @@ -334,7 +334,7 @@ pub fn assign_node_ids_and_map<'ast>(sess: &Session, let map = time(sess.time_passes(), "assigning node ids and indexing ast", forest, |forest| ast_map::map_crate(forest, NodeIdAssigner { sess: sess })); - if sess.opts.debugging_opts & config::AST_JSON != 0 { + if sess.opts.debugging_opts.ast_json { println!("{}", json::as_json(map.krate())); } @@ -484,7 +484,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, } fn save_analysis(sess: &Session) -> bool { - (sess.opts.debugging_opts & config::SAVE_ANALYSIS) != 0 + sess.opts.debugging_opts.save_analysis } pub fn phase_save_analysis(sess: &Session, @@ -575,7 +575,7 @@ pub fn stop_after_phase_1(sess: &Session) -> bool { if sess.opts.show_span.is_some() { return true; } - return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0; + return sess.opts.debugging_opts.ast_json_noexpand; } pub fn stop_after_phase_2(sess: &Session) -> bool { @@ -583,7 +583,7 @@ pub fn stop_after_phase_2(sess: &Session) -> bool { debug!("invoked with --no-analysis, returning early from compile_input"); return true; } - return sess.opts.debugging_opts & config::AST_JSON != 0; + return sess.opts.debugging_opts.ast_json; } pub fn stop_after_phase_5(sess: &Session) -> bool { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 27e1eaacdfd99..c4ecb6b7b0634 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -378,13 +378,13 @@ Available lint options: fn describe_debug_flags() { println!("\nAvailable debug options:\n"); - let r = config::debugging_opts_map(); - for tuple in r.iter() { - match *tuple { - (ref name, ref desc, _) => { - println!(" -Z {:>20} -- {}", *name, *desc); - } - } + for &(name, _, opt_type_desc, desc) in config::DB_OPTIONS.iter() { + let (width, extra) = match opt_type_desc { + Some(..) => (21, "=val"), + None => (25, "") + }; + println!(" -Z {:>width$}{} -- {}", name.replace("_", "-"), + extra, desc, width=width); } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 7592fbc05b338..1765c80f9437b 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -23,7 +23,7 @@ use rustc::middle::ty; use rustc::middle::cfg; use rustc::middle::cfg::graphviz::LabelledCFG; use rustc::session::Session; -use rustc::session::config::{self, Input}; +use rustc::session::config::Input; use rustc::util::ppaux; use rustc_borrowck as borrowck; use rustc_borrowck::graphviz as borrowck_dot; @@ -305,19 +305,18 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { } fn gather_flowgraph_variants(sess: &Session) -> Vec { - let print_loans = config::FLOWGRAPH_PRINT_LOANS; - let print_moves = config::FLOWGRAPH_PRINT_MOVES; - let print_assigns = config::FLOWGRAPH_PRINT_ASSIGNS; - let print_all = config::FLOWGRAPH_PRINT_ALL; - let opt = |&: print_which| sess.debugging_opt(print_which); + let print_loans = sess.opts.debugging_opts.flowgraph_print_loans; + let print_moves = sess.opts.debugging_opts.flowgraph_print_moves; + let print_assigns = sess.opts.debugging_opts.flowgraph_print_assigns; + let print_all = sess.opts.debugging_opts.flowgraph_print_all; let mut variants = Vec::new(); - if opt(print_all) || opt(print_loans) { + if print_all || print_loans { variants.push(borrowck_dot::Loans); } - if opt(print_all) || opt(print_moves) { + if print_all || print_moves { variants.push(borrowck_dot::Moves); } - if opt(print_all) || opt(print_assigns) { + if print_all || print_assigns { variants.push(borrowck_dot::Assigns); } variants diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index a798ec9aaf760..f68c76f4c4424 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -99,7 +99,7 @@ fn test_env(source_string: &str, { let mut options = config::basic_options(); - options.debugging_opts |= config::VERBOSE; + options.debugging_opts.verbose = true; let codemap = CodeMap::new(); let diagnostic_handler = diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 43f8c677e303b..351be70cf5261 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -778,7 +778,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, cmd.arg("-lcompiler-rt"); } - if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 { + if sess.opts.debugging_opts.print_link_args { println!("{}", &cmd); } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index e0ba6d569cc03..c818dda7581bd 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -715,7 +715,7 @@ pub fn run_passes(sess: &Session, cmd.args(&sess.target.target.options.post_link_args[]); - if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 { + if sess.opts.debugging_opts.print_link_args { println!("{}", &cmd); } From efaf613497da355fa3afaeaa75eaf95b55991e4e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 9 Dec 2014 21:33:05 +0530 Subject: [PATCH 3/8] librustc::metadata : Allow passing a string to read_plugin_metadata --- src/librustc/metadata/creader.rs | 31 ++++++++++++++++++++++++------- src/librustc/plugin/load.rs | 4 ++-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 310874c311b12..7615ff82bd257 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -26,7 +26,7 @@ use syntax::ast; use syntax::abi; use syntax::attr; use syntax::attr::AttrMetaMethods; -use syntax::codemap::{Span, mk_sp}; +use syntax::codemap::{DUMMY_SP, Span, mk_sp}; use syntax::parse; use syntax::parse::token::InternedString; use syntax::parse::token; @@ -445,8 +445,20 @@ impl<'a> CrateReader<'a> { } pub fn read_plugin_metadata<'b>(&'b mut self, - vi: &'b ast::ViewItem) -> PluginMetadata<'b> { - let info = self.extract_crate_info(vi).unwrap(); + krate: CrateOrString<'b>) -> PluginMetadata<'b> { + let (info, span) = match krate { + CrateOrString::Krate(c) => { + (self.extract_crate_info(c).unwrap(), c.span) + } + CrateOrString::Str(s) => { + (CrateInfo { + name: s.to_string(), + ident: s.to_string(), + id: ast::DUMMY_NODE_ID, + should_link: true, + }, DUMMY_SP) + } + }; let target_triple = &self.sess.opts.target_triple[]; let is_cross = target_triple != config::host_triple(); let mut should_link = info.should_link && !is_cross; @@ -455,7 +467,7 @@ impl<'a> CrateReader<'a> { let name = info.name.clone(); let mut load_ctxt = loader::Context { sess: self.sess, - span: vi.span, + span: span, ident: &ident[], crate_name: &name[], hash: None, @@ -485,8 +497,8 @@ impl<'a> CrateReader<'a> { let register = should_link && self.existing_match(info.name.as_slice(), None).is_none(); let metadata = if register { // Register crate now to avoid double-reading metadata - let (_, cmd, _) = self.register_crate(&None, &info.ident[], - &info.name[], vi.span, library); + let (_, cmd, _) = self.register_crate(&None, info.ident[], + info.name[], span, library); PMDSource::Registered(cmd) } else { // Not registering the crate; just hold on to the metadata @@ -498,12 +510,17 @@ impl<'a> CrateReader<'a> { metadata: metadata, dylib: dylib, info: info, - vi_span: vi.span, + vi_span: span, target_only: target_only, } } } +pub enum CrateOrString<'a> { + Krate(&'a ast::ViewItem), + Str(&'a str) +} + impl<'a> PluginMetadata<'a> { /// Read exported macros pub fn exported_macros(&self) -> Vec { diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 87f5ba0246fc3..e1f5c10a1a4e0 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -11,7 +11,7 @@ //! Used by `rustc` when loading a plugin, or a crate with exported macros. use session::Session; -use metadata::creader::CrateReader; +use metadata::creader::{CrateOrString, CrateReader}; use plugin::registry::Registry; use std::mem; @@ -175,7 +175,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } if load_macros || load_registrar { - let pmd = self.reader.read_plugin_metadata(vi); + let pmd = self.reader.read_plugin_metadata(CrateOrString::Krate(vi)); if load_macros { macros = pmd.exported_macros(); } From 9f5f706f96e5940a6149257feda6a70844067d7a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 9 Dec 2014 22:14:08 +0530 Subject: [PATCH 4/8] librustc::plugin : make PluginLoader usable for loading argument-specified plugins --- src/librustc/metadata/creader.rs | 1 + src/librustc/plugin/load.rs | 56 ++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 7615ff82bd257..2acefd5a8a682 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -516,6 +516,7 @@ impl<'a> CrateReader<'a> { } } +#[deriving(Copy)] pub enum CrateOrString<'a> { Krate(&'a ast::ViewItem), Str(&'a str) diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index e1f5c10a1a4e0..a94ddf61a5512 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -160,6 +160,21 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } } + self.load_plugin(CrateOrString::Krate(vi), plugin_attr, macro_selection, reexport) + } + + fn visit_mac(&mut self, _: &ast::Mac) { + // bummer... can't see plugins inside macros. + // do nothing. + } +} + +impl<'a> PluginLoader<'a> { + pub fn load_plugin<'b>(&mut self, + c: CrateOrString<'b>, + plugin_attr: Option>, + macro_selection: Option>, + reexport: HashSet) { let mut macros = vec![]; let mut registrar = None; @@ -169,13 +184,15 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { }; let load_registrar = plugin_attr.is_some(); - if load_macros && !self.span_whitelist.contains(&vi.span) { - self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \ - the crate root"); - } + if let CrateOrString::Krate(vi) = c { + if load_macros && !self.span_whitelist.contains(&vi.span) { + self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \ + the crate root"); + } + } if load_macros || load_registrar { - let pmd = self.reader.read_plugin_metadata(CrateOrString::Krate(vi)); + let pmd = self.reader.read_plugin_metadata(c); if load_macros { macros = pmd.exported_macros(); } @@ -195,7 +212,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } if let Some((lib, symbol)) = registrar { - let fun = self.dylink_registrar(vi, lib, symbol); + let fun = self.dylink_registrar(c, lib, symbol); self.plugins.registrars.push(PluginRegistrar { fun: fun, args: plugin_attr.unwrap(), @@ -203,16 +220,9 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } } - fn visit_mac(&mut self, _: &ast::Mac) { - // bummer... can't see plugins inside macros. - // do nothing. - } -} - -impl<'a> PluginLoader<'a> { // Dynamically link a registrar function into the compiler process. - fn dylink_registrar(&mut self, - vi: &ast::ViewItem, + fn dylink_registrar<'b>(&mut self, + c: CrateOrString<'b>, path: Path, symbol: String) -> PluginRegistrarFun { // Make sure the path contains a / or the linker will search for it. @@ -223,7 +233,13 @@ impl<'a> PluginLoader<'a> { // this is fatal: there are almost certainly macros we need // inside this crate, so continue would spew "macro undefined" // errors - Err(err) => self.sess.span_fatal(vi.span, &err[]) + Err(err) => { + if let CrateOrString::Krate(cr) = c { + self.sess.span_fatal(cr.span, &err[]) + } else { + self.sess.fatal(&err[]) + } + } }; unsafe { @@ -233,7 +249,13 @@ impl<'a> PluginLoader<'a> { mem::transmute::<*mut u8,PluginRegistrarFun>(registrar) } // again fatal if we can't register macros - Err(err) => self.sess.span_fatal(vi.span, &err[]) + Err(err) => { + if let CrateOrString::Krate(cr) = c { + self.sess.span_fatal(cr.span, &err[]) + } else { + self.sess.fatal(&err[]) + } + } }; // Intentionally leak the dynamic library. We can't ever unload it From c41cafb10c3e1cd5063bcacd663d0fc17fddc8c3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 9 Dec 2014 22:55:37 +0530 Subject: [PATCH 5/8] librustc_driver: Add support for loading plugins via command line (fixes #15446) --- src/librustc/metadata/creader.rs | 2 +- src/librustc/plugin/load.rs | 37 ++++++++++++++++---------------- src/librustc/session/config.rs | 2 ++ src/librustc_driver/driver.rs | 4 ++-- src/librustc_driver/lib.rs | 4 +++- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 2acefd5a8a682..3ab5b0a3bc463 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -516,7 +516,7 @@ impl<'a> CrateReader<'a> { } } -#[deriving(Copy)] +#[derive(Copy)] pub enum CrateOrString<'a> { Krate(&'a ast::ViewItem), Str(&'a str) diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index a94ddf61a5512..ef8a89c40fb5a 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -44,11 +44,11 @@ pub struct Plugins { pub registrars: Vec, } -struct PluginLoader<'a> { +pub struct PluginLoader<'a> { sess: &'a Session, span_whitelist: HashSet, reader: CrateReader<'a>, - plugins: Plugins, + pub plugins: Plugins, } impl<'a> PluginLoader<'a> { @@ -67,7 +67,7 @@ impl<'a> PluginLoader<'a> { /// Read plugin metadata and dynamically load registrar functions. pub fn load_plugins(sess: &Session, krate: &ast::Crate, - addl_plugins: Option) -> Plugins { + addl_plugins: Option>) -> Plugins { let mut loader = PluginLoader::new(sess); // We need to error on `#[macro_use] extern crate` when it isn't at the @@ -79,19 +79,14 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate, visit::walk_crate(&mut loader, krate); - let mut plugins = loader.plugins; - - match addl_plugins { - Some(addl_plugins) => { - // Add in the additional plugins requested by the frontend - let Plugins { macros: addl_macros, registrars: addl_registrars } = addl_plugins; - plugins.macros.extend(addl_macros.into_iter()); - plugins.registrars.extend(addl_registrars.into_iter()); + if let Some(plugins) = addl_plugins { + for plugin in plugins.iter() { + loader.load_plugin(CrateOrString::Str(plugin.as_slice()), + None, None, None) } - None => () } - return plugins; + return loader.plugins; } // note that macros aren't expanded yet, and therefore macros can't add plugins. @@ -160,7 +155,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } } - self.load_plugin(CrateOrString::Krate(vi), plugin_attr, macro_selection, reexport) + self.load_plugin(CrateOrString::Krate(vi), plugin_attr, macro_selection, Some(reexport)) } fn visit_mac(&mut self, _: &ast::Mac) { @@ -174,13 +169,13 @@ impl<'a> PluginLoader<'a> { c: CrateOrString<'b>, plugin_attr: Option>, macro_selection: Option>, - reexport: HashSet) { + reexport: Option>) { let mut macros = vec![]; let mut registrar = None; - let load_macros = match macro_selection.as_ref() { - Some(sel) => sel.len() != 0 || reexport.len() != 0, - None => true, + let load_macros = match (macro_selection.as_ref(), reexport.as_ref()) { + (Some(sel), Some(re)) => sel.len() != 0 || re.len() != 0, + _ => true, }; let load_registrar = plugin_attr.is_some(); @@ -207,7 +202,11 @@ impl<'a> PluginLoader<'a> { None => true, Some(sel) => sel.contains(&name), }; - def.export = reexport.contains(&name); + def.export = if let Some(ref re) = reexport { + re.contains(&name) + } else { + false // Don't reexport macros from crates loaded from the command line + }; self.plugins.macros.push(def); } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ca24c1f56a091..c506d32fc94f2 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -574,6 +574,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "Run all passes except translation; no output"), no_analysis: bool = (false, parse_bool, "Parse and expand the source, but run no analysis"), + extra_plugins: Vec = (Vec::new(), parse_list, + "load extra plugins"), unstable_options: bool = (false, parse_bool, "Adds unstable command line options to rustc interface"), print_enum_sizes: bool = (false, parse_bool, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c5ade686dfb46..c2af4315b06a2 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -47,7 +47,7 @@ pub fn compile_input(sess: Session, input: &Input, outdir: &Option, output: &Option, - addl_plugins: Option) { + addl_plugins: Option>) { // We need nested scopes here, because the intermediate results can keep // large chunks of memory alive and we want to free them as soon as // possible to keep the peak memory usage low @@ -166,7 +166,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) pub fn phase_2_configure_and_expand(sess: &Session, mut krate: ast::Crate, crate_name: &str, - addl_plugins: Option) + addl_plugins: Option>) -> Option { let time_passes = sess.time_passes(); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index c4ecb6b7b0634..da2ec948cc96a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -53,6 +53,7 @@ use rustc::session::config::{Input, PrintRequest, UnstableFeatures}; use rustc::lint::Lint; use rustc::lint; use rustc::metadata; +use rustc::metadata::creader::CrateOrString::Str; use rustc::DIAGNOSTICS; use std::cmp::Ordering::Equal; @@ -185,7 +186,8 @@ fn run_compiler(args: &[String]) { return; } - driver::compile_input(sess, cfg, &input, &odir, &ofile, None); + let plugins = sess.opts.debugging_opts.extra_plugins.clone(); + driver::compile_input(sess, cfg, &input, &odir, &ofile, Some(plugins)); } pub fn get_unstable_features_setting() -> UnstableFeatures { From 0bd022c893b00e0bb76d84bbbf8ccf7f685aad9c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 11 Dec 2014 01:48:23 +0530 Subject: [PATCH 6/8] libsyntax: add COMMAND_LINE_SP and use it for spans generated from the command line --- src/librustc/metadata/creader.rs | 4 ++-- src/libsyntax/codemap.rs | 7 +++++++ src/libsyntax/diagnostic.rs | 20 ++++++++++++++------ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 3ab5b0a3bc463..24befbd44a106 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -26,7 +26,7 @@ use syntax::ast; use syntax::abi; use syntax::attr; use syntax::attr::AttrMetaMethods; -use syntax::codemap::{DUMMY_SP, Span, mk_sp}; +use syntax::codemap::{COMMAND_LINE_SP, Span, mk_sp}; use syntax::parse; use syntax::parse::token::InternedString; use syntax::parse::token; @@ -456,7 +456,7 @@ impl<'a> CrateReader<'a> { ident: s.to_string(), id: ast::DUMMY_NODE_ID, should_link: true, - }, DUMMY_SP) + }, COMMAND_LINE_SP) } }; let target_triple = &self.sess.opts.target_triple[]; diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index d1768867f0da2..9a422e17bb4de 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -105,6 +105,11 @@ pub struct Span { pub const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: NO_EXPANSION }; +// Generic span to be used for code originating from the command line +pub const COMMAND_LINE_SP: Span = Span { lo: BytePos(0), + hi: BytePos(0), + expn_id: COMMAND_LINE_EXPN }; + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub struct Spanned { pub node: T, @@ -235,6 +240,8 @@ pub struct ExpnInfo { pub struct ExpnId(u32); pub const NO_EXPANSION: ExpnId = ExpnId(-1); +// For code appearing from the command line +pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(-2); impl ExpnId { pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId { diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 7e57709f33d0a..64fdb61f2ecee 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -13,7 +13,7 @@ pub use self::RenderSpan::*; pub use self::ColorConfig::*; use self::Destination::*; -use codemap::{Pos, Span}; +use codemap::{COMMAND_LINE_SP, Pos, Span}; use codemap; use diagnostics; @@ -368,6 +368,9 @@ impl Emitter for EmitterWriter { cmsp: Option<(&codemap::CodeMap, Span)>, msg: &str, code: Option<&str>, lvl: Level) { let error = match cmsp { + Some((cm, COMMAND_LINE_SP)) => emit(self, cm, + FileLine(COMMAND_LINE_SP), + msg, code, lvl, false), Some((cm, sp)) => emit(self, cm, FullSpan(sp), msg, code, lvl, false), None => print_diagnostic(self, "", lvl, msg, code), }; @@ -390,8 +393,11 @@ impl Emitter for EmitterWriter { fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, msg: &str, code: Option<&str>, lvl: Level, custom: bool) -> io::IoResult<()> { let sp = rsp.span(); - let ss = cm.span_to_string(sp); - let lines = cm.span_to_lines(sp); + let ss = if sp == COMMAND_LINE_SP { + "".to_string() + } else { + cm.span_to_string(sp) + }; if custom { // we want to tell compiletest/runtest to look at the last line of the // span (since `custom_highlight_lines` displays an arrow to the end of @@ -400,15 +406,17 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, let ses = cm.span_to_string(span_end); try!(print_diagnostic(dst, &ses[], lvl, msg, code)); if rsp.is_full_span() { - try!(custom_highlight_lines(dst, cm, sp, lvl, lines)); + try!(custom_highlight_lines(dst, cm, sp, lvl, cm.span_to_lines(sp))); } } else { try!(print_diagnostic(dst, &ss[], lvl, msg, code)); if rsp.is_full_span() { - try!(highlight_lines(dst, cm, sp, lvl, lines)); + try!(highlight_lines(dst, cm, sp, lvl, cm.span_to_lines(sp))); } } - try!(print_macro_backtrace(dst, cm, sp)); + if sp != COMMAND_LINE_SP { + try!(print_macro_backtrace(dst, cm, sp)); + } match code { Some(code) => match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) { From f4a26726000d2b2144b2f929ad0555868d85f32f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 20 Dec 2014 08:09:43 +0530 Subject: [PATCH 7/8] Add test for -Z extra-plugins --- src/librustc/metadata/creader.rs | 4 ++-- src/librustc/session/config.rs | 14 +++++++------ ...mdline.rs => lint-plugin-cmdline-allow.rs} | 0 .../lint-plugin-cmdline-load.rs | 21 +++++++++++++++++++ 4 files changed, 31 insertions(+), 8 deletions(-) rename src/test/run-pass-fulldeps/{lint-plugin-cmdline.rs => lint-plugin-cmdline-allow.rs} (100%) create mode 100644 src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 24befbd44a106..4a2981b8cdfe5 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -497,8 +497,8 @@ impl<'a> CrateReader<'a> { let register = should_link && self.existing_match(info.name.as_slice(), None).is_none(); let metadata = if register { // Register crate now to avoid double-reading metadata - let (_, cmd, _) = self.register_crate(&None, info.ident[], - info.name[], span, library); + let (_, cmd, _) = self.register_crate(&None, &info.ident[], + &info.name[], span, library); PMDSource::Registered(cmd) } else { // Not registering the crate; just hold on to the metadata diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index c506d32fc94f2..d9bb1d769bfbe 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -311,18 +311,20 @@ macro_rules! options { if !setter(&mut op, value) { match (value, opt_type_desc) { (Some(..), None) => { - early_error(format!("{} option `{}` takes no \ + early_error(&format!("{} option `{}` takes no \ value", $outputname, key)[]) } (None, Some(type_desc)) => { - early_error(format!("{0} option `{1}` requires \ + early_error(&format!("{0} option `{1}` requires \ {2} ({3} {1}=)", - $outputname, key, type_desc, $prefix)[]) + $outputname, key, + type_desc, $prefix)[]) } (Some(value), Some(type_desc)) => { - early_error(format!("incorrect value `{}` for {} \ + early_error(&format!("incorrect value `{}` for {} \ option `{}` - {} was expected", - value, $outputname, key, type_desc)[]) + value, $outputname, + key, type_desc)[]) } (None, None) => unreachable!() } @@ -331,7 +333,7 @@ macro_rules! options { break; } if !found { - early_error(format!("unknown codegen option: `{}`", + early_error(&format!("unknown codegen option: `{}`", key)[]); } } diff --git a/src/test/run-pass-fulldeps/lint-plugin-cmdline.rs b/src/test/run-pass-fulldeps/lint-plugin-cmdline-allow.rs similarity index 100% rename from src/test/run-pass-fulldeps/lint-plugin-cmdline.rs rename to src/test/run-pass-fulldeps/lint-plugin-cmdline-allow.rs diff --git a/src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs b/src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs new file mode 100644 index 0000000000000..1af26094f2315 --- /dev/null +++ b/src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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. + +// aux-build:lint_plugin_test.rs +// ignore-stage1 +// ignore-pretty: Random space appears with the pretty test +// compile-flags: -Z extra-plugins=lint_plugin_test + +fn lintme() { } //~ WARNING item is named 'lintme' + +#[allow(test_lint)] +pub fn main() { + fn lintme() { } +} From 6342aa62efd1b3aa7e1bc8f834f317290b11c519 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 8 Jan 2015 18:22:43 +0530 Subject: [PATCH 8/8] Ignore extra error from test for now --- src/compiletest/header.rs | 13 +++++++++++++ src/compiletest/runtest.rs | 10 ++++++++-- src/test/compile-fail/recursion.rs | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 2413a001ee805..374fd2e3ef02b 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -42,6 +42,8 @@ pub struct TestProps { pub pretty_compare_only: bool, // Patterns which must not appear in the output of a cfail test. pub forbid_output: Vec, + // Ignore errors which originate from a command line span + pub ignore_command_line: bool, } // Load any test directives embedded in the file @@ -60,6 +62,8 @@ pub fn load_props(testfile: &Path) -> TestProps { let mut pretty_mode = None; let mut pretty_compare_only = false; let mut forbid_output = Vec::new(); + let mut ignore_command_line = false; + iter_header(testfile, |ln| { match parse_error_pattern(ln) { Some(ep) => error_patterns.push(ep), @@ -102,6 +106,10 @@ pub fn load_props(testfile: &Path) -> TestProps { pretty_compare_only = parse_pretty_compare_only(ln); } + if !ignore_command_line { + ignore_command_line = parse_ignore_command_line(ln); + } + match parse_aux_build(ln) { Some(ab) => { aux_builds.push(ab); } None => {} @@ -140,6 +148,7 @@ pub fn load_props(testfile: &Path) -> TestProps { pretty_mode: pretty_mode.unwrap_or("normal".to_string()), pretty_compare_only: pretty_compare_only, forbid_output: forbid_output, + ignore_command_line: ignore_command_line, } } @@ -291,6 +300,10 @@ fn parse_pretty_compare_only(line: &str) -> bool { parse_name_directive(line, "pretty-compare-only") } +fn parse_ignore_command_line(line: &str) -> bool { + parse_name_directive(line, "ignore-command-line") +} + fn parse_exec_env(line: &str) -> Option<(String, String)> { parse_name_value_directive(line, "exec-env").map(|nv| { // nv is either FOO or FOO=BAR diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 5de93c5202922..a97d49134407d 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -104,7 +104,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) { if !props.error_patterns.is_empty() { fatal("both error pattern and expected errors specified"); } - check_expected_errors(expected_errors, testfile, &proc_res); + check_expected_errors(props, expected_errors, testfile, &proc_res); } else { check_error_patterns(props, testfile, output_to_check.as_slice(), &proc_res); } @@ -941,7 +941,8 @@ fn check_forbid_output(props: &TestProps, } } -fn check_expected_errors(expected_errors: Vec , +fn check_expected_errors(props: &TestProps, + expected_errors: Vec , testfile: &Path, proc_res: &ProcRes) { @@ -996,6 +997,11 @@ fn check_expected_errors(expected_errors: Vec , was_expected = true; } + if line.starts_with("") && + props.ignore_command_line { + was_expected = true; + } + if !was_expected && is_compiler_error_or_warning(line) { fatal_proc_rec(format!("unexpected compiler error or warning: '{}'", line).as_slice(), diff --git a/src/test/compile-fail/recursion.rs b/src/test/compile-fail/recursion.rs index da05514f76300..de326677c868d 100644 --- a/src/test/compile-fail/recursion.rs +++ b/src/test/compile-fail/recursion.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//~^^^^^^^^^^ ERROR overflow +// ignore-command-line: See https://github.com/rust-lang/rust/issues/20747 // // We also get a second error message at the top of file (dummy // span). This is not helpful, but also kind of annoying to prevent,