Skip to content

Commit 21c580e

Browse files
Add hints for the case of confusing enum with its variants
1 parent c703ff2 commit 21c580e

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

src/librustc_resolve/lib.rs

+79
Original file line numberDiff line numberDiff line change
@@ -2599,6 +2599,21 @@ impl<'a> Resolver<'a> {
25992599
}
26002600
_ => {}
26012601
},
2602+
(Def::Enum(..), PathSource::TupleStruct) => {
2603+
if let Some(variants) = this.collect_enum_variants(def) {
2604+
err.note(&format!("did you mean to use one \
2605+
of the following variants?\n{}",
2606+
variants.iter()
2607+
.map(|suggestion| format!("- `{}`",
2608+
path_names_to_string(suggestion)))
2609+
.collect::<Vec<_>>()
2610+
.join("\n")));
2611+
2612+
} else {
2613+
err.note("did you mean to use one of the enum's variants?");
2614+
}
2615+
return (err, candidates);
2616+
},
26022617
_ if ns == ValueNS && is_struct_like(def) => {
26032618
if let Def::Struct(def_id) = def {
26042619
if let Some((ctor_def, ctor_vis))
@@ -3495,6 +3510,70 @@ impl<'a> Resolver<'a> {
34953510
candidates
34963511
}
34973512

3513+
fn find_module(&mut self,
3514+
module_def: Def)
3515+
-> Option<(Module<'a>, ImportSuggestion)>
3516+
{
3517+
let mut result = None;
3518+
let mut worklist = Vec::new();
3519+
let mut seen_modules = FxHashSet();
3520+
worklist.push((self.graph_root, Vec::new()));
3521+
3522+
while let Some((in_module, path_segments)) = worklist.pop() {
3523+
// abort if the module is already found
3524+
if let Some(_) = result { break; }
3525+
3526+
self.populate_module_if_necessary(in_module);
3527+
3528+
in_module.for_each_child(|ident, _, name_binding| {
3529+
// abort if the module is already found
3530+
if let Some(_) = result {
3531+
return ();
3532+
}
3533+
if let Some(module) = name_binding.module() {
3534+
// form the path
3535+
let mut path_segments = path_segments.clone();
3536+
path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
3537+
if module.def() == Some(module_def) {
3538+
let path = Path {
3539+
span: name_binding.span,
3540+
segments: path_segments,
3541+
};
3542+
result = Some((module, ImportSuggestion { path: path }));
3543+
} else {
3544+
// add the module to the lookup
3545+
if seen_modules.insert(module.def_id().unwrap()) {
3546+
worklist.push((module, path_segments));
3547+
}
3548+
}
3549+
}
3550+
});
3551+
}
3552+
3553+
result
3554+
}
3555+
3556+
fn collect_enum_variants(&mut self, enum_def: Def) -> Option<Vec<Path>> {
3557+
if let Def::Enum(..) = enum_def {} else {
3558+
panic!("Non-enum def passed to collect_enum_variants: {:?}", enum_def)
3559+
}
3560+
3561+
self.find_module(enum_def).map(|(enum_module, enum_import_suggestion)| {
3562+
let mut variants = Vec::new();
3563+
enum_module.for_each_child_stable(|ident, _, name_binding| {
3564+
if let Def::Variant(..) = name_binding.def() {
3565+
let mut segms = enum_import_suggestion.path.segments.clone();
3566+
segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
3567+
variants.push(Path {
3568+
span: name_binding.span,
3569+
segments: segms,
3570+
});
3571+
}
3572+
});
3573+
variants
3574+
})
3575+
}
3576+
34983577
fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
34993578
debug!("(recording def) recording {:?} for {}", resolution, node_id);
35003579
if let Some(prev_res) = self.def_map.insert(node_id, resolution) {

0 commit comments

Comments
 (0)