diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2024-12-05 21:19:08 +0000 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2024-12-10 18:17:24 +0000 |
| commit | 69fb612608f6b3d7f21a4efae869e69ca949955f (patch) | |
| tree | 7ccfffcd5eaa17872e697268c7be73985c42a25b /compiler/rustc_resolve/src/ident.rs | |
| parent | 3f52583c6a85f243e8444145e533fa799a40f777 (diff) | |
| download | rust-69fb612608f6b3d7f21a4efae869e69ca949955f.tar.gz rust-69fb612608f6b3d7f21a4efae869e69ca949955f.zip | |
Keep track of parse errors in `mod`s and don't emit resolve errors for paths involving them
When we expand a `mod foo;` and parse `foo.rs`, we now track whether that file had an unrecovered parse error that reached the end of the file. If so, we keep that information around. When resolving a path like `foo::bar`, we do not emit any errors for "`bar` not found in `foo`", as we know that the parse error might have caused `bar` to not be parsed and accounted for. When this happens in an existing project, every path referencing `foo` would be an irrelevant compile error. Instead, we now skip emitting anything until `foo.rs` is fixed. Tellingly enough, we didn't have any test for errors caused by `mod` expansion. Fix #97734.
Diffstat (limited to 'compiler/rustc_resolve/src/ident.rs')
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 82 |
1 files changed, 53 insertions, 29 deletions
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 466e190028a..5906a682f3e 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<Import<'ra>>, ) -> 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, + ) + }, + ); } } } |
