Skip to content

Commit df1c61d

Browse files
committed
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 rust-lang#35887.
1 parent 6b99ade commit df1c61d

File tree

4 files changed

+61
-14
lines changed

4 files changed

+61
-14
lines changed

src/librustc/session/config.rs

+29-9
Original file line numberDiff line numberDiff line change
@@ -549,24 +549,44 @@ impl OutputFilenames {
549549
format!("{}{}", self.out_filestem, self.extra)
550550
}
551551

552-
pub fn contains_path(&self, input_path: &PathBuf) -> bool {
553-
let input_path = input_path.canonicalize().ok();
554-
if input_path.is_none() {
555-
return false
556-
}
552+
fn check_output<F, T>(&self, f: F) -> Option<T> where F: Fn(PathBuf) -> Option<T> {
557553
match self.single_output_file {
558-
Some(ref output_path) => output_path.canonicalize().ok() == input_path,
554+
Some(ref output_path) => {
555+
f(output_path.clone())
556+
},
559557
None => {
560558
for k in self.outputs.keys() {
561559
let output_path = self.path(k.to_owned());
562-
if output_path.canonicalize().ok() == input_path {
563-
return true;
560+
if let Some(result) = f(output_path) {
561+
return Some(result);
564562
}
565563
}
566-
false
564+
None
567565
}
568566
}
569567
}
568+
569+
pub fn contains_path(&self, input_path: &PathBuf) -> bool {
570+
let input_path = input_path.canonicalize().ok();
571+
if input_path.is_none() {
572+
return false
573+
}
574+
let check = |output_path: PathBuf| {
575+
if output_path.canonicalize().ok() == input_path {
576+
Some(())
577+
} else { None }
578+
};
579+
self.check_output(check).is_some()
580+
}
581+
582+
pub fn conflicts_with_dir(&self) -> Option<PathBuf> {
583+
let check = |output_path: PathBuf| {
584+
if output_path.is_dir() {
585+
Some(output_path)
586+
} else { None }
587+
};
588+
self.check_output(check)
589+
}
570590
}
571591

572592
pub fn host_triple() -> &'static str {

src/librustc_driver/driver.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,20 @@ pub fn compile_input(trans: Box<TransCrate>,
125125
// Ensure the source file isn't accidentally overwritten during compilation.
126126
match *input_path {
127127
Some(ref input_path) => {
128-
if outputs.contains_path(input_path) && sess.opts.will_create_output_file() {
129-
sess.err(&format!(
130-
"the input file \"{}\" would be overwritten by the generated executable",
131-
input_path.display()));
132-
return Err(CompileIncomplete::Stopped);
128+
if sess.opts.will_create_output_file() {
129+
if outputs.contains_path(input_path) {
130+
sess.err(&format!(
131+
"the input file \"{}\" would be overwritten by the generated executable",
132+
input_path.display()));
133+
return Err(CompileIncomplete::Stopped);
134+
}
135+
if let Some(dir_path) = outputs.conflicts_with_dir() {
136+
sess.err(&format!(
137+
"the generated executable for the input file \"{}\" conflicts with the \
138+
existing directory \"{}\'",
139+
input_path.display(), dir_path.display()));
140+
return Err(CompileIncomplete::Stopped);
141+
}
133142
}
134143
},
135144
None => {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-include ../tools.mk
2+
3+
all:
4+
cp foo.rs $(TMPDIR)/foo.rs
5+
mkdir $(TMPDIR)/foo
6+
$(RUSTC) $(TMPDIR)/foo.rs 2>&1 \
7+
| $(CGREP) -e "the generated executable for the input file \".*foo\.rs\" conflicts with the existing directory \".*foo\'"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {}

0 commit comments

Comments
 (0)