fn rustfix_crate(
    lock_addr: &str,
    rustc: &ProcessBuilder,
    filename: &Path,
    args: &FixArgs,
    config: &Config,
) -> Result<FixedCrate, Error> {
    if !args.can_run_rustfix(config)? {
        // This fix should not be run. Skipping...
        return Ok(FixedCrate::default());
    }

    // First up, we want to make sure that each crate is only checked by one
    // process at a time. If two invocations concurrently check a crate then
    // it's likely to corrupt it.
    //
    // Historically this used per-source-file locking, then per-package
    // locking. It now uses a single, global lock as some users do things like
    // #[path] or include!() of shared files between packages. Serializing
    // makes it slower, but is the only safe way to prevent concurrent
    // modification.
    let _lock = LockServerClient::lock(&lock_addr.parse()?, "global")?;

    // Next up, this is a bit suspicious, but we *iteratively* execute rustc and
    // collect suggestions to feed to rustfix. Once we hit our limit of times to
    // execute rustc or we appear to be reaching a fixed point we stop running
    // rustc.
    //
    // This is currently done to handle code like:
    //
    //      ::foo::<::Bar>();
    //
    // where there are two fixes to happen here: `crate::foo::<crate::Bar>()`.
    // The spans for these two suggestions are overlapping and its difficult in
    // the compiler to **not** have overlapping spans here. As a result, a naive
    // implementation would feed the two compiler suggestions for the above fix
    // into `rustfix`, but one would be rejected because it overlaps with the
    // other.
    //
    // In this case though, both suggestions are valid and can be automatically
    // applied! To handle this case we execute rustc multiple times, collecting
    // fixes each time we do so. Along the way we discard any suggestions that
    // failed to apply, assuming that they can be fixed the next time we run
    // rustc.
    //
    // Naturally, we want a few protections in place here though to avoid looping
    // forever or otherwise losing data. To that end we have a few termination
    // conditions:
    //
    // * Do this whole process a fixed number of times. In theory we probably
    //   need an infinite number of times to apply fixes, but we're not gonna
    //   sit around waiting for that.
    // * If it looks like a fix genuinely can't be applied we need to bail out.
    //   Detect this when a fix fails to get applied *and* no suggestions
    //   successfully applied to the same file. In that case looks like we
    //   definitely can't make progress, so bail out.
    let mut fixes = FixedCrate::default();
    let mut last_fix_counts = HashMap::new();
    let iterations = env::var("CARGO_FIX_MAX_RETRIES")
        .ok()
        .and_then(|n| n.parse().ok())
        .unwrap_or(4);
    for _ in 0..iterations {
        last_fix_counts.clear();
        for (path, file) in fixes.files.iter_mut() {
            last_fix_counts.insert(path.clone(), file.fixes_applied);
            // We'll generate new errors below.
            file.errors_applying_fixes.clear();
        }
        rustfix_and_fix(&mut fixes, rustc, filename, args, config)?;
        let mut progress_yet_to_be_made = false;
        for (path, file) in fixes.files.iter_mut() {
            if file.errors_applying_fixes.is_empty() {
                continue;
            }
            // If anything was successfully fixed *and* there's at least one
            // error, then assume the error was spurious and we'll try again on
            // the next iteration.
            if file.fixes_applied != *last_fix_counts.get(path).unwrap_or(&0) {
                progress_yet_to_be_made = true;
            }
        }
        if !progress_yet_to_be_made {
            break;
        }
    }

    // Any errors still remaining at this point need to be reported as probably
    // bugs in Cargo and/or rustfix.
    for (path, file) in fixes.files.iter_mut() {
        for error in file.errors_applying_fixes.drain(..) {
            Message::ReplaceFailed {
                file: path.clone(),
                message: error,
            }
            .post()?;
        }
    }

    Ok(fixes)
}
/// Attempts to apply fixes to a single crate.
///
/// This runs `rustc` (possibly multiple times) to gather suggestions from the
/// compiler and applies them to the files on disk.
Attempts to apply fixes to a single crate.
This runs `rustc` (possibly multiple times) to gather suggestions from the
compiler and applies them to the files on disk.
Attempts to apply fixes to a single crate . This runs ` rustc ` ( possibly multiple times ) to gather suggestions from the compiler and applies them to the files on disk .
fn rustfix_crate(
    lock_addr: &str,
    rustc: &ProcessBuilder,
    filename: &Path,
    args: &FixArgs,
    config: &Config,
) -> Result<FixedCrate, Error> {
    if !args.can_run_rustfix(config)? {
        // This fix should not be run. Skipping...
        return Ok(FixedCrate::default());
    }
    // First up, we want to make sure that each crate is only checked by one
    // process at a time. If two invocations concurrently check a crate then
    // it's likely to corrupt it.
    //
    // Historically this used per-source-file locking, then per-package
    // locking. It now uses a single, global lock as some users do things like
    // #[path] or include!() of shared files between packages. Serializing
    // makes it slower, but is the only safe way to prevent concurrent
    // modification.
    let _lock = LockServerClient::lock(&lock_addr.parse()?, "global")?;
    // Next up, this is a bit suspicious, but we *iteratively* execute rustc and
    // collect suggestions to feed to rustfix. Once we hit our limit of times to
    // execute rustc or we appear to be reaching a fixed point we stop running
    // rustc.
    //
    // This is currently done to handle code like:
    //
    //      ::foo::<::Bar>();
    //
    // where there are two fixes to happen here: `crate::foo::<crate::Bar>()`.
    // The spans for these two suggestions are overlapping and its difficult in
    // the compiler to **not** have overlapping spans here. As a result, a naive
    // implementation would feed the two compiler suggestions for the above fix
    // into `rustfix`, but one would be rejected because it overlaps with the
    // other.
    //
    // In this case though, both suggestions are valid and can be automatically
    // applied! To handle this case we execute rustc multiple times, collecting
    // fixes each time we do so. Along the way we discard any suggestions that
    // failed to apply, assuming that they can be fixed the next time we run
    // rustc.
    //
    // Naturally, we want a few protections in place here though to avoid looping
    // forever or otherwise losing data. To that end we have a few termination
    // conditions:
    //
    // * Do this whole process a fixed number of times. In theory we probably
    //   need an infinite number of times to apply fixes, but we're not gonna
    //   sit around waiting for that.
    // * If it looks like a fix genuinely can't be applied we need to bail out.
    //   Detect this when a fix fails to get applied *and* no suggestions
    //   successfully applied to the same file. In that case looks like we
    //   definitely can't make progress, so bail out.
    let mut fixes = FixedCrate::default();
    let mut last_fix_counts = HashMap::new();
    let iterations = env::var("CARGO_FIX_MAX_RETRIES")
        .ok()
        .and_then(|n| n.parse().ok())
        .unwrap_or(4);
    for _ in 0..iterations {
        last_fix_counts.clear();
        for (path, file) in fixes.files.iter_mut() {
            last_fix_counts.insert(path.clone(), file.fixes_applied);
            // We'll generate new errors below.
            file.errors_applying_fixes.clear();
        }
        rustfix_and_fix(&mut fixes, rustc, filename, args, config)?;
        let mut progress_yet_to_be_made = false;
        for (path, file) in fixes.files.iter_mut() {
            if file.errors_applying_fixes.is_empty() {
                continue;
            }
            // If anything was successfully fixed *and* there's at least one
            // error, then assume the error was spurious and we'll try again on
            // the next iteration.
            if file.fixes_applied != *last_fix_counts.get(path).unwrap_or(&0) {
                progress_yet_to_be_made = true;
            }
        }
        if !progress_yet_to_be_made {
            break;
        }
    }
    // Any errors still remaining at this point need to be reported as probably
    // bugs in Cargo and/or rustfix.
    for (path, file) in fixes.files.iter_mut() {
        for error in file.errors_applying_fixes.drain(..) {
            Message::ReplaceFailed {
                file: path.clone(),
                message: error,
            }
            .post()?;
        }
    }
    Ok(fixes)
}
fn rustfix_crate ( lock_addr : & str , rustc : & ProcessBuilder , filename : & Path , args : & FixArgs , config : & Config , ) -> Result < FixedCrate , Error > { if ! args . can_run_rustfix ( config ) ? { // This fix should not be run. Skipping... return Ok ( FixedCrate :: default ( ) ) ; } // First up, we want to make sure that each crate is only checked by one // process at a time. If two invocations concurrently check a crate then // it's likely to corrupt it. // // Historically this used per-source-file locking, then per-package // locking. It now uses a single, global lock as some users do things like // #[path] or include!() of shared files between packages. Serializing // makes it slower, but is the only safe way to prevent concurrent // modification. let _lock = LockServerClient :: lock ( & lock_addr . parse ( ) ? , " " ) ? ; // Next up, this is a bit suspicious, but we *iteratively* execute rustc and // collect suggestions to feed to rustfix. Once we hit our limit of times to // execute rustc or we appear to be reaching a fixed point we stop running // rustc. // // This is currently done to handle code like: // //      ::foo::<::Bar>(); // // where there are two fixes to happen here: `crate::foo::<crate::Bar>()`. // The spans for these two suggestions are overlapping and its difficult in // the compiler to **not** have overlapping spans here. As a result, a naive // implementation would feed the two compiler suggestions for the above fix // into `rustfix`, but one would be rejected because it overlaps with the // other. // // In this case though, both suggestions are valid and can be automatically // applied! To handle this case we execute rustc multiple times, collecting // fixes each time we do so. Along the way we discard any suggestions that // failed to apply, assuming that they can be fixed the next time we run // rustc. // // Naturally, we want a few protections in place here though to avoid looping // forever or otherwise losing data. To that end we have a few termination // conditions: // // * Do this whole process a fixed number of times. In theory we probably //   need an infinite number of times to apply fixes, but we're not gonna //   sit around waiting for that. // * If it looks like a fix genuinely can't be applied we need to bail out. //   Detect this when a fix fails to get applied *and* no suggestions //   successfully applied to the same file. In that case looks like we //   definitely can't make progress, so bail out. let mut fixes = FixedCrate :: default ( ) ; let mut last_fix_counts = HashMap :: new ( ) ; let iterations = env :: var ( " " ) . ok ( ) . and_then ( | n | n . parse ( ) . ok ( ) ) . unwrap_or ( 4 ) ; for _ in 0 .. iterations { last_fix_counts . clear ( ) ; for ( path , file ) in fixes . files . iter_mut ( ) { last_fix_counts . insert ( path . clone ( ) , file . fixes_applied ) ; // We'll generate new errors below. file . errors_applying_fixes . clear ( ) ; } rustfix_and_fix ( & mut fixes , rustc , filename , args , config ) ? ; let mut progress_yet_to_be_made = false ; for ( path , file ) in fixes . files . iter_mut ( ) { if file . errors_applying_fixes . is_empty ( ) { continue ; } // If anything was successfully fixed *and* there's at least one // error, then assume the error was spurious and we'll try again on // the next iteration. if file . fixes_applied != * last_fix_counts . get ( path ) . unwrap_or ( & 0 ) { progress_yet_to_be_made = true ; } } if ! progress_yet_to_be_made { break ; } } // Any errors still remaining at this point need to be reported as probably // bugs in Cargo and/or rustfix. for ( path , file ) in fixes . files . iter_mut ( ) { for error in file . errors_applying_fixes . drain ( .. ) { Message :: ReplaceFailed { file : path . clone ( ) , message : error , } . post ( ) ? ; } } Ok ( fixes ) }
Attempts to apply fixes to a single crate.
Attempts to apply fixes to a single crate .
lock_addr
&str
rustc
&ProcessBuilder
filename
&Path
args
&FixArgs
config
&Config
lock_addr
&str
rustc
&ProcessBuilder
filename
&Path
args
&FixArgs
config
&Config