Skip to content

Commit 83adf88

Browse files
committed
rustdoc: remove unchecked_claim_error_was_emitted call in main_args.
`main_args` calls `from_matches`, which does lots of initialization. If anything goes wrong, `from_matches` emits an error message and returns `Err(1)` (or `Err(3)`). `main_args` then turns the `Err(1)` into `Err(ErrorGuaranteed)`, because that's what `catch_with_exit_code` requires on error. But `catch_with_exit_code` doesn't do anything with the `ErrorGuaranteed`, it just exits with `EXIT_FAILURE`. We can avoid the creation of the `ErrorGuaranteed` (which requires an undesirable `unchecked_claim_error_was_emitted` call), by changing `from_matches` to instead eagerly abort if anything goes wrong. The behaviour from the user's point of view is the same: an early abort with an `EXIT_FAILURE` exit code. And we can also simplify `from_matches` to return an `Option` instead of a `Result`: - Old `Err(0)` case --> `None` - Old `Err(_)` case --> fatal error. This requires similar changes to `ScrapeExamplesOptions::new` and `load_call_locations`.
1 parent e6794dd commit 83adf88

File tree

3 files changed

+54
-102
lines changed

3 files changed

+54
-102
lines changed

src/librustdoc/config.rs

+32-64
Original file line numberDiff line numberDiff line change
@@ -323,20 +323,20 @@ impl Options {
323323
early_dcx: &mut EarlyDiagCtxt,
324324
matches: &getopts::Matches,
325325
args: Vec<String>,
326-
) -> Result<(Options, RenderOptions), i32> {
326+
) -> Option<(Options, RenderOptions)> {
327327
// Check for unstable options.
328328
nightly_options::check_nightly_options(early_dcx, matches, &opts());
329329

330330
if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") {
331331
crate::usage("rustdoc");
332-
return Err(0);
332+
return None;
333333
} else if matches.opt_present("version") {
334334
rustc_driver::version!(&early_dcx, "rustdoc", matches);
335-
return Err(0);
335+
return None;
336336
}
337337

338338
if rustc_driver::describe_flag_categories(early_dcx, &matches) {
339-
return Err(0);
339+
return None;
340340
}
341341

342342
let color = config::parse_color(early_dcx, matches);
@@ -382,18 +382,15 @@ impl Options {
382382
}
383383
}
384384

385-
return Err(0);
385+
return None;
386386
}
387387

388388
let mut emit = Vec::new();
389389
for list in matches.opt_strs("emit") {
390390
for kind in list.split(',') {
391391
match kind.parse() {
392392
Ok(kind) => emit.push(kind),
393-
Err(()) => {
394-
dcx.err(format!("unrecognized emission type: {kind}"));
395-
return Err(1);
396-
}
393+
Err(()) => dcx.fatal(format!("unrecognized emission type: {kind}")),
397394
}
398395
}
399396
}
@@ -403,7 +400,7 @@ impl Options {
403400
&& !matches.opt_present("show-coverage")
404401
&& !nightly_options::is_unstable_enabled(matches)
405402
{
406-
early_dcx.early_fatal(
403+
dcx.fatal(
407404
"the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)",
408405
);
409406
}
@@ -420,10 +417,7 @@ impl Options {
420417
}
421418
let paths = match theme::load_css_paths(content) {
422419
Ok(p) => p,
423-
Err(e) => {
424-
dcx.err(e);
425-
return Err(1);
426-
}
420+
Err(e) => dcx.fatal(e),
427421
};
428422
let mut errors = 0;
429423

@@ -442,21 +436,19 @@ impl Options {
442436
}
443437
}
444438
if errors != 0 {
445-
return Err(1);
439+
dcx.fatal("[check-theme] one or more tests failed");
446440
}
447-
return Err(0);
441+
return None;
448442
}
449443

450444
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
451445

