Skip to content

Commit

Permalink
Unify wording of "failed to resolve" errors with "cannot find" resolu…
Browse files Browse the repository at this point in the history
…tion errors

* Use the same wording for all macro resolution errors
* specify the scope in which the resolution failure happened

Before

```
error[E0433]: failed to resolve: `crate` in paths can only be used in start position
  --> $DIR/crate-path-non-absolute.rs:5:22
   |
LL |         let s = ::m::crate::S;
   |                      ^^^^^ `crate` in paths can only be used in start position
```
after
```
error[E0433]: cannot find module `crate` in module `m`
  --> $DIR/crate-path-non-absolute.rs:5:22
   |
LL |         let s = ::m::crate::S;
   |                      ^^^^^ `crate` in paths can only be used in start position
```
  • Loading branch information
estebank committed Jul 23, 2024
1 parent 2a1c384 commit 2abb31d
Show file tree
Hide file tree
Showing 208 changed files with 541 additions and 407 deletions.
12 changes: 9 additions & 3 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,15 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
PathResult::NonModule(partial_res) => {
expected_found_error(partial_res.expect_full_res())
}
PathResult::Failed { span, label, suggestion, .. } => {
Err(VisResolutionError::FailedToResolve(span, label, suggestion))
}
PathResult::Failed {
span, label, suggestion, segment_name, item_type, ..
} => Err(VisResolutionError::FailedToResolve(
span,
segment_name,
label,
suggestion,
item_type,
)),
PathResult::Indeterminate => Err(VisResolutionError::Indeterminate(path.span)),
}
}
Expand Down
46 changes: 38 additions & 8 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,9 +796,32 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
}
ResolutionError::FailedToResolve { segment, label, suggestion, module } => {
let mut err =
struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {label}");
ResolutionError::FailedToResolve { segment, label, suggestion, module, item_type } => {
let mut err = struct_span_code_err!(
self.dcx(),
span,
E0433,
"cannot find {item_type} `{segment}` in {}",
match module {
Some(ModuleOrUniformRoot::CurrentScope) | None => "this scope".to_string(),
Some(ModuleOrUniformRoot::Module(module)) => {
match module.kind {
ModuleKind::Def(_, _, name) if name == kw::Empty => {
"the crate root".to_string()
}
ModuleKind::Def(kind, def_id, name) => {
format!("{} `{name}`", kind.descr(def_id))
}
ModuleKind::Block => "this scope".to_string(),
}
}
Some(ModuleOrUniformRoot::CrateRootAndExternPrelude) => {
"the crate root or the list of imported crates".to_string()
}
Some(ModuleOrUniformRoot::ExternPrelude) =>
"the list of imported crates".to_string(),
},
);
err.span_label(span, label);

if let Some((suggestions, msg, applicability)) = suggestion {
Expand All @@ -811,7 +834,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {

if let Some(ModuleOrUniformRoot::Module(module)) = module
&& let Some(module) = module.opt_def_id()
&& let Some(segment) = segment
{
self.find_cfg_stripped(&mut err, &segment, module);
}
Expand Down Expand Up @@ -998,10 +1020,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
VisResolutionError::AncestorOnly(span) => {
self.dcx().create_err(errs::AncestorOnly(span))
}
VisResolutionError::FailedToResolve(span, label, suggestion) => self.into_struct_error(
span,
ResolutionError::FailedToResolve { segment: None, label, suggestion, module: None },
),
VisResolutionError::FailedToResolve(span, segment, label, suggestion, item_type) => {
self.into_struct_error(
span,
ResolutionError::FailedToResolve {
segment,
label,
suggestion,
module: None,
item_type,
},
)
}
VisResolutionError::ExpectedFound(span, path_str, res) => {
self.dcx().create_err(errs::ExpectedModuleFound { span, res, path_str })
}
Expand Down
110 changes: 81 additions & 29 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc_ast::{self as ast, NodeId};
use rustc_errors::ErrorGuaranteed;
use rustc_errors::{Applicability, ErrorGuaranteed};
use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS};
use rustc_middle::bug;
use rustc_middle::ty;
Expand Down Expand Up @@ -1483,9 +1483,42 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
continue;
}
}
return PathResult::failed(ident, false, finalize.is_some(), module, || {
("there are too many leading `super` keywords".to_string(), None)
});
let mut item_type = "module";
if path.len() == 1
&& let Some(ribs) = ribs
&& let RibKind::Normal = ribs[ValueNS][ribs[ValueNS].len() - 1].kind
{
item_type = "item";
}
return PathResult::failed(
ident,
false,
finalize.is_some(),
module,
|| {
let mut suggestion = None;
let label = if path.len() == 1
&& let Some(ribs) = ribs
&& let RibKind::Normal = ribs[ValueNS][ribs[ValueNS].len() - 1].kind
{
suggestion = Some((
vec![(ident.span.shrink_to_lo(), "r#".to_string())],
"if you still want to call your identifier `super`, use the \
raw identifier format"
.to_string(),
Applicability::MachineApplicable,
));
"can't use `super` as an identifier"
} else if segment_idx == 0 {
"can't use `super` on the crate root, there are no further modules \
to go \"up\" to"
} else {
"there are too many leading `super` keywords"
};
(label.to_string(), suggestion)
},
item_type,
);
}
if segment_idx == 0 {
if name == kw::SelfLower {
Expand Down Expand Up @@ -1517,19 +1550,26 @@ impl<'a, 'tcx> Resolver<'a, '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,
|| {
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)
},
"module",
);
}

