File: run-compiler-twice.rs

package info (click to toggle)
rustc 1.85.0%2Bdfsg3-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, trixie
  • size: 893,396 kB
  • sloc: xml: 158,127; python: 35,830; javascript: 19,497; cpp: 19,002; sh: 17,245; ansic: 13,127; asm: 4,376; makefile: 1,051; perl: 29; lisp: 29; ruby: 19; sql: 11
file content (87 lines) | stat: -rw-r--r-- 2,844 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//@ edition: 2021
//@ run-pass
//@ run-flags: {{sysroot-base}} {{target-linker}}
//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)

// Regression test for <https://github.com/rust-lang/rust/issues/19371>.
//
// This test ensures that `compile_input` can be called twice in one task
// without causing a panic.

#![feature(rustc_private)]

extern crate rustc_driver;
extern crate rustc_interface;
extern crate rustc_session;
extern crate rustc_span;

use std::path::{Path, PathBuf};

use rustc_interface::{Linker, interface};
use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes};
use rustc_span::FileName;

fn main() {
    let src = r#"
    fn main() {}
    "#;

    let args: Vec<String> = std::env::args().collect();

    if args.len() < 2 {
        panic!("expected sysroot (and optional linker)");
    }

    let sysroot = PathBuf::from(&args[1]);
    let linker = args.get(2).map(PathBuf::from);

    // compiletest sets the current dir to `output_base_dir` when running.
    let tmpdir = std::env::current_dir().unwrap().join("tmp");
    std::fs::create_dir_all(&tmpdir).unwrap();

    compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
    compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
}

fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) {
    let mut opts = Options::default();
    opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
    opts.maybe_sysroot = Some(sysroot);

    if let Some(linker) = linker {
        opts.cg.linker = Some(linker.to_owned());
    }

    let name = FileName::anon_source_code(&code);
    let input = Input::Str { name, input: code };

    let config = interface::Config {
        opts,
        crate_cfg: Default::default(),
        crate_check_cfg: Default::default(),
        input,
        output_file: Some(OutFileName::Real(output)),
        output_dir: None,
        ice_file: None,
        file_loader: None,
        locale_resources: Vec::new(),
        lint_caps: Default::default(),
        psess_created: None,
        hash_untracked_state: None,
        register_lints: None,
        override_queries: None,
        make_codegen_backend: None,
        registry: rustc_driver::diagnostics_registry(),
        using_internal_features: std::sync::Arc::default(),
        expanded_args: Default::default(),
    };

    interface::run_compiler(config, |compiler| {
        let krate = rustc_interface::passes::parse(&compiler.sess);
        let linker = rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| {
            let _ = tcx.analysis(());
            Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend)
        });
        linker.link(&compiler.sess, &*compiler.codegen_backend);
    });
}