452446
let input = PathBuf::from(if describe_lints {
453447
"" // dummy, this won't be used
454448
} else if matches.free.is_empty() {
455-
dcx.err("missing file operand");
456-
return Err(1);
449+
dcx.fatal("missing file operand");
457450
} else if matches.free.len() > 1 {
458-
dcx.err("too many file operands");
459-
return Err(1);
451+
dcx.fatal("too many file operands");
460452
} else {
461453
&matches.free[0]
462454
});
@@ -466,10 +458,7 @@ impl Options {
466458
let externs = parse_externs(early_dcx, matches, &unstable_opts);
467459
let extern_html_root_urls = match parse_extern_html_roots(matches) {
468460
Ok(ex) => ex,
469-
Err(err) => {
470-
dcx.err(err);
471-
return Err(1);
472-
}
461+
Err(err) => dcx.fatal(err),
473462
};
474463

475464
let default_settings: Vec<Vec<(String, String)>> = vec![
@@ -526,16 +515,14 @@ impl Options {
526515
let no_run = matches.opt_present("no-run");
527516

528517
if !should_test && no_run {
529-
dcx.err("the `--test` flag must be passed to enable `--no-run`");
530-
return Err(1);
518+
dcx.fatal("the `--test` flag must be passed to enable `--no-run`");
531519
}
532520

533521
let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s));
534522
let output = matches.opt_str("output").map(|s| PathBuf::from(&s));
535523
let output = match (out_dir, output) {
536524
(Some(_), Some(_)) => {
537-
dcx.err("cannot use both 'out-dir' and 'output' at once");
538-
return Err(1);
525+
dcx.fatal("cannot use both 'out-dir' and 'output' at once");
539526
}
540527
(Some(out_dir), None) => out_dir,
541528
(None, Some(output)) => output,
@@ -549,8 +536,7 @@ impl Options {
549536

550537
if let Some(ref p) = extension_css {
551538
if !p.is_file() {
552-
dcx.err("option --extend-css argument must be a file");
553-
return Err(1);
539+
dcx.fatal("option --extend-css argument must be a file");
554540
}
555541
}
556542

@@ -566,31 +552,25 @@ impl Options {
566552
}
567553
let paths = match theme::load_css_paths(content) {
568554
Ok(p) => p,
569-
Err(e) => {
570-
dcx.err(e);
571-
return Err(1);
572-
}
555+
Err(e) => dcx.fatal(e),
573556
};
574557

575558
for (theme_file, theme_s) in
576559
matches.opt_strs("theme").iter().map(|s| (PathBuf::from(&s), s.to_owned()))
577560
{
578561
if !theme_file.is_file() {
579-
dcx.struct_err(format!("invalid argument: \"{theme_s}\""))
562+
dcx.struct_fatal(format!("invalid argument: \"{theme_s}\""))
580563
.with_help("arguments to --theme must be files")
581564
.emit();
582-
return Err(1);
583565
}
584566
if theme_file.extension() != Some(OsStr::new("css")) {
585-
dcx.struct_err(format!("invalid argument: \"{theme_s}\""))
567+
dcx.struct_fatal(format!("invalid argument: \"{theme_s}\""))
586568
.with_help("arguments to --theme must have a .css extension")
587569
.emit();
588-
return Err(1);
589570
}
590571
let (success, ret) = theme::test_theme_against(&theme_file, &paths, &dcx);
591572
if !success {
592-
dcx.err(format!("error loading theme file: \"{theme_s}\""));
593-
return Err(1);
573+
dcx.fatal(format!("error loading theme file: \"{theme_s}\""));
594574
} else if !ret.is_empty() {
595575
dcx.struct_warn(format!(
596576
"theme file \"{theme_s}\" is missing CSS rules from the default theme",
@@ -620,22 +600,18 @@ impl Options {
620600
edition,
621601
&None,
622602
) else {
623-
return Err(3);
603+
dcx.fatal("`ExternalHtml::load` failed");
624604
};
625605

626606
match matches.opt_str("r").as_deref() {
627607
Some("rust") | None => {}
628-
Some(s) => {
629-
dcx.err(format!("unknown input format: {s}"));
630-
return Err(1);
631-
}
608+
Some(s) => dcx.fatal(format!("unknown input format: {s}")),
632609
}
633610

634611
let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s));
635612
if let Some(ref index_page) = index_page {
636613
if !index_page.is_file() {
637-
dcx.err("option `--index-page` argument must be a file");
638-
return Err(1);
614+
dcx.fatal("option `--index-page` argument must be a file");
639615
}
640616
}
641617

@@ -646,27 +622,21 @@ impl Options {
646622
let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) {
647623
Ok(types) => types,
648624
Err(e) => {
649-
dcx.err(format!("unknown crate type: {e}"));
650-
return Err(1);
625+
dcx.fatal(format!("unknown crate type: {e}"));
651626
}
652627
};
653628

654629
let output_format = match matches.opt_str("output-format") {
655630
Some(s) => match OutputFormat::try_from(s.as_str()) {
656631
Ok(out_fmt) => {
657632
if !out_fmt.is_json() && show_coverage {
658-
dcx.struct_err(
633+
dcx.fatal(
659634
"html output format isn't supported for the --show-coverage option",
660-
)
661-
.emit();
662-
return Err(1);
635+
);
663636
}
664637
out_fmt
665638
}
666-
Err(e) => {
667-
dcx.err(e);
668-
return Err(1);
669-
}
639+
Err(e) => dcx.fatal(e),
670640
},
671641
None => OutputFormat::default(),
672642
};
@@ -709,16 +679,14 @@ impl Options {
709679
let html_no_source = matches.opt_present("html-no-source");
710680

711681
if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) {
712-
dcx.struct_err(
682+
dcx.fatal(
713683
"--generate-link-to-definition option can only be used with HTML output format",
714-
)
715-
.emit();
716-
return Err(1);
684+
);
717685
}
718686

719-
let scrape_examples_options = ScrapeExamplesOptions::new(matches, &dcx)?;
687+
let scrape_examples_options = ScrapeExamplesOptions::new(matches, &dcx);
720688
let with_examples = matches.opt_strs("with-examples");
721-
let call_locations = crate::scrape_examples::load_call_locations(with_examples, &dcx)?;
689+
let call_locations = crate::scrape_examples::load_call_locations(with_examples, &dcx);
722690

723691
let unstable_features =
724692
rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
@@ -793,7 +761,7 @@ impl Options {
793761
no_emit_shared: false,
794762
html_no_source,
795763
};
796-
Ok((options, render_options))
764+
Some((options, render_options))
797765
}
798766

799767
/// Returns `true` if the file given as `self.input` is a Markdown file.

src/librustdoc/lib.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -720,15 +720,8 @@ fn main_args(
720720
// Note that we discard any distinction between different non-zero exit
721721
// codes from `from_matches` here.
722722
let (options, render_options) = match config::Options::from_matches(early_dcx, &matches, args) {
723-
Ok(opts) => opts,
724-
Err(code) => {
725-
return if code == 0 {
726-
Ok(())
727-
} else {
728-
#[allow(deprecated)]
729-
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
730-
};
731-
}
723+
Some(opts) => opts,
724+
None => return Ok(()),
732725
};
733726

734727
let diag =

src/librustdoc/scrape_examples.rs

+20-29
Original file line numberDiff line numberDiff line change
@@ -38,28 +38,23 @@ pub(crate) struct ScrapeExamplesOptions {
3838
}
3939

4040
impl ScrapeExamplesOptions {
41-
pub(crate) fn new(
42-
matches: &getopts::Matches,
43-
dcx: &rustc_errors::DiagCtxt,
44-
) -> Result<Option<Self>, i32> {
41+
pub(crate) fn new(matches: &getopts::Matches, dcx: &rustc_errors::DiagCtxt) -> Option<Self> {
4542
let output_path = matches.opt_str("scrape-examples-output-path");
4643
let target_crates = matches.opt_strs("scrape-examples-target-crate");
4744
let scrape_tests = matches.opt_present("scrape-tests");
4845
match (output_path, !target_crates.is_empty(), scrape_tests) {
49-
(Some(output_path), true, _) => Ok(Some(ScrapeExamplesOptions {
46+
(Some(output_path), true, _) => Some(ScrapeExamplesOptions {
5047
output_path: PathBuf::from(output_path),
5148
target_crates,
5249
scrape_tests,
53-
})),
50+
}),
5451
(Some(_), false, _) | (None, true, _) => {
55-
dcx.err("must use --scrape-examples-output-path and --scrape-examples-target-crate together");
56-
Err(1)
52+
dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate together");
5753
}
5854
(None, false, true) => {
59-
dcx.err("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests");
60-
Err(1)
55+
dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests");
6156
}
62-
(None, false, false) => Ok(None),
57+
(None, false, false) => None,
6358
}
6459
}
6560
}
@@ -342,24 +337,20 @@ pub(crate) fn run(
342337
pub(crate) fn load_call_locations(
343338
with_examples: Vec<String>,
344339
dcx: &rustc_errors::DiagCtxt,
345-
) -> Result<AllCallLocations, i32> {
346-
let inner = || {
347-
let mut all_calls: AllCallLocations = FxHashMap::default();
348-
for path in with_examples {
349-
let bytes = fs::read(&path).map_err(|e| format!("{e} (for path {path})"))?;
350-
let mut decoder = MemDecoder::new(&bytes, 0);
351-
let calls = AllCallLocations::decode(&mut decoder);
352-
353-
for (function, fn_calls) in calls.into_iter() {
354-
all_calls.entry(function).or_default().extend(fn_calls.into_iter());
355-
}
356-
}
340+
) -> AllCallLocations {
341+
let mut all_calls: AllCallLocations = FxHashMap::default();
342+
for path in with_examples {
343+
let bytes = match fs::read(&path) {
344+
Ok(bytes) => bytes,
345+
Err(e) => dcx.fatal(format!("failed to load examples: {e}")),
346+
};
347+
let mut decoder = MemDecoder::new(&bytes, 0);
348+
let calls = AllCallLocations::decode(&mut decoder);
357349

358-
Ok(all_calls)
359-
};
350+
for (function, fn_calls) in calls.into_iter() {
351+
all_calls.entry(function).or_default().extend(fn_calls.into_iter());
352+
}
353+
}
360354

361-
inner().map_err(|e: String| {
362-
dcx.err(format!("failed to load examples: {e}"));
363-
1
364-
})
355+
all_calls
365356
}

0 commit comments

Comments
 (0)