Resolve paths generated in the ast->hir lowerer

This commit is contained in:
Jeffrey Seyfried 2016-05-02 23:26:18 +00:00
parent 983b4d3925
commit e5a0dd7c6e
3 changed files with 144 additions and 76 deletions

View File

@ -43,7 +43,8 @@
use hir;
use hir::map::Definitions;
use hir::map::definitions::DefPathData;
use hir::def_id::DefIndex;
use hir::def_id::{DefIndex, DefId};
use hir::def::{Def, DefMap, PathResolution};
use std::collections::BTreeMap;
use std::iter;
@ -63,19 +64,25 @@ pub struct LoweringContext<'a> {
crate_root: Option<&'static str>,
// Use to assign ids to hir nodes that do not directly correspond to an ast node
id_assigner: &'a NodeIdAssigner,
// We must keep the set of definitions up to date as we add nodes that
// weren't in the AST.
definitions: Option<&'a RefCell<Definitions>>,
// As we walk the AST we must keep track of the current 'parent' def id (in
// the form of a DefIndex) so that if we create a new node which introduces
// a definition, then we can properly create the def id.
parent_def: Cell<Option<DefIndex>>,
resolver: Option<RefCell<&'a mut Resolver>>,
}
pub trait Resolver {
fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def;
fn def_map(&mut self) -> &mut DefMap;
// We must keep the set of definitions up to date as we add nodes that weren't in the AST.
fn definitions(&mut self) -> &mut Definitions;
}
impl<'a, 'hir> LoweringContext<'a> {
pub fn new(id_assigner: &'a NodeIdAssigner,
c: Option<&Crate>,
defs: &'a RefCell<Definitions>)
resolver: &'a mut Resolver)
-> LoweringContext<'a> {
let crate_root = c.and_then(|c| {
if std_inject::no_core(c) {
@ -90,8 +97,8 @@ impl<'a, 'hir> LoweringContext<'a> {
LoweringContext {
crate_root: crate_root,
id_assigner: id_assigner,
definitions: Some(defs),
parent_def: Cell::new(None),
resolver: Some(RefCell::new(resolver)),
}
}
@ -101,8 +108,8 @@ impl<'a, 'hir> LoweringContext<'a> {
LoweringContext {
crate_root: None,
id_assigner: id_assigner,
definitions: None,
parent_def: Cell::new(None),
resolver: None,
}
}
@ -120,7 +127,7 @@ impl<'a, 'hir> LoweringContext<'a> {
}
fn with_parent_def<T, F: FnOnce() -> T>(&self, parent_id: NodeId, f: F) -> T {
if self.definitions.is_none() {
if self.resolver.is_none() {
// This should only be used for testing.
return f();
}
@ -134,8 +141,22 @@ impl<'a, 'hir> LoweringContext<'a> {
}
fn get_def(&self, id: NodeId) -> DefIndex {
let defs = self.definitions.unwrap().borrow();
defs.opt_def_index(id).unwrap()
let mut resolver = self.resolver.as_ref().unwrap().borrow_mut();
resolver.definitions().opt_def_index(id).unwrap()
}
fn record_def(&self, id: NodeId, def: Def) {
if let Some(ref resolver) = self.resolver {
resolver.borrow_mut().def_map().insert(id, PathResolution { base_def: def, depth: 0 });
}
}
fn resolve_generated_global_path(&self, path: &hir::Path, is_value: bool) -> Def {
if let Some(ref resolver) = self.resolver {
resolver.borrow_mut().resolve_generated_global_path(path, is_value)
} else {
Def::Err
}
}
}
@ -999,7 +1020,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
};
// let placer = <placer_expr> ;
let s1 = {
let (s1, placer_binding) = {
let placer_expr = signal_block_expr(lctx,
hir_vec![],
placer_expr,
@ -1010,15 +1031,15 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
};
// let mut place = Placer::make_place(placer);
let s2 = {
let placer = expr_ident(lctx, e.span, placer_ident, None);
let (s2, place_binding) = {
let placer = expr_ident(lctx, e.span, placer_ident, None, placer_binding);
let call = make_call(lctx, &make_place, hir_vec![placer]);
mk_stmt_let_mut(lctx, place_ident, call)
};
// let p_ptr = Place::pointer(&mut place);
let s3 = {
let agent = expr_ident(lctx, e.span, place_ident, None);
let (s3, p_ptr_binding) = {
let agent = expr_ident(lctx, e.span, place_ident, None, place_binding);
let args = hir_vec![expr_mut_addr_of(lctx, e.span, agent, None)];
let call = make_call(lctx, &place_pointer, args);
mk_stmt_let(lctx, p_ptr_ident, call)
@ -1044,14 +1065,14 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// InPlace::finalize(place)
// })
let expr = {
let ptr = expr_ident(lctx, e.span, p_ptr_ident, None);
let ptr = expr_ident(lctx, e.span, p_ptr_ident, None, p_ptr_binding);
let call_move_val_init =
hir::StmtSemi(
make_call(lctx, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
lctx.next_id());
let call_move_val_init = respan(e.span, call_move_val_init);
let place = expr_ident(lctx, e.span, place_ident, None);
let place = expr_ident(lctx, e.span, place_ident, None, place_binding);
let call = make_call(lctx, &inplace_finalize, hir_vec![place]);
signal_block_expr(lctx,
hir_vec![call_move_val_init],
@ -1489,6 +1510,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
arm(hir_vec![pat_none(lctx, e.span)], break_expr)
};
// `mut iter`
let iter_pat =
pat_ident_binding_mode(lctx, e.span, iter, hir::BindByValue(hir::MutMutable));
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
let next_path = {
@ -1496,7 +1521,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
path_global(e.span, strs)
};
let iter = expr_ident(lctx, e.span, iter, None);
let iter = expr_ident(lctx, e.span, iter, None, iter_pat.id);
let ref_mut_iter = expr_mut_addr_of(lctx, e.span, iter, None);
let next_path = expr_path(lctx, next_path, None);
let next_expr = expr_call(lctx,
@ -1520,13 +1545,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None });
// `mut iter => { ... }`
let iter_arm = {
let iter_pat = pat_ident_binding_mode(lctx,
e.span,
iter,
hir::BindByValue(hir::MutMutable));
arm(hir_vec![iter_pat], loop_expr)
};
let iter_arm = arm(hir_vec![iter_pat], loop_expr);
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
@ -1550,13 +1569,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// `{ let _result = ...; _result }`
// underscore prevents an unused_variables lint if the head diverges
let result_ident = lctx.str_to_ident("_result");
let let_stmt = stmt_let(lctx,
e.span,
false,
result_ident,
match_expr,
None);
let result = expr_ident(lctx, e.span, result_ident, None);
let (let_stmt, let_stmt_binding) =
stmt_let(lctx, e.span, false, result_ident, match_expr, None);
let result = expr_ident(lctx, e.span, result_ident, None, let_stmt_binding);
let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result));
// add the attributes to the outer returned expr node
return expr_block(lctx, block, e.attrs.clone());
@ -1583,7 +1599,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let ok_arm = {
let val_ident = lctx.str_to_ident("val");
let val_pat = pat_ident(lctx, e.span, val_ident);
let val_expr = expr_ident(lctx, e.span, val_ident, None);
let val_expr = expr_ident(lctx, e.span, val_ident, None, val_pat.id);
let ok_pat = pat_ok(lctx, e.span, val_pat);
arm(hir_vec![ok_pat], val_expr)
@ -1592,11 +1608,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// Err(err) => return Err(From::from(err))
let err_arm = {
let err_ident = lctx.str_to_ident("err");
let err_local = pat_ident(lctx, e.span, err_ident);
let from_expr = {
let path = std_path(lctx, &["convert", "From", "from"]);
let path = path_global(e.span, path);
let from = expr_path(lctx, path, None);
let err_expr = expr_ident(lctx, e.span, err_ident, None);
let err_expr = expr_ident(lctx, e.span, err_ident, None, err_local.id);
expr_call(lctx, e.span, from, hir_vec![err_expr], None)
};
@ -1606,8 +1623,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let err_ctor = expr_path(lctx, path, None);
expr_call(lctx, e.span, err_ctor, hir_vec![from_expr], None)
};
let err_pat = pat_err(lctx, e.span,
pat_ident(lctx, e.span, err_ident));
let err_pat = pat_err(lctx, e.span, err_local);
let ret_expr = expr(lctx, e.span,
hir::Expr_::ExprRet(Some(err_expr)), None);
@ -1747,8 +1763,13 @@ fn expr_call(lctx: &LoweringContext,
}
fn expr_ident(lctx: &LoweringContext, span: Span, id: hir::Ident,
attrs: ThinAttributes) -> P<hir::Expr> {
expr_path(lctx, path_ident(span, id), attrs)
attrs: ThinAttributes, binding: NodeId) -> P<hir::Expr> {
let expr = expr(lctx, span, hir::ExprPath(None, path_ident(span, id)), attrs);
if let Some(ref resolver) = lctx.resolver {
let def_id = resolver.borrow_mut().definitions().local_def_id(binding);
lctx.record_def(expr.id, Def::Local(def_id, binding));
}
expr
}
fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>,
@ -1758,7 +1779,10 @@ fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>,
fn expr_path(lctx: &LoweringContext, path: hir::Path,
attrs: ThinAttributes) -> P<hir::Expr> {
expr(lctx, path.span, hir::ExprPath(None, path), attrs)
let def = lctx.resolve_generated_global_path(&path, true);
let expr = expr(lctx, path.span, hir::ExprPath(None, path), attrs);
lctx.record_def(expr.id, def);
expr
}
fn expr_match(lctx: &LoweringContext,
@ -1787,7 +1811,11 @@ fn expr_struct(lctx: &LoweringContext,
fields: hir::HirVec<hir::Field>,
e: Option<P<hir::Expr>>,
attrs: ThinAttributes) -> P<hir::Expr> {
expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs)
let def = lctx.resolve_generated_global_path(&path, false);
let expr = expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs);
lctx.record_def(expr.id, def);
expr
}
fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_,
@ -1806,12 +1834,13 @@ fn stmt_let(lctx: &LoweringContext,
ident: hir::Ident,
ex: P<hir::Expr>,
attrs: ThinAttributes)
-> hir::Stmt {
-> (hir::Stmt, NodeId) {
let pat = if mutbl {
pat_ident_binding_mode(lctx, sp, ident, hir::BindByValue(hir::MutMutable))
} else {
pat_ident(lctx, sp, ident)
};
let pat_id = pat.id;
let local = P(hir::Local {
pat: pat,
ty: None,
@ -1821,7 +1850,7 @@ fn stmt_let(lctx: &LoweringContext,
attrs: attrs,
});
let decl = respan(sp, hir::DeclLocal(local));
respan(sp, hir::StmtDecl(P(decl), lctx.next_id()))
(respan(sp, hir::StmtDecl(P(decl), lctx.next_id())), pat_id)
}
fn block_expr(lctx: &LoweringContext, expr: P<hir::Expr>) -> P<hir::Block> {
@ -1871,12 +1900,15 @@ fn pat_enum(lctx: &LoweringContext,
path: hir::Path,
subpats: hir::HirVec<P<hir::Pat>>)
-> P<hir::Pat> {
let def = lctx.resolve_generated_global_path(&path, true);
let pt = if subpats.is_empty() {
hir::PatKind::Path(path)
} else {
hir::PatKind::TupleStruct(path, Some(subpats))
};
pat(lctx, span, pt)
let pat = pat(lctx, span, pt);
lctx.record_def(pat.id, def);
pat
}
fn pat_ident(lctx: &LoweringContext, span: Span, ident: hir::Ident) -> P<hir::Pat> {
@ -1897,11 +1929,13 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
let pat = pat(lctx, span, pat_ident);
if let Some(defs) = lctx.definitions {
let mut defs = defs.borrow_mut();
defs.create_def_with_parent(lctx.parent_def.get(),
pat.id,
DefPathData::Binding(ident.name));
if let Some(ref resolver) = lctx.resolver {
let def_index =
resolver.borrow_mut().definitions()
.create_def_with_parent(lctx.parent_def.get(),
pat.id,
DefPathData::Binding(ident.name));
lctx.record_def(pat.id, Def::Local(DefId::local(def_index), pat.id));
}
pat

View File

@ -154,12 +154,19 @@ pub fn compile_input(sess: &Session,
"early lint checks",
|| lint::check_ast_crate(sess, &expanded_crate));
let (analysis, resolutions) = {
resolve::with_resolver(sess, &defs.borrow(), control.make_glob_map, |mut resolver| {
let (analysis, resolutions, mut hir_forest) = {
let defs = &mut *defs.borrow_mut();
resolve::with_resolver(sess, defs, control.make_glob_map, |mut resolver| {
time(sess.time_passes(), "name resolution", || {
resolve::resolve_crate(&mut resolver, &expanded_crate);
});
// Lower ast -> hir.
let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || {
let lcx = LoweringContext::new(sess, Some(&expanded_crate), &mut resolver);
hir_map::Forest::new(lower_crate(&lcx, &expanded_crate), dep_graph)
});
(ty::CrateAnalysis {
export_map: resolver.export_map,
access_levels: AccessLevels::default(),
@ -171,17 +178,10 @@ pub fn compile_input(sess: &Session,
freevars: resolver.freevars,
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
})
}, hir_forest)
})
};
// Lower ast -> hir.
let lcx = LoweringContext::new(sess, Some(&expanded_crate), defs);
let hir_forest = &mut time(sess.time_passes(),
"lowering ast -> hir",
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
dep_graph));
// Discard MTWT tables that aren't required past lowering to HIR.
if !keep_mtwt_tables(sess) {
syntax::ext::mtwt::clear_tables();
@ -190,6 +190,7 @@ pub fn compile_input(sess: &Session,
let arenas = ty::CtxtArenas::new();
// Construct the HIR map
let hir_forest = &mut hir_forest;
let hir_map = time(sess.time_passes(),
"indexing hir",
move || hir_map::map_crate(hir_forest, defs));

View File

@ -44,7 +44,7 @@ use self::BareIdentifierPatternResolution::*;
use self::ParentLink::*;
use rustc::hir::map::Definitions;
use rustc::hir::{PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
use rustc::session::Session;
use rustc::lint;
use rustc::hir::def::*;
@ -962,7 +962,7 @@ impl PrimitiveTypeTable {
pub struct Resolver<'a> {
session: &'a Session,
definitions: &'a Definitions,
definitions: &'a mut Definitions,
graph_root: Module<'a>,
@ -1082,9 +1082,49 @@ impl<'a> ty::NodeIdTree for Resolver<'a> {
}
}
impl<'a> hir::lowering::Resolver for Resolver<'a> {
fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def {
let namespace = if is_value { ValueNS } else { TypeNS };
match self.resolve_crate_relative_path(path.span, &path.segments, namespace) {
Ok(binding) => binding.def().unwrap(),
Err(true) => Def::Err,
Err(false) => {
let path_name = &format!("{}", path);
let error =
ResolutionError::UnresolvedName(path_name, "", UnresolvedNameContext::Other);
resolve_error(self, path.span, error);
Def::Err
}
}
}
fn def_map(&mut self) -> &mut DefMap {
&mut self.def_map
}
fn definitions(&mut self) -> &mut Definitions {
self.definitions
}
}
trait Named {
fn name(&self) -> Name;
}
impl Named for ast::PathSegment {
fn name(&self) -> Name {
self.identifier.name
}
}
impl Named for hir::PathSegment {
fn name(&self) -> Name {
self.identifier.name
}
}
impl<'a> Resolver<'a> {
fn new(session: &'a Session,
definitions: &'a Definitions,
definitions: &'a mut Definitions,
make_glob_map: MakeGlobMap,
arenas: &'a ResolverArenas<'a>)
-> Resolver<'a> {
@ -2721,19 +2761,12 @@ impl<'a> Resolver<'a> {
/// Invariant: This must be called only during main resolution, not during
/// import resolution.
fn resolve_crate_relative_path(&mut self,
span: Span,
segments: &[ast::PathSegment],
namespace: Namespace)
-> Result<&'a NameBinding<'a>,
bool /* true if an error was reported */> {
let module_path = segments.split_last()
.unwrap()
.1
.iter()
.map(|ps| ps.identifier.name)
.collect::<Vec<_>>();
fn resolve_crate_relative_path<T>(&mut self, span: Span, segments: &[T], namespace: Namespace)
-> Result<&'a NameBinding<'a>,
bool /* true if an error was reported */>
where T: Named,
{
let module_path = segments.split_last().unwrap().1.iter().map(T::name).collect::<Vec<_>>();
let root_module = self.graph_root;
let containing_module;
@ -2762,7 +2795,7 @@ impl<'a> Resolver<'a> {
}
}
let name = segments.last().unwrap().identifier.name;
let name = segments.last().unwrap().name();
let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
result.success().map(|binding| {
self.check_privacy(name, binding, span);
@ -3588,7 +3621,7 @@ pub fn resolve_crate<'a, 'b>(resolver: &'b mut Resolver<'a>, krate: &'b Crate) {
}
pub fn with_resolver<'a, T, F>(session: &'a Session,
definitions: &'a Definitions,
definitions: &'a mut Definitions,
make_glob_map: MakeGlobMap,
f: F) -> T
where F: for<'b> FnOnce(Resolver<'b>) -> T,