rustc: More helpful error message when using a struct type like a function

Closes #6702
This commit is contained in:
Tim Chevalier 2013-08-13 17:54:14 -07:00
parent 5622ce10fe
commit ef8a5044ff

View File

@ -831,6 +831,7 @@ pub fn Resolver(session: Session,
trait_map: HashMap::new(),
used_imports: HashSet::new(),
emit_errors: true,
intr: session.intr()
};
@ -888,6 +889,11 @@ pub struct Resolver {
export_map2: ExportMap2,
trait_map: TraitMap,
// Whether or not to print error messages. Can be set to true
// when getting additional info for error message suggestions,
// so as to avoid printing duplicate errors
emit_errors: bool,
used_imports: HashSet<NodeId>,
}
@ -1072,7 +1078,7 @@ impl Resolver {
// Return an error here by looking up the namespace that
// had the duplicate.
let ns = ns.unwrap();
self.session.span_err(sp,
self.resolve_error(sp,
fmt!("duplicate definition of %s `%s`",
namespace_error_to_str(duplicate_type),
self.session.str_of(name)));
@ -2074,7 +2080,7 @@ impl Resolver {
self.import_path_to_str(
import_directive.module_path,
*import_directive.subclass));
self.session.span_err(import_directive.span, msg);
self.resolve_error(import_directive.span, msg);
}
Indeterminate => {
// Bail out. We'll come around next time.
@ -2445,12 +2451,12 @@ impl Resolver {
let span = directive.span;
if resolve_fail {
self.session.span_err(span, fmt!("unresolved import: there is no `%s` in `%s`",
self.resolve_error(span, fmt!("unresolved import: there is no `%s` in `%s`",
self.session.str_of(source),
self.module_to_str(containing_module)));
return Failed;
} else if priv_fail {
self.session.span_err(span, fmt!("unresolved import: found `%s` in `%s` but it is \
self.resolve_error(span, fmt!("unresolved import: found `%s` in `%s` but it is \
private", self.session.str_of(source),
self.module_to_str(containing_module)));
return Failed;
@ -2617,14 +2623,14 @@ impl Resolver {
hi: span.lo + BytePos(segment_name.len()),
expn_info: span.expn_info,
};
self.session.span_err(span,
self.resolve_error(span,
fmt!("unresolved import. maybe \
a missing `extern mod \
%s`?",
segment_name));
return Failed;
}
self.session.span_err(span, fmt!("unresolved import: could not find `%s` in \
self.resolve_error(span, fmt!("unresolved import: could not find `%s` in \
`%s`.", segment_name, module_name));
return Failed;
}
@ -2642,7 +2648,7 @@ impl Resolver {
match type_def.module_def {
None => {
// Not a module.
self.session.span_err(span,
self.resolve_error(span,
fmt!("not a \
module `%s`",
self.session.
@ -2658,7 +2664,7 @@ impl Resolver {
module_def.kind) {
(ImportSearch, TraitModuleKind) |
(ImportSearch, ImplModuleKind) => {
self.session.span_err(
self.resolve_error(
span,
"cannot import from a trait \
or type implementation");
@ -2671,7 +2677,7 @@ impl Resolver {
}
None => {
// There are no type bindings at all.
self.session.span_err(span,
self.resolve_error(span,
fmt!("not a module `%s`",
self.session.str_of(
name)));
@ -2723,7 +2729,7 @@ impl Resolver {
let mpath = self.idents_to_str(module_path);
match mpath.rfind(':') {
Some(idx) => {
self.session.span_err(span, fmt!("unresolved import: could not find `%s` \
self.resolve_error(span, fmt!("unresolved import: could not find `%s` \
in `%s`",
// idx +- 1 to account for the colons
// on either side
@ -2759,8 +2765,7 @@ impl Resolver {
module_path[0]);
match result {
Failed => {
self.session.span_err(span,
"unresolved name");
self.resolve_error(span, "unresolved name");
return Failed;
}
Indeterminate => {
@ -3140,11 +3145,11 @@ impl Resolver {
if index != import_count {
let sn = self.session.codemap.span_to_snippet(imports[index].span).unwrap();
if sn.contains("::") {
self.session.span_err(imports[index].span, "unresolved import");
self.resolve_error(imports[index].span, "unresolved import");
} else {
let err = fmt!("unresolved import (maybe you meant `%s::*`?)",
sn.slice(0, sn.len()));
self.session.span_err(imports[index].span, err);
self.resolve_error(imports[index].span, err);
}
}
@ -3409,7 +3414,7 @@ impl Resolver {
// named function item. This is not allowed, so we
// report an error.
self.session.span_err(
self.resolve_error(
span,
"can't capture dynamic environment in a fn item; \
use the || { ... } closure form instead");
@ -3417,7 +3422,7 @@ impl Resolver {
// This was an attempt to use a type parameter outside
// its scope.
self.session.span_err(span,
self.resolve_error(span,
"attempt to use a type \
argument out of scope");
}
@ -3432,7 +3437,7 @@ impl Resolver {
// named function item. This is not allowed, so we
// report an error.
self.session.span_err(
self.resolve_error(
span,
"can't capture dynamic environment in a fn item; \
use the || { ... } closure form instead");
@ -3440,7 +3445,7 @@ impl Resolver {
// This was an attempt to use a type parameter outside
// its scope.
self.session.span_err(span,
self.resolve_error(span,
"attempt to use a type \
argument out of scope");
}
@ -3449,7 +3454,7 @@ impl Resolver {
}
ConstantItemRibKind => {
// Still doesn't deal with upvars
self.session.span_err(span,
self.resolve_error(span,
"attempt to use a non-constant \
value in a constant");
@ -3846,7 +3851,7 @@ impl Resolver {
};
let msg = fmt!("attempt to %s a nonexistent trait `%s`", usage_str, path_str);
self.session.span_err(trait_reference.path.span, msg);
self.resolve_error(trait_reference.path.span, msg);
}
Some(def) => {
debug!("(resolving trait) found trait def: %?", def);
@ -3867,7 +3872,7 @@ impl Resolver {
match ident_map.find(&ident) {
Some(&prev_field) => {
let ident_str = self.session.str_of(ident);
self.session.span_err(field.span,
self.resolve_error(field.span,
fmt!("field `%s` is already declared", ident_str));
self.session.span_note(prev_field.span,
"Previously declared here");
@ -4052,7 +4057,7 @@ impl Resolver {
for (&key, &binding_0) in map_0.iter() {
match map_i.find(&key) {
None => {
self.session.span_err(
self.resolve_error(
p.span,
fmt!("variable `%s` from pattern #1 is \
not bound in pattern #%u",
@ -4060,7 +4065,7 @@ impl Resolver {
}
Some(binding_i) => {
if binding_0.binding_mode != binding_i.binding_mode {
self.session.span_err(
self.resolve_error(
binding_i.span,
fmt!("variable `%s` is bound with different \
mode in pattern #%u than in pattern #1",
@ -4072,7 +4077,7 @@ impl Resolver {
for (&key, &binding) in map_i.iter() {
if !map_0.contains_key(&key) {
self.session.span_err(
self.resolve_error(
binding.span,
fmt!("variable `%s` from pattern #%u is \
not bound in pattern #1",
@ -4185,7 +4190,7 @@ impl Resolver {
self.record_def(path_id, def);
}
None => {
self.session.span_err
self.resolve_error
(ty.span, fmt!("use of undeclared type name `%s`",
self.idents_to_str(path.idents)));
}
@ -4253,7 +4258,7 @@ impl Resolver {
self.record_def(pattern.id, def);
}
FoundStructOrEnumVariant(_) => {
self.session.span_err(pattern.span,
self.resolve_error(pattern.span,
fmt!("declaration of `%s` \
shadows an enum \
variant or unit-like \
@ -4273,7 +4278,7 @@ impl Resolver {
self.record_def(pattern.id, def);
}
FoundConst(_) => {
self.session.span_err(pattern.span,
self.resolve_error(pattern.span,
"only refutable patterns \
allowed here");
}
@ -4327,7 +4332,7 @@ impl Resolver {
// Then this is a duplicate variable
// in the same disjunct, which is an
// error
self.session.span_err(pattern.span,
self.resolve_error(pattern.span,
fmt!("Identifier `%s` is bound more \
than once in the same pattern",
path_to_str(path, self.session
@ -4367,14 +4372,14 @@ impl Resolver {
self.record_def(pattern.id, def);
}
Some(_) => {
self.session.span_err(
self.resolve_error(
path.span,
fmt!("`%s` is not an enum variant or constant",
self.session.str_of(
*path.idents.last())));
}
None => {
self.session.span_err(path.span,
self.resolve_error(path.span,
"unresolved enum variant");
}
}
@ -4395,14 +4400,14 @@ impl Resolver {
self.record_def(pattern.id, def);
}
Some(_) => {
self.session.span_err(
self.resolve_error(
path.span,
fmt!("`%s` is not an enum variant, struct or const",
self.session.str_of(
*path.idents.last())));
}
None => {
self.session.span_err(path.span,
self.resolve_error(path.span,
"unresolved enum variant, \
struct or const");
}
@ -4441,7 +4446,7 @@ impl Resolver {
result => {
debug!("(resolving pattern) didn't find struct \
def: %?", result);
self.session.span_err(
self.resolve_error(
path.span,
fmt!("`%s` does not name a structure",
self.idents_to_str(path.idents)));
@ -4661,7 +4666,7 @@ impl Resolver {
path.span,
PathPublicOnlySearch) {
Failed => {
self.session.span_err(path.span,
self.resolve_error(path.span,
fmt!("use of undeclared module `%s`",
self.idents_to_str(
module_path_idents)));
@ -4729,7 +4734,7 @@ impl Resolver {
path.span,
PathPublicOrPrivateSearch) {
Failed => {
self.session.span_err(path.span,
self.resolve_error(path.span,
fmt!("use of undeclared module `::%s`",
self.idents_to_str(
module_path_idents)));
@ -4855,6 +4860,19 @@ impl Resolver {
}
}
fn with_no_errors<T>(@mut self, f: &fn() -> T) -> T {
self.emit_errors = false;
let rs = f();
self.emit_errors = true;
rs
}
fn resolve_error(@mut self, span: span, s: &str) {
if self.emit_errors {
self.session.span_err(span, s);
}
}
pub fn find_best_match_for_name(@mut self,
name: &str,
max_distance: uint)
@ -4954,7 +4972,7 @@ impl Resolver {
// out here.
match def {
def_method(*) => {
self.session.span_err(expr.span,
self.resolve_error(expr.span,
"first-class methods \
are not supported");
self.session.span_note(expr.span,
@ -4971,7 +4989,7 @@ impl Resolver {
let wrong_name = self.idents_to_str(
path.idents);
if self.name_exists_in_scope_struct(wrong_name) {
self.session.span_err(expr.span,
self.resolve_error(expr.span,
fmt!("unresolved name `%s`. \
Did you mean `self.%s`?",
wrong_name,
@ -4980,12 +4998,13 @@ impl Resolver {
else {
// Be helpful if the name refers to a struct
// (The pattern matching def_tys where the id is in self.structs
// matches on regular structs while excluding tuple- and
// enum-like structs, which wouldn't result in this error.)
match self.resolve_path(expr.id, path, TypeNS, false, visitor) {
// matches on regular structs while excluding tuple- and enum-like
// structs, which wouldn't result in this error.)
match self.with_no_errors(||
self.resolve_path(expr.id, path, TypeNS, false, visitor)) {
Some(def_ty(struct_id))
if self.structs.contains(&struct_id) => {
self.session.span_err(expr.span,
self.resolve_error(expr.span,
fmt!("`%s` is a structure name, but this expression \
uses it like a function name", wrong_name));
@ -4998,13 +5017,13 @@ impl Resolver {
// of stupid suggestions
match self.find_best_match_for_name(wrong_name, 5) {
Some(m) => {
self.session.span_err(expr.span,
self.resolve_error(expr.span,
fmt!("unresolved name `%s`. \
Did you mean `%s`?",
wrong_name, m));
}
None => {
self.session.span_err(expr.span,
self.resolve_error(expr.span,
fmt!("unresolved name `%s`.",
wrong_name));
}
@ -5041,7 +5060,7 @@ impl Resolver {
result => {
debug!("(resolving expression) didn't find struct \
def: %?", result);
self.session.span_err(
self.resolve_error(
path.span,
fmt!("`%s` does not name a structure",
self.idents_to_str(path.idents)));
@ -5070,7 +5089,7 @@ impl Resolver {
match self.search_ribs(self.label_ribs, label, expr.span,
DontAllowCapturingSelf) {
None =>
self.session.span_err(expr.span,
self.resolve_error(expr.span,
fmt!("use of undeclared label \
`%s`",
self.session.str_of(
@ -5089,7 +5108,7 @@ impl Resolver {
expr_self => {
match self.resolve_self_value_in_local_ribs(expr.span) {
None => {
self.session.span_err(expr.span,
self.resolve_error(expr.span,
"`self` is not allowed in \
this context")
}
@ -5320,7 +5339,7 @@ impl Resolver {
match pat_binding_mode {
bind_infer => {}
bind_by_ref(*) => {
self.session.span_err(
self.resolve_error(
pat.span,
fmt!("cannot use `ref` binding mode with %s",
descr));