]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_expand/src/module.rs
use full path for E0761
[rust.git] / compiler / rustc_expand / src / module.rs
index 2ec656d4895e7f0d960741bdf49cc6c934dc9a51..993522d01d86744bec64592c31f698d58a0e7ae2 100644 (file)
@@ -1,6 +1,6 @@
 use crate::base::ModuleData;
 use rustc_ast::ptr::P;
-use rustc_ast::{token, Attribute, Item};
+use rustc_ast::{token, Attribute, Inline, Item};
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_parse::new_parser_from_file;
 use rustc_session::parse::ParseSess;
@@ -37,7 +37,7 @@ pub enum ModError<'a> {
     CircularInclusion(Vec<PathBuf>),
     ModInBlock(Option<Ident>),
     FileNotFound(Ident, PathBuf),
-    MultipleCandidates(Ident, String, String),
+    MultipleCandidates(Ident, PathBuf, PathBuf),
     ParserError(DiagnosticBuilder<'a>),
 }
 
@@ -83,29 +83,49 @@ pub enum ModError<'a> {
     attrs: &[Attribute],
     module: &ModuleData,
     mut dir_ownership: DirOwnership,
+    inline: Inline,
 ) -> (PathBuf, DirOwnership) {
-    if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
-        // For inline modules file path from `#[path]` is actually the directory path
-        // for historical reasons, so we don't pop the last segment here.
-        return (file_path, DirOwnership::Owned { relative: None });
-    }
+    match inline {
+        Inline::Yes => {
+            if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
+                // For inline modules file path from `#[path]` is actually the directory path
+                // for historical reasons, so we don't pop the last segment here.
+                return (file_path, DirOwnership::Owned { relative: None });
+            }
 
-    // We have to push on the current module name in the case of relative
-    // paths in order to ensure that any additional module paths from inline
-    // `mod x { ... }` come after the relative extension.
-    //
-    // For example, a `mod z { ... }` inside `x/y.rs` should set the current
-    // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
-    let mut dir_path = module.dir_path.clone();
-    if let DirOwnership::Owned { relative } = &mut dir_ownership {
-        if let Some(ident) = relative.take() {
-            // Remove the relative offset.
+            // We have to push on the current module name in the case of relative
+            // paths in order to ensure that any additional module paths from inline
+            // `mod x { ... }` come after the relative extension.
+            //
+            // For example, a `mod z { ... }` inside `x/y.rs` should set the current
+            // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
+            let mut dir_path = module.dir_path.clone();
+            if let DirOwnership::Owned { relative } = &mut dir_ownership {
+                if let Some(ident) = relative.take() {
+                    // Remove the relative offset.
+                    dir_path.push(&*ident.as_str());
+                }
+            }
             dir_path.push(&*ident.as_str());
+
+            (dir_path, dir_ownership)
         }
-    }
-    dir_path.push(&*ident.as_str());
+        Inline::No => {
+            // FIXME: This is a subset of `parse_external_mod` without actual parsing,
+            // check whether the logic for unloaded, loaded and inline modules can be unified.
+            let file_path = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership)
+                .map(|mp| {
+                    dir_ownership = mp.dir_ownership;
+                    mp.file_path
+                })
+                .unwrap_or_default();
 
-    (dir_path, dir_ownership)
+            // Extract the directory path for submodules of the module.
+            let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
+
+            (dir_path, dir_ownership)
+        }
+    }
 }
 
 fn mod_file_path<'a>(
@@ -200,9 +220,7 @@ pub fn default_submod_path<'a>(
             dir_ownership: DirOwnership::Owned { relative: None },
         }),
         (false, false) => Err(ModError::FileNotFound(ident, default_path)),
-        (true, true) => {
-            Err(ModError::MultipleCandidates(ident, default_path_str, secondary_path_str))
-        }
+        (true, true) => Err(ModError::MultipleCandidates(ident, default_path, secondary_path)),
     }
 }
 
@@ -244,15 +262,15 @@ fn report(self, sess: &Session, span: Span) {
                 ));
                 err
             }
-            ModError::MultipleCandidates(ident, default_path_short, secondary_path_short) => {
+            ModError::MultipleCandidates(ident, default_path, secondary_path) => {
                 let mut err = struct_span_err!(
                     diag,
                     span,
                     E0761,
-                    "file for module `{}` found at both {} and {}",
+                    "file for module `{}` found at both \"{}\" and \"{}\"",
                     ident,
-                    default_path_short,
-                    secondary_path_short,
+                    default_path.display(),
+                    secondary_path.display(),
                 );
                 err.help("delete or rename one of them to remove the ambiguity");
                 err