let binding = if let Some(module) = module {
Expand Down Expand Up @@ -1625,6 +1665,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
);
(label, None)
},
"module",
);
}
}
Expand All @@ -1639,18 +1680,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}

return PathResult::failed(ident, is_last, finalize.is_some(), module, || {
self.report_path_resolution_error(
path,
opt_ns,
parent_scope,
ribs,
ignore_binding,
module,
segment_idx,
ident,
)
});
return PathResult::failed(
ident,
is_last,
finalize.is_some(),
module,
|| {
self.report_path_resolution_error(
path,
opt_ns,
parent_scope,
ribs,
ignore_binding,
module,
segment_idx,
ident,
)
},
match opt_ns {
Some(ValueNS) if path.len() == 1 => "item or value",
Some(ns) if path.len() - 1 == segment_idx => ns.descr(),
Some(_) | None => "item",
},
);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,16 +900,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
label,
suggestion,
module,
item_type,
} => {
if no_ambiguity {
assert!(import.imported_module.get().is_none());
self.report_error(
span,
ResolutionError::FailedToResolve {
segment: Some(segment_name),
segment: segment_name,
label,
suggestion,
module,
item_type,
},
);
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4312,14 +4312,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
suggestion,
module,
segment_name,
item_type,
} => {
return Err(respan(
span,
ResolutionError::FailedToResolve {
segment: Some(segment_name),
segment: segment_name,
label,
suggestion,
module,
item_type,
},
));
}
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,11 @@ enum ResolutionError<'a> {
SelfImportOnlyInImportListWithNonEmptyPrefix,
/// Error E0433: failed to resolve.
FailedToResolve {
segment: Option<Symbol>,
segment: Symbol,
label: String,
suggestion: Option<Suggestion>,
module: Option<ModuleOrUniformRoot<'a>>,
item_type: &'static str,
},
/// Error E0434: can't capture dynamic environment in a fn item.
CannotCaptureDynamicEnvironmentInFnItem,
Expand Down Expand Up @@ -288,7 +289,7 @@ enum ResolutionError<'a> {
enum VisResolutionError<'a> {
Relative2018(Span, &'a ast::Path),
AncestorOnly(Span),
FailedToResolve(Span, String, Option<Suggestion>),
FailedToResolve(Span, Symbol, String, Option<Suggestion>, &'static str),
ExpectedFound(Span, String, Res),
Indeterminate(Span),
ModuleOnly(Span),
Expand Down Expand Up @@ -430,6 +431,7 @@ enum PathResult<'a> {
module: Option<ModuleOrUniformRoot<'a>>,
/// The segment name of target
segment_name: Symbol,
item_type: &'static str,
},
}

Expand All @@ -440,6 +442,7 @@ impl<'a> PathResult<'a> {
finalize: bool,
module: Option<ModuleOrUniformRoot<'a>>,
label_and_suggestion: impl FnOnce() -> (String, Option<Suggestion>),
item_type: &'static str,
) -> PathResult<'a> {
let (label, suggestion) =
if finalize { label_and_suggestion() } else { (String::new(), None) };
Expand All @@ -450,6 +453,7 @@ impl<'a> PathResult<'a> {
suggestion,
is_error_from_last_segment,
module,
item_type,
}
}
}
Expand Down
70 changes: 40 additions & 30 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -862,44 +862,54 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
),
path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => {
let mut suggestion = None;
let (span, label, module) =
if let PathResult::Failed { span, label, module, .. } = path_res {
// try to suggest if it's not a macro, maybe a function
if let PathResult::NonModule(partial_res) =
self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
&& partial_res.unresolved_segments() == 0
{
let sm = self.tcx.sess.source_map();
let exclamation_span = sm.next_point(span);
suggestion = Some((
vec![(exclamation_span, "".to_string())],
format!(
"{} is not a macro, but a {}, try to remove `!`",
Segment::names_to_string(&path),
partial_res.base_res().descr()
),
Applicability::MaybeIncorrect,
));
}
(span, label, module)
} else {
(
path_span,
let (span, label, module, segment, item_type) = if let PathResult::Failed {
span,
label,
module,
segment_name,
item_type,
..
} = path_res
{
// try to suggest if it's not a macro, maybe a function
if let PathResult::NonModule(partial_res) =
self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
&& partial_res.unresolved_segments() == 0
{
let sm = self.tcx.sess.source_map();
let exclamation_span = sm.next_point(span);
suggestion = Some((
vec![(exclamation_span, "".to_string())],
format!(
"partially resolved path in {} {}",
kind.article(),
kind.descr()
"{} is not a macro, but a {}, try to remove `!`",
Segment::names_to_string(&path),
partial_res.base_res().descr()
),
None,
)
};
Applicability::MaybeIncorrect,
));
}
(span, label, module, segment_name, item_type)
} else {
(
path_span,
format!(
"partially resolved path in {} {}",
kind.article(),
kind.descr()
),
None,
path.last().map(|segment| segment.ident.name).unwrap(),
"macro",
)
};
self.report_error(
span,
ResolutionError::FailedToResolve {
segment: path.last().map(|segment| segment.ident.name),
segment,
label,
suggestion,
module,
item_type,
},
);
}
Expand Down
Loading

0 comments on commit 2abb31d

Please sign in to comment.