diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 650525a2f520e..a219f1dc03299 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2877,7 +2877,7 @@ pub enum ModKind {
/// or with definition outlined to a separate file `mod foo;` and already loaded from it.
/// The inner span is from the first token past `{` to the last token until `}`,
/// or from the first to the last token in the loaded file.
- Loaded(ThinVec
>, Inline, ModSpans),
+ Loaded(ThinVec
>, Inline, ModSpans, Result<(), ErrorGuaranteed>),
/// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it.
Unloaded,
}
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 2c09059fe1904..0e299c604790c 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1212,7 +1212,12 @@ impl WalkItemKind for ItemKind {
ItemKind::Mod(safety, mod_kind) => {
visit_safety(vis, safety);
match mod_kind {
- ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => {
+ ModKind::Loaded(
+ items,
+ _inline,
+ ModSpans { inner_span, inject_use_span },
+ _,
+ ) => {
items.flat_map_in_place(|item| vis.flat_map_item(item));
vis.visit_span(inner_span);
vis.visit_span(inject_use_span);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index a7f7c37693a84..a6232b6dfaf86 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -380,7 +380,7 @@ impl WalkItemKind for ItemKind {
try_visit!(visitor.visit_fn(kind, span, id));
}
ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
- ModKind::Loaded(items, _inline, _inner_span) => {
+ ModKind::Loaded(items, _inline, _inner_span, _) => {
walk_list!(visitor, visit_item, items);
}
ModKind::Unloaded => {}
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 7d6c41992eb09..d63131eacb555 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -238,7 +238,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
})
}
ItemKind::Mod(_, mod_kind) => match mod_kind {
- ModKind::Loaded(items, _, spans) => {
+ ModKind::Loaded(items, _, spans, _) => {
hir::ItemKind::Mod(self.lower_mod(items, spans))
}
ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 64e91c91e2ca3..290c2e5297014 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1029,7 +1029,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
}
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
- if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
+ if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _))
&& !attr::contains_name(&item.attrs, sym::path)
{
self.check_mod_file_item_asciionly(item.ident);
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index b2048c534a48a..e7ff65e08f9cd 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -141,8 +141,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
// We don't want to recurse into anything other than mods, since
// mods or tests inside of functions will break things
- if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) =
- item.kind
+ if let ast::ItemKind::Mod(
+ _,
+ ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _),
+ ) = item.kind
{
let prev_tests = mem::take(&mut self.tests);
walk_item_kind(
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 6a6496f982702..690e080fbfce5 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -723,7 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
item_inner.kind,
ItemKind::Mod(
_,
- ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _),
+ ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _),
)
) =>
{
@@ -889,7 +889,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
fn visit_item(&mut self, item: &'ast ast::Item) {
match &item.kind {
ItemKind::Mod(_, mod_kind)
- if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
+ if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) =>
{
feature_err(
self.sess,
@@ -1195,7 +1195,7 @@ impl InvocationCollectorNode for P {
let ecx = &mut collector.cx;
let (file_path, dir_path, dir_ownership) = match mod_kind {
- ModKind::Loaded(_, inline, _) => {
+ ModKind::Loaded(_, inline, _, _) => {
// Inline `mod foo { ... }`, but we still need to push directories.
let (dir_path, dir_ownership) = mod_dir_path(
ecx.sess,
@@ -1217,15 +1217,21 @@ impl InvocationCollectorNode for P {
ModKind::Unloaded => {
// We have an outline `mod foo;` so we need to parse the file.
let old_attrs_len = attrs.len();
- let ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } =
- parse_external_mod(
- ecx.sess,
- ident,
- span,
- &ecx.current_expansion.module,
- ecx.current_expansion.dir_ownership,
- &mut attrs,
- );
+ let ParsedExternalMod {
+ items,
+ spans,
+ file_path,
+ dir_path,
+ dir_ownership,
+ had_parse_error,
+ } = parse_external_mod(
+ ecx.sess,
+ ident,
+ span,
+ &ecx.current_expansion.module,
+ ecx.current_expansion.dir_ownership,
+ &mut attrs,
+ );
if let Some(lint_store) = ecx.lint_store {
lint_store.pre_expansion_lint(
@@ -1239,7 +1245,7 @@ impl InvocationCollectorNode for P {
);
}
- *mod_kind = ModKind::Loaded(items, Inline::No, spans);
+ *mod_kind = ModKind::Loaded(items, Inline::No, spans, had_parse_error);
node.attrs = attrs;
if node.attrs.len() > old_attrs_len {
// If we loaded an out-of-line module and added some inner attributes,
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 614f52bbd2851..85ea42e78ad49 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -37,6 +37,7 @@ pub(crate) struct ParsedExternalMod {
pub file_path: PathBuf,
pub dir_path: PathBuf,
pub dir_ownership: DirOwnership,
+ pub had_parse_error: Result<(), ErrorGuaranteed>,
}
pub enum ModError<'a> {
@@ -74,14 +75,17 @@ pub(crate) fn parse_external_mod(
attrs.extend(inner_attrs);
(items, inner_span, mp.file_path)
};
+
// (1) ...instead, we return a dummy module.
- let (items, spans, file_path) =
- result.map_err(|err| err.report(sess, span)).unwrap_or_default();
+ let ((items, spans, file_path), had_parse_error) = match result {
+ Err(err) => (Default::default(), Err(err.report(sess, span))),
+ Ok(result) => (result, Ok(())),
+ };
// Extract the directory path for submodules of the module.
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
- ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership }
+ ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership, had_parse_error }
}
pub(crate) fn mod_dir_path(
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 093cc16fb4c18..3543784bc7283 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -3038,7 +3038,7 @@ impl EarlyLintPass for SpecialModuleName {
for item in &krate.items {
if let ast::ItemKind::Mod(
_,
- ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _),
+ ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _),
) = item.kind
{
if item.attrs.iter().any(|a| a.has_name(sym::path)) {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 58b4bf8980b1f..e27fc963eb901 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -45,7 +45,7 @@ impl<'a> Parser<'a> {
let (inner_attrs, items, inner_span) =
self.parse_mod(&token::CloseDelim(Delimiter::Brace))?;
attrs.extend(inner_attrs);
- ModKind::Loaded(items, Inline::Yes, inner_span)
+ ModKind::Loaded(items, Inline::Yes, inner_span, Ok(()))
};
Ok((id, ItemKind::Mod(safety, mod_kind)))
}
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 293cee500bbd8..924b8afa329f2 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -770,7 +770,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
);
}
- ItemKind::Mod(..) => {
+ ItemKind::Mod(.., ref mod_kind) => {
let module = self.r.new_module(
Some(parent),
ModuleKind::Def(def_kind, def_id, ident.name),
@@ -781,6 +781,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
);
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
+ if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind {
+ self.r.mods_with_parse_errors.insert(def_id);
+ }
+
// Descend into the module.
self.parent_scope.module = module;
}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 4c76617a3918d..368eb3c26c7b3 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -3056,7 +3056,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
fn visit_item(&mut self, item: &'tcx ast::Item) {
if self.target_module == item.id {
- if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
+ if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
let inject = mod_spans.inject_use_span;
if is_span_suitable_for_use_injection(inject) {
self.first_legal_span = Some(inject);
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 466e190028ac9..5906a682f3e1a 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1428,6 +1428,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ignore_import: Option>,
) -> PathResult<'ra> {
let mut module = None;
+ let mut module_had_parse_errors = false;
let mut allow_super = true;
let mut second_binding = None;
@@ -1471,9 +1472,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
continue;
}
}
- return PathResult::failed(ident, false, finalize.is_some(), module, || {
- ("there are too many leading `super` keywords".to_string(), None)
- });
+ return PathResult::failed(
+ ident,
+ false,
+ finalize.is_some(),
+ module_had_parse_errors,
+ module,
+ || ("there are too many leading `super` keywords".to_string(), None),
+ );
}
if segment_idx == 0 {
if name == kw::SelfLower {
@@ -1511,19 +1517,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Report special messages for path segment keywords in wrong positions.
if ident.is_path_segment_keyword() && segment_idx != 0 {
- return PathResult::failed(ident, false, finalize.is_some(), module, || {
- let name_str = if name == kw::PathRoot {
- "crate root".to_string()
- } else {
- format!("`{name}`")
- };
- let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
- format!("global paths cannot start with {name_str}")
- } else {
- format!("{name_str} in paths can only be used in start position")
- };
- (label, None)
- });
+ return PathResult::failed(
+ ident,
+ false,
+ finalize.is_some(),
+ module_had_parse_errors,
+ module,
+ || {
+ let name_str = if name == kw::PathRoot {
+ "crate root".to_string()
+ } else {
+ format!("`{name}`")
+ };
+ let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
+ format!("global paths cannot start with {name_str}")
+ } else {
+ format!("{name_str} in paths can only be used in start position")
+ };
+ (label, None)
+ },
+ );
}
let binding = if let Some(module) = module {
@@ -1589,6 +1602,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
if let Some(next_module) = binding.module() {
+ if self.mods_with_parse_errors.contains(&next_module.def_id()) {
+ module_had_parse_errors = true;
+ }
module = Some(ModuleOrUniformRoot::Module(next_module));
record_segment_res(self, res);
} else if res == Res::ToolMod && !is_last && opt_ns.is_some() {
@@ -1614,6 +1630,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ident,
is_last,
finalize.is_some(),
+ module_had_parse_errors,
module,
|| {
let label = format!(
@@ -1637,19 +1654,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
- return PathResult::failed(ident, is_last, finalize.is_some(), module, || {
- self.report_path_resolution_error(
- path,
- opt_ns,
- parent_scope,
- ribs,
- ignore_binding,
- ignore_import,
- module,
- segment_idx,
- ident,
- )
- });
+ return PathResult::failed(
+ ident,
+ is_last,
+ finalize.is_some(),
+ module_had_parse_errors,
+ module,
+ || {
+ self.report_path_resolution_error(
+ path,
+ opt_ns,
+ parent_scope,
+ ribs,
+ ignore_binding,
+ ignore_import,
+ module,
+ segment_idx,
+ ident,
+ )
+ },
+ );
}
}
}
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 51fbcb8ebb805..2ed3f4d2c4fbb 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -670,9 +670,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
fn throw_unresolved_import_error(
&mut self,
- errors: Vec<(Import<'_>, UnresolvedImportError)>,
+ mut errors: Vec<(Import<'_>, UnresolvedImportError)>,
glob_error: bool,
) {
+ errors.retain(|(_import, err)| match err.module {
+ // Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors.
+ Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,
+ _ => true,
+ });
if errors.is_empty() {
return;
}
@@ -898,6 +903,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
label,
suggestion,
module,
+ error_implied_by_parse_error: _,
} => {
if no_ambiguity {
assert!(import.imported_module.get().is_none());
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 789d74876f722..5cb7bb9b461c4 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4395,6 +4395,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
PartialRes::new(module.res().unwrap())
}
+ // A part of this path references a `mod` that had a parse error. To avoid resolution
+ // errors for each reference to that module, we don't emit an error for them until the
+ // `mod` is fixed. this can have a significant cascade effect.
+ PathResult::Failed { error_implied_by_parse_error: true, .. } => {
+ PartialRes::new(Res::Err)
+ }
// In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we
// don't report an error right away, but try to fallback to a primitive type.
// So, we are still able to successfully resolve something like
@@ -4443,6 +4449,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
suggestion,
module,
segment_name,
+ error_implied_by_parse_error: _,
} => {
return Err(respan(span, ResolutionError::FailedToResolve {
segment: Some(segment_name),
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ca4adce37ce03..94adfcd3b915d 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -450,6 +450,7 @@ enum PathResult<'ra> {
module: Option>,
/// The segment name of target
segment_name: Symbol,
+ error_implied_by_parse_error: bool,
},
}
@@ -458,6 +459,7 @@ impl<'ra> PathResult<'ra> {
ident: Ident,
is_error_from_last_segment: bool,
finalize: bool,
+ error_implied_by_parse_error: bool,
module: Option>,
label_and_suggestion: impl FnOnce() -> (String, Option),
) -> PathResult<'ra> {
@@ -470,6 +472,7 @@ impl<'ra> PathResult<'ra> {
suggestion,
is_error_from_last_segment,
module,
+ error_implied_by_parse_error,
}
}
}
@@ -1198,6 +1201,8 @@ pub struct Resolver<'ra, 'tcx> {
/// This is the `Span` where an `extern crate foo;` suggestion would be inserted, if `foo`
/// could be a crate that wasn't imported. For diagnostics use only.
current_crate_outer_attr_insert_span: Span,
+
+ mods_with_parse_errors: FxHashSet,
}
/// This provides memory for the rest of the crate. The `'ra` lifetime that is
@@ -1543,6 +1548,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
impl_unexpanded_invocations: Default::default(),
impl_binding_keys: Default::default(),
current_crate_outer_attr_insert_span,
+ mods_with_parse_errors: Default::default(),
};
let root_parent_scope = ParentScope::module(graph_root, &resolver);
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 0b4d0e04c295c..669a9c2428f8d 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -166,7 +166,7 @@ fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bo
[seg1, seg2] if seg1.ident.name == sym::rustfmt && seg2.ident.name == sym::skip => {
if let InvocationKind::Attr { item, .. } = &invoc.kind {
if let Annotatable::Item(item) = item {
- if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _)) = item.kind {
+ if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _, _)) = item.kind {
return true;
}
}
diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
index ed27e38ef2d19..1dac7b971f957 100644
--- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
+++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
@@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]);
impl EarlyLintPass for DuplicateMod {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans)) = &item.kind
+ if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
&& let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
&& let Some(local_path) = real.into_local_path()
&& let Ok(absolute_path) = local_path.canonicalize()
diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
index ffc76366983aa..dfea40db182f2 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
@@ -163,7 +163,7 @@ impl Visitor<'_> for NestingVisitor<'_, '_> {
}
match &item.kind {
- ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => {
+ ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _, _)) => {
self.nest_level += 1;
if !self.check_indent(item.span, item.id) {
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 620a9b56eb557..12074dd16e604 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -379,7 +379,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
(Mod(lu, lmk), Mod(ru, rmk)) => {
lu == ru
&& match (lmk, rmk) {
- (ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => {
+ (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
},
(ModKind::Unloaded, ModKind::Unloaded) => true,
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 18932587f1fb0..c3debc2f4f045 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -3597,7 +3597,7 @@ pub(crate) fn rewrite_extern_crate(
pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
!matches!(
item.kind,
- ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _))
+ ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
)
}
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 493b04f16c6f4..a40ee7f66a978 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -316,12 +316,11 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
self.directory = directory;
}
match (sub_mod.ast_mod_kind, sub_mod.items) {
- (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
+ (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _, _))), _) => {
self.visit_mod_from_ast(items)
}
- (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
- self.visit_mod_outside_ast(items)
- }
+ (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _, _))), _)
+ | (_, Cow::Owned(items)) => self.visit_mod_outside_ast(items),
(_, _) => Ok(()),
}
}
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 9b116b620b79d..805e13b780367 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -927,7 +927,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
let ident_str = rewrite_ident(&self.get_context(), ident).to_owned();
self.push_str(&ident_str);
- if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans) = mod_kind {
+ if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans, _) = mod_kind {
let ast::ModSpans {
inner_span,
inject_use_span: _,
diff --git a/tests/ui/parser/circular_modules_main.stderr b/tests/ui/parser/circular_modules_main.stderr
index 2de70789358b0..e1780fe9fd9d0 100644
--- a/tests/ui/parser/circular_modules_main.stderr
+++ b/tests/ui/parser/circular_modules_main.stderr
@@ -4,22 +4,5 @@ error: circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_
LL | mod circular_modules_main;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0425]: cannot find function `hi_str` in module `circular_modules_main`
- --> $DIR/circular_modules_hello.rs:7:43
- |
-LL | println!("{}", circular_modules_main::hi_str());
- | ^^^^^^ not found in `circular_modules_main`
- |
-help: consider importing this function
- |
-LL + use hi_str;
- |
-help: if you import `hi_str`, refer to it directly
- |
-LL - println!("{}", circular_modules_main::hi_str());
-LL + println!("{}", hi_str());
- |
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs
new file mode 100644
index 0000000000000..1e0772648afec
--- /dev/null
+++ b/tests/ui/resolve/parse-error-resolve.rs
@@ -0,0 +1,7 @@
+mod parse_error;
+use parse_error::Canonical; // ok, `parse_error.rs` had parse errors
+
+fn main() {
+ let _ = "" + 1; //~ ERROR E0369
+ parse_error::Canonical.foo(); // ok, `parse_error.rs` had parse errors
+}
diff --git a/tests/ui/resolve/parse-error-resolve.stderr b/tests/ui/resolve/parse-error-resolve.stderr
new file mode 100644
index 0000000000000..30475aa0ee63e
--- /dev/null
+++ b/tests/ui/resolve/parse-error-resolve.stderr
@@ -0,0 +1,22 @@
+error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From`
+ --> $DIR/parse_error.rs:2:46
+ |
+LL | impl> From for Canonical {
+ | ^^^^ expected one of `+`, `,`, `::`, `=`, or `>`
+ |
+help: you might have meant to end the type parameters here
+ |
+LL | impl>> From for Canonical {
+ | +
+
+error[E0369]: cannot add `{integer}` to `&str`
+ --> $DIR/parse-error-resolve.rs:5:16
+ |
+LL | let _ = "" + 1;
+ | -- ^ - {integer}
+ | |
+ | &str
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/resolve/parse_error.rs b/tests/ui/resolve/parse_error.rs
new file mode 100644
index 0000000000000..4cd025e1edf5b
--- /dev/null
+++ b/tests/ui/resolve/parse_error.rs
@@ -0,0 +1,5 @@
+struct Canonical;
+impl> From for Canonical { //~ ERROR expected
+ fn foo() {}
+}
+fn bar() {}
diff --git a/tests/ui/resolve/parse_error.stderr b/tests/ui/resolve/parse_error.stderr
new file mode 100644
index 0000000000000..f764f08875ff7
--- /dev/null
+++ b/tests/ui/resolve/parse_error.stderr
@@ -0,0 +1,13 @@
+error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From`
+ --> $DIR/parse_error.rs:2:46
+ |
+LL | impl> From for Canonical {
+ | ^^^^ expected one of `+`, `,`, `::`, `=`, or `>`
+ |
+help: you might have meant to end the type parameters here
+ |
+LL | impl>> From for Canonical {
+ | +
+
+error: aborting due to 1 previous error
+