| 
 | 1 | +//! Regression test for rust-lang/rust#70924. Check that if we add the `rust-src` component in  | 
 | 2 | +//! between two incremental compiles, that the compiler doesn't ICE on the second invocation.  | 
 | 3 | +//!  | 
 | 4 | +//! This test uses symbolic links to save testing time.  | 
 | 5 | +//!  | 
 | 6 | +//! The way this test works is that, for every prefix in `root/lib/rustlib/src`, link all of prefix  | 
 | 7 | +//! parent content, then remove the prefix, then loop on the next prefix. This way, we basically  | 
 | 8 | +//! create a copy of the context around `root/lib/rustlib/src`, and can freely add/remove the src  | 
 | 9 | +//! component itself.  | 
 | 10 | +
  | 
 | 11 | +//@ ignore-cross-compile  | 
 | 12 | +// Reason: test needs to run.  | 
 | 13 | + | 
 | 14 | +//@ needs-symlink  | 
 | 15 | +// Reason: test needs symlink to create stub directories and files.  | 
 | 16 | + | 
 | 17 | +use std::path::Path;  | 
 | 18 | + | 
 | 19 | +use run_make_support::rfs::read_dir_entries;  | 
 | 20 | +use run_make_support::{bare_rustc, path, rfs, run};  | 
 | 21 | + | 
 | 22 | +#[derive(Debug, Copy, Clone)]  | 
 | 23 | +struct Symlink<'a, 'b> {  | 
 | 24 | +    src_dir: &'a Path,  | 
 | 25 | +    dst_dir: &'b Path,  | 
 | 26 | +}  | 
 | 27 | + | 
 | 28 | +fn shallow_symlink_dir<'a, 'b>(Symlink { src_dir, dst_dir }: Symlink<'a, 'b>) {  | 
 | 29 | +    eprintln!(  | 
 | 30 | +        "shallow_symlink_dir: src_dir={} -> dst_dir={}",  | 
 | 31 | +        src_dir.display(),  | 
 | 32 | +        dst_dir.display()  | 
 | 33 | +    );  | 
 | 34 | + | 
 | 35 | +    read_dir_entries(src_dir, |src_path| {  | 
 | 36 | +        let src_metadata = rfs::symlink_metadata(src_path);  | 
 | 37 | +        let filename = src_path.file_name().unwrap();  | 
 | 38 | +        if src_metadata.is_dir() {  | 
 | 39 | +            rfs::symlink_dir(src_path, dst_dir.join(filename));  | 
 | 40 | +        } else if src_metadata.is_file() {  | 
 | 41 | +            rfs::symlink_file(src_path, dst_dir.join(filename));  | 
 | 42 | +        } else if src_metadata.is_symlink() {  | 
 | 43 | +            rfs::copy_symlink(src_path, dst_dir.join(filename));  | 
 | 44 | +        }  | 
 | 45 | +    });  | 
 | 46 | +}  | 
 | 47 | + | 
 | 48 | +fn recreate_dir(path: &Path) {  | 
 | 49 | +    rfs::recursive_remove(path);  | 
 | 50 | +    rfs::create_dir(path);  | 
 | 51 | +}  | 
 | 52 | + | 
 | 53 | +fn main() {  | 
 | 54 | +    let sysroot = bare_rustc().print("sysroot").run().stdout_utf8();  | 
 | 55 | +    let sysroot = sysroot.trim();  | 
 | 56 | +    let sysroot = path(sysroot);  | 
 | 57 | + | 
 | 58 | +    let incr = path("incr");  | 
 | 59 | + | 
 | 60 | +    let fakeroot = path("fakeroot");  | 
 | 61 | +    rfs::create_dir(&fakeroot);  | 
 | 62 | + | 
 | 63 | +    shallow_symlink_dir(Symlink { src_dir: &sysroot, dst_dir: &fakeroot });  | 
 | 64 | +    recreate_dir(&fakeroot.join("lib"));  | 
 | 65 | + | 
 | 66 | +    shallow_symlink_dir(Symlink { src_dir: &sysroot.join("lib"), dst_dir: &fakeroot.join("lib") });  | 
 | 67 | +    recreate_dir(&fakeroot.join("lib").join("rustlib"));  | 
 | 68 | + | 
 | 69 | +    shallow_symlink_dir(Symlink {  | 
 | 70 | +        src_dir: &sysroot.join("lib").join("rustlib"),  | 
 | 71 | +        dst_dir: &fakeroot.join("lib").join("rustlib"),  | 
 | 72 | +    });  | 
 | 73 | +    recreate_dir(&fakeroot.join("lib").join("rustlib").join("src"));  | 
 | 74 | + | 
 | 75 | +    shallow_symlink_dir(Symlink {  | 
 | 76 | +        src_dir: &sysroot.join("lib").join("rustlib").join("src"),  | 
 | 77 | +        dst_dir: &fakeroot.join("lib").join("rustlib").join("src"),  | 
 | 78 | +    });  | 
 | 79 | + | 
 | 80 | +    rfs::recursive_remove(&fakeroot.join("lib").join("rustlib").join("src").join("rust"));  | 
 | 81 | + | 
 | 82 | +    let run_incr_rustc = || {  | 
 | 83 | +        bare_rustc()  | 
 | 84 | +            .sysroot(&fakeroot)  | 
 | 85 | +            .arg("-C")  | 
 | 86 | +            .arg(format!("incremental={}", incr.to_str().unwrap()))  | 
 | 87 | +            .input("main.rs")  | 
 | 88 | +            .run();  | 
 | 89 | +    };  | 
 | 90 | + | 
 | 91 | +    // Run rustc w/ incremental once...  | 
 | 92 | +    run_incr_rustc();  | 
 | 93 | + | 
 | 94 | +    // NOTE: the Makefile version of this used `$SYSROOT/lib/rustlib/src/rust/src/libstd/lib.rs`,  | 
 | 95 | +    // but that actually got moved around and reorganized over the years. As of Dec 2024, the  | 
 | 96 | +    // rust-src component is more like (specific for our purposes):  | 
 | 97 | +    //  | 
 | 98 | +    // ```  | 
 | 99 | +    // $SYSROOT/lib/rustlib/src/rust/  | 
 | 100 | +    //     library/std/src/lib.rs  | 
 | 101 | +    //     src/  | 
 | 102 | +    // ```  | 
 | 103 | +    rfs::create_dir_all(  | 
 | 104 | +        &fakeroot  | 
 | 105 | +            .join("lib")  | 
 | 106 | +            .join("rustlib")  | 
 | 107 | +            .join("src")  | 
 | 108 | +            .join("rust")  | 
 | 109 | +            .join("library")  | 
 | 110 | +            .join("std")  | 
 | 111 | +            .join("src"),  | 
 | 112 | +    );  | 
 | 113 | +    rfs::write(  | 
 | 114 | +        &fakeroot  | 
 | 115 | +            .join("lib")  | 
 | 116 | +            .join("rustlib")  | 
 | 117 | +            .join("src")  | 
 | 118 | +            .join("rust")  | 
 | 119 | +            .join("library")  | 
 | 120 | +            .join("std")  | 
 | 121 | +            .join("src")  | 
 | 122 | +            .join("lib.rs"),  | 
 | 123 | +        b"",  | 
 | 124 | +    );  | 
 | 125 | + | 
 | 126 | +    // ... and a second time.  | 
 | 127 | +    run_incr_rustc();  | 
 | 128 | + | 
 | 129 | +    // Basic sanity check that the compiled binary can run.  | 
 | 130 | +    run("main");  | 
 | 131 | +}  | 
0 commit comments