diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index b9546143a054..b04376000c0e 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -549,23 +549,43 @@ impl OutputFilenames { format!("{}{}", self.out_filestem, self.extra) } + fn check_output(&self, f: F) -> Option where F: Fn(PathBuf) -> Option { + 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 { + let check = |output_path: PathBuf| { + if output_path.is_dir() { + Some(output_path) + } else { None } + }; + self.check_output(check) } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e97d83ed1ee5..5875ccbfd585 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -125,11 +125,20 @@ pub fn compile_input(trans: Box, // 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 => {} diff --git a/src/test/run-make/output-filename-conflicts-with-directory/Makefile b/src/test/run-make/output-filename-conflicts-with-directory/Makefile new file mode 100644 index 000000000000..68f72094ce65 --- /dev/null +++ b/src/test/run-make/output-filename-conflicts-with-directory/Makefile @@ -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\'" diff --git a/src/test/run-make/output-filename-conflicts-with-directory/foo.rs b/src/test/run-make/output-filename-conflicts-with-directory/foo.rs new file mode 100644 index 000000000000..046d27a9f0fe --- /dev/null +++ b/src/test/run-make/output-filename-conflicts-with-directory/foo.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {}