Warn when rustc output conflicts with existing directories
When the compiled executable would conflict with a directory, display a rustc error instead of a verbose and potentially-confusing linker error. This is a usability improvement, and doesn’t actually change behaviour with regards to compilation success. This addresses the concern in #35887.
This commit is contained in:
parent
6b99adeb11
commit
df1c61d303
4 changed files with 64 additions and 17 deletions
|
@ -549,23 +549,43 @@ impl OutputFilenames {
|
|||
format!("{}{}", self.out_filestem, self.extra)
|
||||
}
|
||||
|
||||
fn check_output<F, T>(&self, f: F) -> Option<T> where F: Fn(PathBuf) -> Option<T> {
|
||||
match self.single_output_file {
|
||||
Some(ref output_path) => {
|
||||
f(output_path.clone())
|
||||
},
|
||||
None => {
|
||||
for k in self.outputs.keys() {
|
||||
let output_path = self.path(k.to_owned());
|
||||
if let Some(result) = f(output_path) {
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_path(&self, input_path: &PathBuf) -> bool {
|
||||
let input_path = input_path.canonicalize().ok();
|
||||
if input_path.is_none() {
|
||||
return false
|
||||
}
|
||||
match self.single_output_file {
|
||||
Some(ref output_path) => output_path.canonicalize().ok() == input_path,
|
||||
None => {
|
||||
for k in self.outputs.keys() {
|
||||
let output_path = self.path(k.to_owned());
|
||||
if output_path.canonicalize().ok() == input_path {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
let check = |output_path: PathBuf| {
|
||||
if output_path.canonicalize().ok() == input_path {
|
||||
Some(())
|
||||
} else { None }
|
||||
};
|
||||
self.check_output(check).is_some()
|
||||
}
|
||||
|
||||
pub fn conflicts_with_dir(&self) -> Option<PathBuf> {
|
||||
let check = |output_path: PathBuf| {
|
||||
if output_path.is_dir() {
|
||||
Some(output_path)
|
||||
} else { None }
|
||||
};
|
||||
self.check_output(check)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,11 +125,20 @@ pub fn compile_input(trans: Box<TransCrate>,
|
|||
// Ensure the source file isn't accidentally overwritten during compilation.
|
||||
match *input_path {
|
||||
Some(ref input_path) => {
|
||||
if outputs.contains_path(input_path) && sess.opts.will_create_output_file() {
|
||||
sess.err(&format!(
|
||||
"the input file \"{}\" would be overwritten by the generated executable",
|
||||
input_path.display()));
|
||||
return Err(CompileIncomplete::Stopped);
|
||||
if sess.opts.will_create_output_file() {
|
||||
if outputs.contains_path(input_path) {
|
||||
sess.err(&format!(
|
||||
"the input file \"{}\" would be overwritten by the generated executable",
|
||||
input_path.display()));
|
||||
return Err(CompileIncomplete::Stopped);
|
||||
}
|
||||
if let Some(dir_path) = outputs.conflicts_with_dir() {
|
||||
sess.err(&format!(
|
||||
"the generated executable for the input file \"{}\" conflicts with the \
|
||||
existing directory \"{}\'",
|
||||
input_path.display(), dir_path.display()));
|
||||
return Err(CompileIncomplete::Stopped);
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
cp foo.rs $(TMPDIR)/foo.rs
|
||||
mkdir $(TMPDIR)/foo
|
||||
$(RUSTC) $(TMPDIR)/foo.rs 2>&1 \
|
||||
| $(CGREP) -e "the generated executable for the input file \".*foo\.rs\" conflicts with the existing directory \".*foo\'"
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {}
|
Loading…
Reference in a new issue