Skip to content

Look up macro names as well when suggesting replacements for function resolve errors #29968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use middle::dependency_format;
use session::search_paths::PathKind;
use util::nodemap::{NodeMap, FnvHashMap};

use syntax::ast::{NodeId, NodeIdAssigner};
use syntax::ast::{NodeId, NodeIdAssigner, Name};
use syntax::codemap::Span;
use syntax::diagnostic::{self, Emitter};
use syntax::diagnostics;
Expand All @@ -30,6 +30,7 @@ use rustc_back::target::Target;

use std::path::{Path, PathBuf};
use std::cell::{Cell, RefCell};
use std::collections::HashSet;
use std::env;

pub mod config;
Expand Down Expand Up @@ -74,6 +75,10 @@ pub struct Session {
/// didn't already find one, and this tracks what was injected.
pub injected_allocator: Cell<Option<ast::CrateNum>>,

/// Names of all bang-style macros and syntax extensions
/// available in this crate
pub available_macros: RefCell<HashSet<Name>>,

next_node_id: Cell<ast::NodeId>,
}

Expand Down Expand Up @@ -468,6 +473,7 @@ pub fn build_session_(sopts: config::Options,
can_print_warnings: can_print_warnings,
next_node_id: Cell::new(1),
injected_allocator: Cell::new(None),
available_macros: RefCell::new(HashSet::new()),
};

sess
Expand Down
13 changes: 7 additions & 6 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,15 +553,16 @@ pub fn phase_2_configure_and_expand(sess: &Session,
recursion_limit: sess.recursion_limit.get(),
trace_mac: sess.opts.debugging_opts.trace_macros,
};
let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,
cfg,
macros,
syntax_exts,
&mut feature_gated_cfgs,
krate);
let (ret, macro_names) = syntax::ext::expand::expand_crate(&sess.parse_sess,
cfg,
macros,
syntax_exts,
&mut feature_gated_cfgs,
krate);
if cfg!(windows) {
env::set_var("PATH", &_old_path);
}
*sess.available_macros.borrow_mut() = macro_names;
ret
});

Expand Down
26 changes: 21 additions & 5 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ macro_rules! execute_callback {
)
}

enum SuggestionType {
Macro(String),
Function(String),
NotFound,
}

pub enum ResolutionError<'a> {
/// error E0401: can't use type parameters from outer function
TypeParametersFromOuterFunction,
Expand Down Expand Up @@ -3616,10 +3622,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
NoSuggestion
}

fn find_best_match_for_name(&mut self, name: &str) -> Option<String> {
fn find_best_match_for_name(&mut self, name: &str) -> SuggestionType {
let mut maybes: Vec<token::InternedString> = Vec::new();
let mut values: Vec<usize> = Vec::new();

if let Some(macro_name) = self.session.available_macros
.borrow().iter().find(|n| n.as_str() == name) {
return SuggestionType::Macro(format!("{}!", macro_name));
}

for rib in self.value_ribs.iter().rev() {
for (&k, _) in &rib.bindings {
maybes.push(k.as_str());
Expand All @@ -3643,10 +3654,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {

if !values.is_empty() && values[smallest] <= max_distance && name != &maybes[smallest][..] {

Some(maybes[smallest].to_string())
SuggestionType::Function(maybes[smallest].to_string())

} else {
None
SuggestionType::NotFound
}
}

Expand Down Expand Up @@ -3758,8 +3769,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
NoSuggestion => {
// limit search to 5 to reduce the number
// of stupid suggestions
self.find_best_match_for_name(&path_name)
.map_or("".to_string(), |x| format!("`{}`", x))
match self.find_best_match_for_name(&path_name) {
SuggestionType::Macro(s) => {
format!("the macro `{}`", s)
}
SuggestionType::Function(s) => format!("`{}`", s),
SuggestionType::NotFound => "".to_string(),
}
}
Field => format!("`self.{}`", path_name),
Method |
Expand Down
12 changes: 9 additions & 3 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use util::small_vector::SmallVector;
use ext::mtwt;
use fold::Folder;

use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use std::default::Default;

Expand Down Expand Up @@ -856,7 +856,10 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
///
/// This environment maps Names to SyntaxExtensions.
pub struct SyntaxEnv {
chain: Vec<MapChainFrame> ,
chain: Vec<MapChainFrame>,
/// All bang-style macro/extension names
/// encountered so far; to be used for diagnostics in resolve
pub names: HashSet<Name>,
}

// impl question: how to implement it? Initially, the
Expand All @@ -876,7 +879,7 @@ struct MapChainFrame {

impl SyntaxEnv {
fn new() -> SyntaxEnv {
let mut map = SyntaxEnv { chain: Vec::new() };
let mut map = SyntaxEnv { chain: Vec::new() , names: HashSet::new()};
map.push_frame();
map
}
Expand Down Expand Up @@ -913,6 +916,9 @@ impl SyntaxEnv {
}

pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
if let NormalTT(..) = v {
self.names.insert(k);
}
self.find_escape_frame().map.insert(k, Rc::new(v));
}

Expand Down
34 changes: 19 additions & 15 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
use ast::{Local, Ident, Mac_};
use ast::{Local, Ident, Mac_, Name};
use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac};
use ast::{StmtExpr, StmtSemi};
use ast::TokenTree;
Expand All @@ -32,6 +32,8 @@ use visit;
use visit::Visitor;
use std_inject;

use std::collections::HashSet;


pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
let expr_span = e.span;
Expand Down Expand Up @@ -1261,7 +1263,7 @@ pub fn expand_crate<'feat>(parse_sess: &parse::ParseSess,
imported_macros: Vec<ast::MacroDef>,
user_exts: Vec<NamedSyntaxExtension>,
feature_gated_cfgs: &mut Vec<GatedCfg>,
c: Crate) -> Crate {
c: Crate) -> (Crate, HashSet<Name>) {
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg,
feature_gated_cfgs);
if std_inject::no_core(&c) {
Expand All @@ -1271,21 +1273,23 @@ pub fn expand_crate<'feat>(parse_sess: &parse::ParseSess,
} else {
cx.crate_root = Some("std");
}
let ret = {
let mut expander = MacroExpander::new(&mut cx);

let mut expander = MacroExpander::new(&mut cx);

for def in imported_macros {
expander.cx.insert_macro(def);
}
for def in imported_macros {
expander.cx.insert_macro(def);
}

for (name, extension) in user_exts {
expander.cx.syntax_env.insert(name, extension);
}
for (name, extension) in user_exts {
expander.cx.syntax_env.insert(name, extension);
}

let mut ret = expander.fold_crate(c);
ret.exported_macros = expander.cx.exported_macros.clone();
parse_sess.span_diagnostic.handler().abort_if_errors();
return ret;
let mut ret = expander.fold_crate(c);
ret.exported_macros = expander.cx.exported_macros.clone();
parse_sess.span_diagnostic.handler().abort_if_errors();
ret
};
return (ret, cx.syntax_env.names);
}

// HYGIENIC CONTEXT EXTENSION:
Expand Down Expand Up @@ -1480,7 +1484,7 @@ mod tests {
let ps = parse::ParseSess::new();
let crate_ast = panictry!(string_to_parser(&ps, crate_str).parse_crate_mod());
// the cfg argument actually does matter, here...
expand_crate(&ps,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast)
expand_crate(&ps,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast).0
}

// find the pat_ident paths in a crate
Expand Down
13 changes: 13 additions & 0 deletions src/test/compile-fail/resolve-hint-macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
assert(true); //~ERROR unresolved name `assert`. Did you mean the macro `assert!`?
}