@@ -121,23 +121,8 @@ pub fn compile_input(trans: Box<TransCrate>,
121121 } ;
122122
123123 let outputs = build_output_filenames ( input, outdir, output, & krate. attrs , sess) ;
124-
125- // Ensure the source file isn't accidentally overwritten during compilation.
126- match * input_path {
127- 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 ) ;
133- }
134- } ,
135- None => { }
136- }
137-
138124 let crate_name =
139125 :: rustc_trans_utils:: link:: find_crate_name ( Some ( sess) , & krate. attrs , input) ;
140-
141126 let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
142127 phase_2_configure_and_expand (
143128 sess,
@@ -157,7 +142,29 @@ pub fn compile_input(trans: Box<TransCrate>,
157142 ) ?
158143 } ;
159144
160- write_out_deps ( sess, & outputs, & crate_name) ;
145+ let output_paths = generated_output_paths ( sess, & outputs, output. is_some ( ) , & crate_name) ;
146+
147+ // Ensure the source file isn't accidentally overwritten during compilation.
148+ if let Some ( ref input_path) = * input_path {
149+ if sess. opts . will_create_output_file ( ) {
150+ if output_contains_path ( & output_paths, input_path) {
151+ sess. err ( & format ! (
152+ "the input file \" {}\" would be overwritten by the generated \
153+ executable",
154+ input_path. display( ) ) ) ;
155+ return Err ( CompileIncomplete :: Stopped ) ;
156+ }
157+ if let Some ( dir_path) = output_conflicts_with_dir ( & output_paths) {
158+ sess. err ( & format ! (
159+ "the generated executable for the input file \" {}\" conflicts with the \
160+ existing directory \" {}\" ",
161+ input_path. display( ) , dir_path. display( ) ) ) ;
162+ return Err ( CompileIncomplete :: Stopped ) ;
163+ }
164+ }
165+ }
166+
167+ write_out_deps ( sess, & outputs, & output_paths) ;
161168 if sess. opts . output_types . contains_key ( & OutputType :: DepInfo ) &&
162169 sess. opts . output_types . keys ( ) . count ( ) == 1 {
163170 return Ok ( ( ) )
@@ -1101,16 +1108,22 @@ fn escape_dep_filename(filename: &FileName) -> String {
11011108 filename. to_string ( ) . replace ( " " , "\\ " )
11021109}
11031110
1104- fn write_out_deps ( sess : & Session , outputs : & OutputFilenames , crate_name : & str ) {
1111+ // Returns all the paths that correspond to generated files.
1112+ fn generated_output_paths ( sess : & Session ,
1113+ outputs : & OutputFilenames ,
1114+ exact_name : bool ,
1115+ crate_name : & str ) -> Vec < PathBuf > {
11051116 let mut out_filenames = Vec :: new ( ) ;
11061117 for output_type in sess. opts . output_types . keys ( ) {
11071118 let file = outputs. path ( * output_type) ;
11081119 match * output_type {
1109- OutputType :: Exe => {
1110- for output in sess. crate_types . borrow ( ) . iter ( ) {
1120+ // If the filename has been overridden using `-o`, it will not be modified
1121+ // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
1122+ OutputType :: Exe if !exact_name => {
1123+ for crate_type in sess. crate_types . borrow ( ) . iter ( ) {
11111124 let p = :: rustc_trans_utils:: link:: filename_for_input (
11121125 sess,
1113- * output ,
1126+ * crate_type ,
11141127 crate_name,
11151128 outputs
11161129 ) ;
@@ -1125,7 +1138,46 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
11251138 }
11261139 }
11271140 }
1141+ out_filenames
1142+ }
1143+
1144+ // Runs `f` on every output file path and returns the first non-None result, or None if `f`
1145+ // returns None for every file path.
1146+ fn check_output < F , T > ( output_paths : & Vec < PathBuf > , f : F ) -> Option < T >
1147+ where F : Fn ( & PathBuf ) -> Option < T > {
1148+ for output_path in output_paths {
1149+ if let Some ( result) = f ( output_path) {
1150+ return Some ( result) ;
1151+ }
1152+ }
1153+ None
1154+ }
11281155
1156+ pub fn output_contains_path ( output_paths : & Vec < PathBuf > , input_path : & PathBuf ) -> bool {
1157+ let input_path = input_path. canonicalize ( ) . ok ( ) ;
1158+ if input_path. is_none ( ) {
1159+ return false
1160+ }
1161+ let check = |output_path : & PathBuf | {
1162+ if output_path. canonicalize ( ) . ok ( ) == input_path {
1163+ Some ( ( ) )
1164+ } else { None }
1165+ } ;
1166+ check_output ( output_paths, check) . is_some ( )
1167+ }
1168+
1169+ pub fn output_conflicts_with_dir ( output_paths : & Vec < PathBuf > ) -> Option < PathBuf > {
1170+ let check = |output_path : & PathBuf | {
1171+ if output_path. is_dir ( ) {
1172+ Some ( output_path. clone ( ) )
1173+ } else { None }
1174+ } ;
1175+ check_output ( output_paths, check)
1176+ }
1177+
1178+ fn write_out_deps ( sess : & Session ,
1179+ outputs : & OutputFilenames ,
1180+ out_filenames : & Vec < PathBuf > ) {
11291181 // Write out dependency rules to the dep-info file if requested
11301182 if !sess. opts . output_types . contains_key ( & OutputType :: DepInfo ) {
11311183 return ;
@@ -1144,7 +1196,7 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
11441196 . map ( |fmap| escape_dep_filename ( & fmap. name ) )
11451197 . collect ( ) ;
11461198 let mut file = fs:: File :: create ( & deps_filename) ?;
1147- for path in & out_filenames {
1199+ for path in out_filenames {
11481200 write ! ( file, "{}: {}\n \n " , path. display( ) , files. join( " " ) ) ?;
11491201 }
11501202
@@ -1327,7 +1379,10 @@ pub fn build_output_filenames(input: &Input,
13271379 Some ( out_file. clone ( ) )
13281380 } ;
13291381 if * odir != None {
1330- sess. warn ( "ignoring --out-dir flag due to -o flag." ) ;
1382+ sess. warn ( "ignoring --out-dir flag due to -o flag" ) ;
1383+ }
1384+ if !sess. opts . cg . extra_filename . is_empty ( ) {
1385+ sess. warn ( "ignoring -C extra-filename flag due to -o flag" ) ;
13311386 }
13321387
13331388 let cur_dir = Path :: new ( "" ) ;
0 commit comments