E0432 and E0433 are the same error, only inconsistent
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Reporting of name resolution errors in rustc_resolve is complicated (often for good/necessary reasons). The problem is, there seems to be a significant amount of organically grown near-duplicate code for the error reporting. The same error can end up with different suggestions depending on how it was passed through the codebase.
I'm thinking about refactoring this:
- Where possible, don't emit errors immediately. Return them to the caller, and collect in
Resolveruntil the "resolve_report_errors" pass. - Where possible, instead of immediately computing error message and suggestion
String, keep relevant info until "resolve_report_errors" pass to compute suggestions indiagnostics.rs. - Where possible, use structs from
rustc_errorsfor reporting localizable errors. - Perform grouping and deduplication across multiple errors, as late as possible.
Is this the right direction?
More on the current state:
For example, a path resolution in use foo::typ0; gets a "did you mean?" spelling suggestion. The same path, resolved using the same function, failing for the same reason, won't get any suggestions if it's in pub(in foo::typ0), because the original resolution error is converted to a different error type first, skipping lookup of candidates.
There are two places that can generate "could not find `foo` in the crate root" message. I think one of them is unreachable.
The same name resolution error can go through different error reporting code depending whether the first, middle, or last segment of the path failed, even if the reason is the same:
use crate::module::function::err;
// ^ expected type, found function `function` in `module`
use crate::function::err;
// ^ could not find `function` in the crate root
// the second one is wrong; it should have been "expected type, found function `function` in in the crate root",
// but the second case tries emitting another suggestion first, which suppresses the relevant suggestion
pub fn function() {
}
mod module {
pub fn function() {
}
}
There's PathResult::Failed, UnresolvedImportError, VisResolutionError::FailedToResolve, ResolutionError::FailedToResolve, and the same failure can end up being in any one of these.
Some errors are emitted immediately as they happen, usually via report_error(). Some are bubbled up. Some of the bubbled up ones are aggregated for batches of throw_unresolved_import_error, and some are emitted before. The same name resolution error going through the batching codepath is E0432, and reporting it earlier gives it E0433.
Some errors are buffered in Resolver to be deduped and enhanced during the "resolve_report_errors" phase, but most errors are reported earlier in "finalize_imports" phase. There's a different dedupe in finalize_imports, for a different subset of errors. There's a hack for glob import failures suppressing most errors, even syntax errors unrelated to globs.
Motivation for this:
I wanted to add a suggestion for when user writes use crate::missingmod and the file src/missingmod.rs exists on disk, but there's no mod missingmod in the code.
The problem is that the import/type paths are resolved in lots of contexts that report errors in different ways. Any segment of the import path could be a missing mod, but errors about first/middle/last segment go through very different suggestion-generating code.
It's even worse than just duplication of the code for generating the suggestion. The suggestion needs a span to point out the correct place to insert the required mod in parent module's body, but this information is not easily available. It requires walking the ast, which can't be done from most places where the suggestions are currently computed. There's code in diagnostics.rs that has already implemented finding location for suggesting use $ident, and that would work for mod $ident too, but all the relevant errors are emitted early and never make it that far.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the name-resolution error paths in rustc_resolve, including PathResult::Failed, UnresolvedImportError, VisResolutionError::FailedToResolve, and ResolutionError::FailedToResolve. Read diagnostics.rs alongside the Resolver resolve_report_errors and finalize_imports phases to understand where errors are emitted, buffered, grouped, and deduplicated. Done would mean a clearly agreed refactoring direction that unifies equivalent E0432/E0433 reporting while preserving or improving suggestions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100