Skip to content

Commit

Permalink
Add hints for the case of confusing enum with its variants
Browse files Browse the repository at this point in the history
  • Loading branch information
Menschenkindlein committed Nov 13, 2017
1 parent c703ff2 commit 21c580e
Showing 1 changed file with 79 additions and 0 deletions.
79 changes: 79 additions & 0 deletions src/librustc_resolve/lib.rs
Expand Up @@ -2599,6 +2599,21 @@ impl<'a> Resolver<'a> {
}
_ => {}
},
(Def::Enum(..), PathSource::TupleStruct) => {
if let Some(variants) = this.collect_enum_variants(def) {
err.note(&format!("did you mean to use one \
of the following variants?\n{}",
variants.iter()
.map(|suggestion| format!("- `{}`",
path_names_to_string(suggestion)))
.collect::<Vec<_>>()
.join("\n")));

} else {
err.note("did you mean to use one of the enum's variants?");
}
return (err, candidates);
},
_ if ns == ValueNS && is_struct_like(def) => {
if let Def::Struct(def_id) = def {
if let Some((ctor_def, ctor_vis))
Expand Down Expand Up @@ -3495,6 +3510,70 @@ impl<'a> Resolver<'a> {
candidates
}

fn find_module(&mut self,
module_def: Def)
-> Option<(Module<'a>, ImportSuggestion)>
{
let mut result = None;
let mut worklist = Vec::new();
let mut seen_modules = FxHashSet();
worklist.push((self.graph_root, Vec::new()));

while let Some((in_module, path_segments)) = worklist.pop() {
// abort if the module is already found
if let Some(_) = result { break; }

self.populate_module_if_necessary(in_module);

in_module.for_each_child(|ident, _, name_binding| {
// abort if the module is already found
if let Some(_) = result {
return ();
}
if let Some(module) = name_binding.module() {
// form the path
let mut path_segments = path_segments.clone();
path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
if module.def() == Some(module_def) {
let path = Path {
span: name_binding.span,
segments: path_segments,
};
result = Some((module, ImportSuggestion { path: path }));
} else {
// add the module to the lookup
if seen_modules.insert(module.def_id().unwrap()) {
worklist.push((module, path_segments));
}
}
}
});
}

result
}

fn collect_enum_variants(&mut self, enum_def: Def) -> Option<Vec<Path>> {
if let Def::Enum(..) = enum_def {} else {
panic!("Non-enum def passed to collect_enum_variants: {:?}", enum_def)
}

self.find_module(enum_def).map(|(enum_module, enum_import_suggestion)| {
let mut variants = Vec::new();
enum_module.for_each_child_stable(|ident, _, name_binding| {
if let Def::Variant(..) = name_binding.def() {
let mut segms = enum_import_suggestion.path.segments.clone();
segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
variants.push(Path {
span: name_binding.span,
segments: segms,
});
}
});
variants
})
}

fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
debug!("(recording def) recording {:?} for {}", resolution, node_id);
if let Some(prev_res) = self.def_map.insert(node_id, resolution) {
Expand Down

0 comments on commit 21c580e

Please sign in to comment.