diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 354023cea9e07..67495461d69ca 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1726,6 +1726,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 // on `try_to_translate_virtual_to_real`).
                 try_to_translate_virtual_to_real(&mut name);
 
+                // We may have had different remap-path-prefix flags at the time this file was loaded.
+                // Apply the remapping for the current session.
+                // NOTE: this does not "undo and redo" the mapping - any existing remapping from the old
+                // crate is retained unmodified. Only files which were never remapped are considered.
+                name = sess.source_map().path_mapping().map_filename_prefix(&name);
+
                 let local_version = sess.source_map().new_imported_source_file(
                     name,
                     src_hash,
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index dcf346acb334e..9af3351ad8b2e 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -320,7 +320,7 @@ impl SourceMap {
         // Note that filename may not be a valid path, eg it may be `<anon>` etc,
         // but this is okay because the directory determined by `path.pop()` will
         // be empty, so the working directory will be used.
-        let (filename, _) = self.path_mapping.map_filename_prefix(&filename);
+        let filename = self.path_mapping.map_filename_prefix(&filename);
 
         let file_id = StableSourceFileId::new_from_name(&filename, LOCAL_CRATE);
         match self.source_file_by_stable_id(file_id) {
@@ -995,7 +995,7 @@ impl SourceMap {
 
     pub fn get_source_file(&self, filename: &FileName) -> Option<Lrc<SourceFile>> {
         // Remap filename before lookup
-        let filename = self.path_mapping().map_filename_prefix(filename).0;
+        let filename = self.path_mapping().map_filename_prefix(filename);
         for sf in self.files.borrow().source_files.iter() {
             if filename == sf.name {
                 return Some(sf.clone());
@@ -1147,9 +1147,12 @@ impl FilePathMapping {
         }
     }
 
-    fn map_filename_prefix(&self, file: &FileName) -> (FileName, bool) {
+    /// Given a `file`, map it using the `remap-path-prefix` options for the current `Session`.
+    ///
+    /// Public for use in rustc_metadata::decoder
+    pub fn map_filename_prefix(&self, file: &FileName) -> FileName {
         match file {
-            FileName::Real(realfile) if let RealFileName::LocalPath(local_path) = realfile => {
+            FileName::Real(realfile @ RealFileName::LocalPath(local_path)) => {
                 let (mapped_path, mapped) = self.map_prefix(local_path);
                 let realfile = if mapped {
                     RealFileName::Remapped {
@@ -1159,10 +1162,16 @@ impl FilePathMapping {
                 } else {
                     realfile.clone()
                 };
-                (FileName::Real(realfile), mapped)
+                FileName::Real(realfile)
+            }
+            existing @ FileName::Real(RealFileName::Remapped { .. }) => {
+                // This can happen if we are remapping the name of file that was loaded in a
+                // different Session, and inconsistent `remap-path-prefix` flags were passed between
+                // sessions. It's unclear what to do here. For now, respect the original flag, not
+                // the flag from the current session.
+                existing.clone()
             }
-            FileName::Real(_) => unreachable!("attempted to remap an already remapped filename"),
-            other => (other.clone(), false),
+            other => other.clone(),
         }
     }
 
diff --git a/tests/run-make/remap-path-prefix-inconsistent/Makefile b/tests/run-make/remap-path-prefix-inconsistent/Makefile
new file mode 100644
index 0000000000000..47d10ea645bf0
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-inconsistent/Makefile
@@ -0,0 +1,25 @@
+
+include ../tools.mk
+
+all: inconsistent-mapping last-crate-only remap-scope
+
+last-crate-only:
+	$(RUSTC) is_true.rs --crate-type lib
+	$(RUSTC) main.rs --remap-path-prefix=$(CURDIR)=/TEST_DIR 2>$(TMPDIR)/last-crate.txt --extern is_true=$(TMPDIR)/libis_true.rlib || true
+	$(RUSTC_TEST_OP) $(TMPDIR)/last-crate.txt expected-last-crate.txt
+	$(CGREP) "/TEST_DIR" < $(TMPDIR)/last-crate.txt
+
+# exactly like `last-crate-only`, but also uses `-Z remap-path-scope=diagnostics`
+remap-scope:
+	$(RUSTC) is_true.rs --crate-type lib
+	$(RUSTC) main.rs -Z remap-path-scope=diagnostics --remap-path-prefix=$(CURDIR)=/TEST_DIR 2>$(TMPDIR)/last-crate.txt --extern is_true=$(TMPDIR)/libis_true.rlib || true
+	$(RUSTC_TEST_OP) $(TMPDIR)/last-crate.txt expected-last-crate.txt
+	$(CGREP) "/TEST_DIR" < $(TMPDIR)/last-crate.txt
+	# Now again, but excluding diagnostics
+	$(RUSTC) main.rs -Z remap-path-scope=object --remap-path-prefix=$(CURDIR)=/TEST_DIR --extern is_true=$(TMPDIR)/libis_true.rlib 2>&1 | $(CGREP) tests/run-make/
+
+inconsistent-mapping:
+	$(RUSTC) is_true.rs --remap-path-prefix=$(CURDIR)=/TEST_DIR1 --crate-type lib
+	$(RUSTC) main.rs --remap-path-prefix=$(CURDIR)=/TEST_DIR2 2>$(TMPDIR)/inconsistent.txt --extern is_true=$(TMPDIR)/libis_true.rlib || true
+	$(RUSTC_TEST_OP) $(TMPDIR)/inconsistent.txt expected-inconsistent.txt
+	$(CGREP) "/TEST_DIR1" < $(TMPDIR)/inconsistent.txt
diff --git a/tests/run-make/remap-path-prefix-inconsistent/expected-inconsistent.txt b/tests/run-make/remap-path-prefix-inconsistent/expected-inconsistent.txt
new file mode 100644
index 0000000000000..f88eede6320b3
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-inconsistent/expected-inconsistent.txt
@@ -0,0 +1,16 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+ --> main.rs:2:5
+  |
+2 |     is_true::query();
+  |     ^^^^^^^^^^^^^^-- an argument of type `bool` is missing
+  |
+note: function defined here
+ --> /TEST_DIR1/is_true.rs:1:8
+help: provide the argument
+  |
+2 |     is_true::query(/* bool */);
+  |                   ~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/run-make/remap-path-prefix-inconsistent/expected-last-crate.txt b/tests/run-make/remap-path-prefix-inconsistent/expected-last-crate.txt
new file mode 100644
index 0000000000000..239b9297c5e9c
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-inconsistent/expected-last-crate.txt
@@ -0,0 +1,19 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+ --> main.rs:2:5
+  |
+2 |     is_true::query();
+  |     ^^^^^^^^^^^^^^-- an argument of type `bool` is missing
+  |
+note: function defined here
+ --> /TEST_DIR/is_true.rs:1:8
+  |
+1 | pub fn query(_: bool) {}
+  |        ^^^^^
+help: provide the argument
+  |
+2 |     is_true::query(/* bool */);
+  |                   ~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/run-make/remap-path-prefix-inconsistent/is_true.rs b/tests/run-make/remap-path-prefix-inconsistent/is_true.rs
new file mode 100644
index 0000000000000..93153ce588232
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-inconsistent/is_true.rs
@@ -0,0 +1 @@
+pub fn query(_: bool) {}
diff --git a/tests/run-make/remap-path-prefix-inconsistent/main.rs b/tests/run-make/remap-path-prefix-inconsistent/main.rs
new file mode 100644
index 0000000000000..169371a198413
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-inconsistent/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+    is_true::query();
+}