14
14
pub use self :: EntryFnType :: * ;
15
15
pub use self :: CrateType :: * ;
16
16
pub use self :: Passes :: * ;
17
- pub use self :: OptLevel :: * ;
18
17
pub use self :: DebugInfoLevel :: * ;
19
18
20
19
use session:: { early_error, early_warn, Session } ;
@@ -71,6 +70,18 @@ pub enum OutputType {
71
70
DepInfo ,
72
71
}
73
72
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
+
74
85
impl OutputType {
75
86
fn is_compatible_with_codegen_units_and_single_output_file ( & self ) -> bool {
76
87
match * self {
@@ -124,14 +135,14 @@ pub struct Options {
124
135
pub test : bool ,
125
136
pub parse_only : bool ,
126
137
pub no_trans : bool ,
138
+ pub error_format : ErrorOutputType ,
127
139
pub treat_err_as_bug : bool ,
128
140
pub incremental_compilation : bool ,
129
141
pub dump_dep_graph : bool ,
130
142
pub no_analysis : bool ,
131
143
pub debugging_opts : DebuggingOptions ,
132
144
pub prints : Vec < PrintRequest > ,
133
145
pub cg : CodegenOptions ,
134
- pub color : ColorConfig ,
135
146
pub externs : HashMap < String , Vec < String > > ,
136
147
pub crate_name : Option < String > ,
137
148
/// An optional name to use as the crate for std during std injection,
@@ -221,7 +232,7 @@ pub fn basic_options() -> Options {
221
232
Options {
222
233
crate_types : Vec :: new ( ) ,
223
234
gc : false ,
224
- optimize : No ,
235
+ optimize : OptLevel :: No ,
225
236
debuginfo : NoDebugInfo ,
226
237
lint_opts : Vec :: new ( ) ,
227
238
lint_cap : None ,
@@ -241,7 +252,7 @@ pub fn basic_options() -> Options {
241
252
debugging_opts : basic_debugging_options ( ) ,
242
253
prints : Vec :: new ( ) ,
243
254
cg : basic_codegen_options ( ) ,
244
- color : ColorConfig :: Auto ,
255
+ error_format : ErrorOutputType :: default ( ) ,
245
256
externs : HashMap :: new ( ) ,
246
257
crate_name : None ,
247
258
alt_std_name : None ,
@@ -308,7 +319,7 @@ macro_rules! options {
308
319
$struct_name { $( $opt: $init) ,* }
309
320
}
310
321
311
- pub fn $buildfn( matches: & getopts:: Matches , color : ColorConfig ) -> $struct_name
322
+ pub fn $buildfn( matches: & getopts:: Matches , error_format : ErrorOutputType ) -> $struct_name
312
323
{
313
324
let mut op = $defaultfn( ) ;
314
325
for option in matches. opt_strs( $prefix) {
@@ -322,20 +333,20 @@ macro_rules! options {
322
333
if !setter( & mut op, value) {
323
334
match ( value, opt_type_desc) {
324
335
( 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) )
327
338
}
328
339
( 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) )
333
344
}
334
345
( 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) )
339
350
}
340
351
( None , None ) => unreachable!( )
341
352
}
@@ -344,8 +355,8 @@ macro_rules! options {
344
355
break ;
345
356
}
346
357
if !found {
347
- early_error( color , & format!( "unknown {} option: `{}`" ,
348
- $outputname, key) ) ;
358
+ early_error( error_format , & format!( "unknown {} option: `{}`" ,
359
+ $outputname, key) ) ;
349
360
}
350
361
}
351
362
return op;
@@ -861,6 +872,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
861
872
"NAME=PATH" ) ,
862
873
opt:: opt ( "" , "sysroot" , "Override the system root" , "PATH" ) ,
863
874
opt:: multi ( "Z" , "" , "Set internal debugging options" , "FLAG" ) ,
875
+ opt:: opt_u ( "" , "error-format" , "How errors and other messages are produced" , "human|json" ) ,
864
876
opt:: opt ( "" , "color" , "Configure coloring of output:
865
877
auto = colorize, if output goes to a tty (default);
866
878
always = always colorize output;
@@ -903,15 +915,37 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
903
915
None => ColorConfig :: Auto ,
904
916
905
917
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) )
909
921
}
910
922
} ;
911
923
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
+
912
946
let unparsed_crate_types = matches. opt_strs ( "crate-type" ) ;
913
947
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[ ..] ) ) ;
915
949
916
950
let mut lint_opts = vec ! ( ) ;
917
951
let mut describe_lints = false ;
@@ -928,11 +962,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
928
962
929
963
let lint_cap = matches. opt_str ( "cap-lints" ) . map ( |cap| {
930
964
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) )
932
966
} )
933
967
} ) ;
934
968
935
- let debugging_opts = build_debugging_options ( matches, color ) ;
969
+ let debugging_opts = build_debugging_options ( matches, error_format ) ;
936
970
937
971
let parse_only = debugging_opts. parse_only ;
938
972
let no_trans = debugging_opts. no_trans ;
@@ -958,7 +992,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
958
992
"link" => OutputType :: Exe ,
959
993
"dep-info" => OutputType :: DepInfo ,
960
994
part => {
961
- early_error ( color , & format ! ( "unknown emission type: `{}`" ,
995
+ early_error ( error_format , & format ! ( "unknown emission type: `{}`" ,
962
996
part) )
963
997
}
964
998
} ;
@@ -971,7 +1005,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
971
1005
output_types. insert ( OutputType :: Exe , None ) ;
972
1006
}
973
1007
974
- let mut cg = build_codegen_options ( matches, color ) ;
1008
+ let mut cg = build_codegen_options ( matches, error_format ) ;
975
1009
976
1010
// Issue #30063: if user requests llvm-related output to one
977
1011
// particular path, disable codegen-units.
@@ -983,11 +1017,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
983
1017
} ) . collect ( ) ;
984
1018
if !incompatible. is_empty ( ) {
985
1019
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( ) ) ) ;
989
1023
}
990
- early_warn ( color , "resetting to default -C codegen-units=1" ) ;
1024
+ early_warn ( error_format , "resetting to default -C codegen-units=1" ) ;
991
1025
cg. codegen_units = 1 ;
992
1026
}
993
1027
}
@@ -1000,29 +1034,29 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1000
1034
let opt_level = {
1001
1035
if matches. opt_present ( "O" ) {
1002
1036
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" ) ;
1004
1038
}
1005
- Default
1039
+ OptLevel :: Default
1006
1040
} else {
1007
1041
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 ,
1013
1047
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) ) ;
1017
1051
}
1018
1052
}
1019
1053
}
1020
1054
} ;
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 ) ;
1022
1056
let gc = debugging_opts. gc ;
1023
1057
let debuginfo = if matches. opt_present ( "g" ) {
1024
1058
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" ) ;
1026
1060
}
1027
1061
FullDebugInfo
1028
1062
} else {
@@ -1031,16 +1065,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1031
1065
Some ( 1 ) => LimitedDebugInfo ,
1032
1066
Some ( 2 ) => FullDebugInfo ,
1033
1067
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) ) ;
1037
1071
}
1038
1072
}
1039
1073
} ;
1040
1074
1041
1075
let mut search_paths = SearchPaths :: new ( ) ;
1042
1076
for s in & matches. opt_strs ( "L" ) {
1043
- search_paths. add_path ( & s[ ..] , color ) ;
1077
+ search_paths. add_path ( & s[ ..] , error_format ) ;
1044
1078
}
1045
1079
1046
1080
let libs = matches. opt_strs ( "l" ) . into_iter ( ) . map ( |s| {
@@ -1052,9 +1086,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1052
1086
( Some ( name) , "framework" ) => ( name, cstore:: NativeFramework ) ,
1053
1087
( Some ( name) , "static" ) => ( name, cstore:: NativeStatic ) ,
1054
1088
( _, 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) ) ;
1058
1092
}
1059
1093
} ;
1060
1094
( name. to_string ( ) , kind)
@@ -1069,26 +1103,26 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
1069
1103
"file-names" => PrintRequest :: FileNames ,
1070
1104
"sysroot" => PrintRequest :: Sysroot ,
1071
1105
req => {
1072
- early_error ( color , & format ! ( "unknown print request `{}`" , req) )
1106
+ early_error ( error_format , & format ! ( "unknown print request `{}`" , req) )
1073
1107
}
1074
1108
}
1075
1109
} ) . collect :: < Vec < _ > > ( ) ;
1076
1110
1077
1111
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") ;
1080
1114
}
1081
1115
1082
1116
let mut externs = HashMap :: new ( ) ;
1083
1117
for arg in & matches. opt_strs ( "extern" ) {
1084
1118
let mut parts = arg. splitn ( 2 , '=' ) ;
1085
1119
let name = match parts. next ( ) {
1086
1120
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" ) ,
1088
1122
} ;
1089
1123
let location = match parts. next ( ) {
1090
1124
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`" ) ,
1092
1126
} ;
1093
1127
1094
1128
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 {
1119
1153
debugging_opts : debugging_opts,
1120
1154
prints : prints,
1121
1155
cg : cg,
1122
- color : color ,
1156
+ error_format : error_format ,
1123
1157
externs : externs,
1124
1158
crate_name : crate_name,
1125
1159
alt_std_name : None ,
0 commit comments