From 5d7afbe575ad95fee8dee74a961a9a335e16d996 Mon Sep 17 00:00:00 2001 From: gamazeps Date: Sun, 9 Nov 2014 17:31:37 +0100 Subject: [PATCH 1/3] Generalize MacExpr / MacPat / MacItems Closes #17637 --- src/libsyntax/ext/base.rs | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 5401da8cd053b..0361a71c2e9a6 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -164,6 +164,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 From f008bfdc5ca0a566441f8f57a03597d7eba361a1 Mon Sep 17 00:00:00 2001 From: Dan Simon Date: Sun, 16 Nov 2014 19:09:02 -0500 Subject: [PATCH 2/3] creating convenience types for make_def, make_stmt in MacResult Unifying with MacroDefiner --- src/libsyntax/ext/base.rs | 55 ++++++++++++++++++++++++++++- src/libsyntax/ext/tt/macro_rules.rs | 18 +++------- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 0c7a3cf4a6ce3..16a9f0a472529 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -202,7 +202,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> } @@ -219,6 +219,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. pub struct DummyResult { 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 } From 5d1b223e1ee4f236e272193994129fe1d3b2b165 Mon Sep 17 00:00:00 2001 From: oliver Date: Sat, 6 Dec 2014 13:47:24 +0100 Subject: [PATCH 3/3] librustc: hint close matches on accessing nonexisting fields --- src/librustc_typeck/check/mod.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a0f3f2734d976..13689853b237c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3501,11 +3501,38 @@ fn check_expr_with_unifier<'a, 'tcx>(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, @@ -3601,6 +3628,8 @@ fn check_expr_with_unifier<'a, 'tcx>(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)) => {