1414pub use self :: EntryFnType :: * ;
1515pub use self :: CrateType :: * ;
1616pub use self :: Passes :: * ;
17- pub use self :: OptLevel :: * ;
1817pub use self :: DebugInfoLevel :: * ;
1918
2019use session:: { early_error, early_warn, Session } ;
@@ -71,6 +70,18 @@ pub enum OutputType {
7170 DepInfo ,
7271}
7372
73+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
74+ pub enum ErrorOutputType {
75+ HumanReadable ( ColorConfig ) ,
76+ Json ,
77+ }
78+
79+ impl Default for ErrorOutputType {
80+ fn default ( ) -> ErrorOutputType {
81+ ErrorOutputType :: HumanReadable ( ColorConfig :: Auto )
82+ }
83+ }
84+
7485impl OutputType {
7586 fn is_compatible_with_codegen_units_and_single_output_file ( & self ) -> bool {
7687 match * self {
@@ -124,14 +135,14 @@ pub struct Options {
124135 pub test : bool ,
125136 pub parse_only : bool ,
126137 pub no_trans : bool ,
138+ pub error_format : ErrorOutputType ,
127139 pub treat_err_as_bug : bool ,
128140 pub incremental_compilation : bool ,
129141 pub dump_dep_graph : bool ,
130142 pub no_analysis : bool ,
131143 pub debugging_opts : DebuggingOptions ,
132144 pub prints : Vec < PrintRequest > ,
133145 pub cg : CodegenOptions ,
134- pub color : ColorConfig ,
135146 pub externs : HashMap < String , Vec < String > > ,
136147 pub crate_name : Option < String > ,
137148 /// An optional name to use as the crate for std during std injection,
@@ -221,7 +232,7 @@ pub fn basic_options() -> Options {
221232 Options {
222233 crate_types : Vec :: new ( ) ,
223234 gc : false ,
224- optimize : No ,
235+ optimize : OptLevel :: No ,
225236 debuginfo : NoDebugInfo ,
226237 lint_opts : Vec :: new ( ) ,
227238 lint_cap : None ,
@@ -241,7 +252,7 @@ pub fn basic_options() -> Options {
241252 debugging_opts : basic_debugging_options ( ) ,
242253 prints : Vec :: new ( ) ,
243254 cg : basic_codegen_options ( ) ,
244- color : ColorConfig :: Auto ,
255+ error_format : ErrorOutputType :: default ( ) ,
245256 externs : HashMap :: new ( ) ,
246257 crate_name : None ,
247258 alt_std_name : None ,
@@ -308,7 +319,7 @@ macro_rules! options {
308319 $struct_name { $( $opt: $init) ,* }
309320 }
310321
311- pub fn $buildfn( matches: & getopts:: Matches , color : ColorConfig ) -> $struct_name
322+ pub fn $buildfn( matches: & getopts:: Matches , error_format : ErrorOutputType ) -> $struct_name
312323 {
313324 let mut op = $defaultfn( ) ;
314325 for option in matches. opt_strs( $prefix) {
@@ -322,20 +333,20 @@ macro_rules! options {
322333 if !setter( & mut op, value) {
323334 match ( value, opt_type_desc) {
324335 ( Some ( ..) , None ) => {
325- early_error( color , & format!( "{} option `{}` takes no \
326- value", $outputname, key) )
336+ early_error( error_format , & format!( "{} option `{}` takes no \
337+ value", $outputname, key) )
327338 }
328339 ( None , Some ( type_desc) ) => {
329- early_error( color , & format!( "{0} option `{1}` requires \
330- {2} ({3} {1}=<value>)",
331- $outputname, key,
332- type_desc, $prefix) )
340+ early_error( error_format , & format!( "{0} option `{1}` requires \
341+ {2} ({3} {1}=<value>)",
342+ $outputname, key,
343+ type_desc, $prefix) )
333344 }
334345 ( Some ( value) , Some ( type_desc) ) => {
335- early_error( color , & format!( "incorrect value `{}` for {} \
336- option `{}` - {} was expected",
337- value, $outputname,
338- key, type_desc) )
346+ early_error( error_format , & format!( "incorrect value `{}` for {} \
347+ option `{}` - {} was expected",
348+ value, $outputname,
349+ key, type_desc) )
339350 }
340351 ( None , None ) => unreachable!( )
341352 }
@@ -344,8 +355,8 @@ macro_rules! options {
344355 break ;
345356 }
346357 if !found {
347- early_error( color , & format!( "unknown {} option: `{}`" ,
348- $outputname, key) ) ;
358+ early_error( error_format , & format!( "unknown {} option: `{}`" ,
359+ $outputname, key) ) ;
349360 }
350361 }
351362 return op;
@@ -861,6 +872,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
861872 "NAME=PATH" ) ,
862873 opt:: opt ( "" , "sysroot" , "Override the system root" , "PATH" ) ,
863874 opt:: multi ( "Z" , "" , "Set internal debugging options" , "FLAG" ) ,
875+ opt:: opt_u ( "" , "error-format" , "How errors and other messages are produced" , "human|json" ) ,
864876 opt:: opt ( "" , "color" , "Configure coloring of output:
865877 auto = colorize, if output goes to a tty (default);
866878 always = always colorize output;
@@ -903,15 +915,37 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
903915 None => ColorConfig :: Auto ,
904916
905917 Some ( arg) => {
906- early_error ( ColorConfig :: Auto , & format ! ( "argument for --color must be auto, always \
907- or never (instead was `{}`)",
908- arg) )
918+ early_error ( ErrorOutputType :: default ( ) , & format ! ( "argument for --color must be auto, \
919+ always or never (instead was `{}`)",
920+ arg) )
909921 }
910922 } ;
911923
924+ // We need the opts_present check because the driver will send us Matches
925+ // with only stable options if no unstable options are used. Since error-format
926+ // is unstable, it will not be present. We have to use opts_present not
927+ // opt_present because the latter will panic.
928+ let error_format = if matches. opts_present ( & [ "error-format" . to_owned ( ) ] ) {
929+ match matches. opt_str ( "error-format" ) . as_ref ( ) . map ( |s| & s[ ..] ) {
930+ Some ( "human" ) => ErrorOutputType :: HumanReadable ( color) ,
931+ Some ( "json" ) => ErrorOutputType :: Json ,
932+
933+ None => ErrorOutputType :: default ( ) ,
934+
935+ Some ( arg) => {
936+ early_error ( ErrorOutputType :: default ( ) , & format ! ( "argument for --error-format must \
937+ be human or json (instead was \
938+ `{}`)",
939+ arg) )
940+ }
941+ }
942+ } else {
943+ ErrorOutputType :: default ( )
944+ } ;
945+
912946 let unparsed_crate_types = matches. opt_strs ( "crate-type" ) ;
913947 let crate_types = parse_crate_types_from_list ( unparsed_crate_types)
914- . unwrap_or_else ( |e| early_error ( color , & e[ ..] ) ) ;
948+ . unwrap_or_else ( |e| early_error ( error_format , & e[ ..] ) ) ;
915949
916950 let mut lint_opts = vec ! ( ) ;
917951 let mut describe_lints = false ;
@@ -928,11 +962,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
928962
929963 let lint_cap = matches. opt_str ( "cap-lints" ) . map ( |cap| {
930964 lint:: Level :: from_str ( & cap) . unwrap_or_else ( || {
931- early_error ( color , & format ! ( "unknown lint level: `{}`" , cap) )
965+ early_error ( error_format , & format ! ( "unknown lint level: `{}`" , cap) )
932966 } )
933967 } ) ;
934968
935- let debugging_opts = build_debugging_options ( matches, color ) ;
969+ let debugging_opts = build_debugging_options ( matches, error_format ) ;
936970
937971 let parse_only = debugging_opts. parse_only ;
938972 let no_trans = debugging_opts. no_trans ;
@@ -958,7 +992,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
958992 "link" => OutputType :: Exe ,
959993 "dep-info" => OutputType :: DepInfo ,
960994 part => {
961- early_error ( color , & format ! ( "unknown emission type: `{}`" ,
995+ early_error ( error_format , & format ! ( "unknown emission type: `{}`" ,
962996 part) )
963997 }
964998 } ;
@@ -971,7 +1005,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
9711005 output_types. insert ( OutputType :: Exe , None ) ;
9721006 }
9731007
974- let mut cg = build_codegen_options ( matches, color ) ;
1008+ let mut cg = build_codegen_options ( matches, error_format ) ;
9751009
9761010 // Issue #30063: if user requests llvm-related output to one
9771011 // particular path, disable codegen-units.
@@ -983,11 +1017,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
9831017 } ) . collect ( ) ;
9841018 if !incompatible. is_empty ( ) {
9851019 for ot in & incompatible {
986- early_warn ( color , & format ! ( "--emit={} with -o incompatible with \
987- -C codegen-units=N for N > 1",
988- ot. shorthand( ) ) ) ;
1020+ early_warn ( error_format , & format ! ( "--emit={} with -o incompatible with \
1021+ -C codegen-units=N for N > 1",
1022+ ot. shorthand( ) ) ) ;
9891023 }
990- early_warn ( color , "resetting to default -C codegen-units=1" ) ;
1024+ early_warn ( error_format , "resetting to default -C codegen-units=1" ) ;
9911025 cg. codegen_units = 1 ;
9921026 }
9931027 }
@@ -1000,29 +1034,29 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
10001034 let opt_level = {
10011035 if matches. opt_present ( "O" ) {
10021036 if cg. opt_level . is_some ( ) {
1003- early_error ( color , "-O and -C opt-level both provided" ) ;
1037+ early_error ( error_format , "-O and -C opt-level both provided" ) ;
10041038 }
1005- Default
1039+ OptLevel :: Default
10061040 } else {
10071041 match cg. opt_level {
1008- None => No ,
1009- Some ( 0 ) => No ,
1010- Some ( 1 ) => Less ,
1011- Some ( 2 ) => Default ,
1012- Some ( 3 ) => Aggressive ,
1042+ None => OptLevel :: No ,
1043+ Some ( 0 ) => OptLevel :: No ,
1044+ Some ( 1 ) => OptLevel :: Less ,
1045+ Some ( 2 ) => OptLevel :: Default ,
1046+ Some ( 3 ) => OptLevel :: Aggressive ,
10131047 Some ( arg) => {
1014- early_error ( color , & format ! ( "optimization level needs to be \
1015- between 0-3 (instead was `{}`)",
1016- arg) ) ;
1048+ early_error ( error_format , & format ! ( "optimization level needs to be \
1049+ between 0-3 (instead was `{}`)",
1050+ arg) ) ;
10171051 }
10181052 }
10191053 }
10201054 } ;
1021- let debug_assertions = cg. debug_assertions . unwrap_or ( opt_level == No ) ;
1055+ let debug_assertions = cg. debug_assertions . unwrap_or ( opt_level == OptLevel :: No ) ;
10221056 let gc = debugging_opts. gc ;
10231057 let debuginfo = if matches. opt_present ( "g" ) {
10241058 if cg. debuginfo . is_some ( ) {
1025- early_error ( color , "-g and -C debuginfo both provided" ) ;
1059+ early_error ( error_format , "-g and -C debuginfo both provided" ) ;
10261060 }
10271061 FullDebugInfo
10281062 } else {
@@ -1031,16 +1065,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
10311065 Some ( 1 ) => LimitedDebugInfo ,
10321066 Some ( 2 ) => FullDebugInfo ,
10331067 Some ( arg) => {
1034- early_error ( color , & format ! ( "debug info level needs to be between \
1035- 0-2 (instead was `{}`)",
1036- arg) ) ;
1068+ early_error ( error_format , & format ! ( "debug info level needs to be between \
1069+ 0-2 (instead was `{}`)",
1070+ arg) ) ;
10371071 }
10381072 }
10391073 } ;
10401074
10411075 let mut search_paths = SearchPaths :: new ( ) ;
10421076 for s in & matches. opt_strs ( "L" ) {
1043- search_paths. add_path ( & s[ ..] , color ) ;
1077+ search_paths. add_path ( & s[ ..] , error_format ) ;
10441078 }
10451079
10461080 let libs = matches. opt_strs ( "l" ) . into_iter ( ) . map ( |s| {
@@ -1052,9 +1086,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
10521086 ( Some ( name) , "framework" ) => ( name, cstore:: NativeFramework ) ,
10531087 ( Some ( name) , "static" ) => ( name, cstore:: NativeStatic ) ,
10541088 ( _, s) => {
1055- early_error ( color , & format ! ( "unknown library kind `{}`, expected \
1056- one of dylib, framework, or static",
1057- s) ) ;
1089+ early_error ( error_format , & format ! ( "unknown library kind `{}`, expected \
1090+ one of dylib, framework, or static",
1091+ s) ) ;
10581092 }
10591093 } ;
10601094 ( name. to_string ( ) , kind)
@@ -1069,26 +1103,26 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
10691103 "file-names" => PrintRequest :: FileNames ,
10701104 "sysroot" => PrintRequest :: Sysroot ,
10711105 req => {
1072- early_error ( color , & format ! ( "unknown print request `{}`" , req) )
1106+ early_error ( error_format , & format ! ( "unknown print request `{}`" , req) )
10731107 }
10741108 }
10751109 } ) . collect :: < Vec < _ > > ( ) ;
10761110
10771111 if !cg. remark . is_empty ( ) && debuginfo == NoDebugInfo {
1078- early_warn ( color , "-C remark will not show source locations without \
1079- --debuginfo") ;
1112+ early_warn ( error_format , "-C remark will not show source locations without \
1113+ --debuginfo") ;
10801114 }
10811115
10821116 let mut externs = HashMap :: new ( ) ;
10831117 for arg in & matches. opt_strs ( "extern" ) {
10841118 let mut parts = arg. splitn ( 2 , '=' ) ;
10851119 let name = match parts. next ( ) {
10861120 Some ( s) => s,
1087- None => early_error ( color , "--extern value must not be empty" ) ,
1121+ None => early_error ( error_format , "--extern value must not be empty" ) ,
10881122 } ;
10891123 let location = match parts. next ( ) {
10901124 Some ( s) => s,
1091- None => early_error ( color , "--extern value must be of the format `foo=bar`" ) ,
1125+ None => early_error ( error_format , "--extern value must be of the format `foo=bar`" ) ,
10921126 } ;
10931127
10941128 externs. entry ( name. to_string ( ) ) . or_insert ( vec ! [ ] ) . push ( location. to_string ( ) ) ;
@@ -1119,7 +1153,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
11191153 debugging_opts : debugging_opts,
11201154 prints : prints,
11211155 cg : cg,
1122- color : color ,
1156+ error_format : error_format ,
11231157 externs : externs,
11241158 crate_name : crate_name,
11251159 alt_std_name : None ,
0 commit comments