diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index bbc33826f3551..0ebe8d5f33f54 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3345,11 +3345,38 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
actual)
},
expr_t, None);
+ suggest_field_names(expr_t, field, tcx);
}
fcx.write_error(expr.id);
}
+ fn suggest_field_names<'tcx>(t : ty::t,
+ field : &ast::SpannedIdent,
+ tcx : &ty::ctxt<'tcx>) {
+ let id = ty::ty_to_def_id(t).unwrap();
+ let ident = token::get_ident(field.node);
+ let name = ident.get();
+ // only find fits with at least one matching letter
+ let mut best_dist = name.len();
+ let mut best = vec![];
+ let fields = ty::lookup_struct_fields(tcx, id);
+ for elem in fields.iter() {
+ let n = elem.name.as_str();
+ let dist = n.lev_distance(name);
+ if dist < best_dist {
+ best = vec![n];
+ best_dist = dist;
+ } else if dist == best_dist {
+ best.push(n);
+ }
+ }
+ for n in best.iter() {
+ tcx.sess.span_help(field.span,
+ format!("did you mean `{}`?", n).as_slice());
+ }
+ }
+
// Check tuple index expressions
fn check_tup_field(fcx: &FnCtxt,
expr: &ast::Expr,
@@ -3445,6 +3472,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
},
struct_ty,
None);
+ // FIXME: suggest_field_names also displays already defined fields
+ suggest_field_names(struct_ty, &field.ident, tcx);
error_happened = true;
}
Some((_, true)) => {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 3947a602809e6..b0d06e95aec7a 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -166,6 +166,47 @@ pub trait MacResult {
}
}
+/// Single type implementing MacResult with Option fields for all the types
+/// MacResult can return, and a Default impl that fills in None.
+pub struct MacGeneral {
+ expr: Option
>,
+ pat: Option
>,
+ items: Option>>,
+ methods: Option>>,
+ def: Option
+}
+impl MacGeneral {
+ pub fn new(expr: Option>,
+ pat: Option
>,
+ items: Option>>,
+ methods: Option>>,
+ def: Option)
+ -> Box {
+ box MacGeneral { expr: expr, pat: pat, items: items,
+ methods: methods, def: def } as Box
+ }
+ pub fn Default() -> Box {
+ box MacGeneral { expr: None, pat: None, items: None
+ methods: None, def: None} as Box
+ }
+}
+impl MacResult for MacGeneral {
+ fn make_expr(self: Box) -> Option> {
+ self.expr
+ }
+ fn make_pat(self: Box) -> Option> {
+ self.pat
+ }
+ fn make_items(self: Box) -> Option>> {
+ self.items
+ }
+ fn make_methods(self: Box) -> Option>> {
+ self.methods
+ }
+ fn make_def(&mut self) -> Option {
+ self.def
+ }
+}
/// A convenience type for macros that return a single expression.
pub struct MacExpr {
e: P
@@ -204,7 +245,7 @@ impl MacResult for MacPat {
Some(self.p)
}
}
-/// A type for macros that return multiple items.
+/// A convenience type for macros that return multiple items.
pub struct MacItems {
items: SmallVector>
}
@@ -221,6 +262,59 @@ impl MacResult for MacItems {
}
}
+/// A convenience type for macros that return a single statement
+pub struct MacStmt {
+ stmt: P,
+}
+
+impl MacStmt {
+ pub fn new(stmt: P) -> MacStmt {
+ MacStmt{ stmt: stmt }
+ }
+}
+
+impl MacResult for MacStmt {
+ fn make_stmt(self: Box) -> Option> {
+ Some(self.stmt)
+ }
+}
+
+
+/// A convenience type for macros that return a macro def
+pub struct MacDef {
+ def: Option
+}
+
+impl MacDef {
+ pub fn new(def: MacroDef) -> MacDef {
+ MacDef{ def: Some(def) }
+ }
+}
+
+impl MacResult for MacDef {
+ fn make_def(&mut self) -> Option {
+ Some(self.def.take().expect("empty MacDef"))
+ }
+}
+
+/// A convenience type for macros that return methods
+pub struct MacMethods {
+ methods: SmallVector>
+}
+
+impl MacMethods {
+ pub fn new(methods: SmallVector
>) -> MacMethods {
+ MacMethods{ methods: methods }
+ }
+}
+
+impl MacResult for MacMethods {
+ fn make_methods(self: Box) -> Option>> {
+ Some(self.methods)
+ }
+}
+
+
/// Fill-in macro expansion result, to allow compilation to continue
/// after hitting errors.
#[deriving(Copy)]
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 92c68b7a9c724..967747a3ac2b9 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -11,7 +11,7 @@
use ast::{Ident, TtDelimited, TtSequence, TtToken};
use ast;
use codemap::{Span, DUMMY_SP};
-use ext::base::{ExtCtxt, MacResult, MacroDef};
+use ext::base::{ExtCtxt, MacDef, MacResult, MacroDef};
use ext::base::{NormalTT, TTMacroExpander};
use ext::tt::macro_parser::{Success, Error, Failure};
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
@@ -129,14 +129,6 @@ impl TTMacroExpander for MacroRulesMacroExpander {
}
}
-struct MacroRulesDefiner {
- def: Option
-}
-impl MacResult for MacroRulesDefiner {
- fn make_def(&mut self) -> Option {
- Some(self.def.take().expect("empty MacroRulesDefiner"))
- }
-}
/// Given `lhses` and `rhses`, this is the new macro we create
fn generic_extension<'cx>(cx: &'cx ExtCtxt,
@@ -279,10 +271,10 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
rhses: rhses,
};
- box MacroRulesDefiner {
- def: Some(MacroDef {
+ box MacDef::new(
+ MacroDef {
name: token::get_ident(name).to_string(),
ext: NormalTT(exp, Some(sp))
- })
- } as Box
+ }
+ ) as Box
}