1
Fork 0

rustc: remove hir::fold.

This commit is contained in:
Eduard Burtescu 2016-09-01 10:21:12 +03:00
parent ed593bed88
commit 02c4155d2c
6 changed files with 143 additions and 1261 deletions

File diff suppressed because it is too large Load diff

View file

@ -67,7 +67,6 @@ macro_rules! hir_vec {
pub mod check_attr;
pub mod def;
pub mod def_id;
pub mod fold;
pub mod intravisit;
pub mod lowering;
pub mod map;

View file

@ -40,11 +40,10 @@ use rustc_back::slice;
use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
use syntax::codemap::Spanned;
use syntax_pos::{Span, DUMMY_SP};
use rustc::hir::fold::{Folder, noop_fold_pat};
use rustc::hir::print::pat_to_string;
use syntax::ptr::P;
use syntax::util::move_map::MoveMap;
use rustc::util::common::ErrorReported;
use rustc::util::nodemap::FnvHashMap;
pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
id: DUMMY_NODE_ID,
@ -182,7 +181,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
}
}
let mut static_inliner = StaticInliner::new(cx.tcx, None);
let mut static_inliner = StaticInliner::new(cx.tcx);
let inlined_arms = arms.iter().map(|arm| {
(arm.pats.iter().map(|pat| {
static_inliner.fold_pat((*pat).clone())
@ -467,53 +466,30 @@ fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
})
}
pub struct StaticInliner<'a, 'tcx: 'a> {
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub failed: bool,
pub renaming_map: Option<&'a mut FnvHashMap<(NodeId, Span), NodeId>>,
struct StaticInliner<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
failed: bool
}
impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
pub fn new<'b>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
renaming_map: Option<&'b mut FnvHashMap<(NodeId, Span), NodeId>>)
-> StaticInliner<'b, 'tcx> {
pub fn new<'b>(tcx: TyCtxt<'b, 'tcx, 'tcx>) -> StaticInliner<'b, 'tcx> {
StaticInliner {
tcx: tcx,
failed: false,
renaming_map: renaming_map
failed: false
}
}
}
struct RenamingRecorder<'map> {
substituted_node_id: NodeId,
origin_span: Span,
renaming_map: &'map mut FnvHashMap<(NodeId, Span), NodeId>
}
impl<'v, 'map> Visitor<'v> for RenamingRecorder<'map> {
fn visit_id(&mut self, node_id: NodeId) {
let key = (node_id, self.origin_span);
self.renaming_map.insert(key, self.substituted_node_id);
}
}
impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
return match pat.node {
match pat.node {
PatKind::Path(..) => {
match self.tcx.expect_def(pat.id) {
Def::AssociatedConst(did) | Def::Const(did) => {
let substs = Some(self.tcx.node_id_item_substs(pat.id).substs);
if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) {
match const_expr_to_pat(self.tcx, const_expr, pat.id, pat.span) {
Ok(new_pat) => {
if let Some(ref mut map) = self.renaming_map {
// Record any renamings we do here
record_renamings(const_expr, &pat, map);
}
new_pat
}
Ok(new_pat) => return new_pat,
Err(def_id) => {
self.failed = true;
self.tcx.sess.span_err(
@ -521,33 +497,62 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
&format!("constants of the type `{}` \
cannot be used in patterns",
self.tcx.item_path_str(def_id)));
pat
}
}
} else {
self.failed = true;
span_err!(self.tcx.sess, pat.span, E0158,
"statics cannot be referenced in patterns");
pat
}
}
_ => noop_fold_pat(pat, self)
_ => {}
}
}
_ => noop_fold_pat(pat, self)
};
fn record_renamings(const_expr: &hir::Expr,
substituted_pat: &hir::Pat,
renaming_map: &mut FnvHashMap<(NodeId, Span), NodeId>) {
let mut renaming_recorder = RenamingRecorder {
substituted_node_id: substituted_pat.id,
origin_span: substituted_pat.span,
renaming_map: renaming_map,
};
renaming_recorder.visit_expr(const_expr);
_ => {}
}
pat.map(|Pat { id, node, span }| {
let node = match node {
PatKind::Binding(binding_mode, pth1, sub) => {
PatKind::Binding(binding_mode, pth1, sub.map(|x| self.fold_pat(x)))
}
PatKind::TupleStruct(pth, pats, ddpos) => {
PatKind::TupleStruct(pth, pats.move_map(|x| self.fold_pat(x)), ddpos)
}
PatKind::Struct(pth, fields, etc) => {
let fs = fields.move_map(|f| {
Spanned {
span: f.span,
node: hir::FieldPat {
name: f.node.name,
pat: self.fold_pat(f.node.pat),
is_shorthand: f.node.is_shorthand,
},
}
});
PatKind::Struct(pth, fs, etc)
}
PatKind::Tuple(elts, ddpos) => {
PatKind::Tuple(elts.move_map(|x| self.fold_pat(x)), ddpos)
}
PatKind::Box(inner) => PatKind::Box(self.fold_pat(inner)),
PatKind::Ref(inner, mutbl) => PatKind::Ref(self.fold_pat(inner), mutbl),
PatKind::Vec(before, slice, after) => {
PatKind::Vec(before.move_map(|x| self.fold_pat(x)),
slice.map(|x| self.fold_pat(x)),
after.move_map(|x| self.fold_pat(x)))
}
PatKind::Wild |
PatKind::Lit(_) |
PatKind::Range(..) |
PatKind::Path(..) => node
};
Pat {
id: id,
node: node,
span: span
}
})
}
}
@ -1047,7 +1052,7 @@ pub fn specialize<'a, 'b, 'tcx>(
fn check_local(cx: &mut MatchCheckCtxt, loc: &hir::Local) {
intravisit::walk_local(cx, loc);
let pat = StaticInliner::new(cx.tcx, None).fold_pat(loc.pat.clone());
let pat = StaticInliner::new(cx.tcx).fold_pat(loc.pat.clone());
check_irrefutable(cx, &pat, false);
// Check legality of move bindings and `@` patterns.

View file

@ -38,7 +38,6 @@ use rustc::middle::privacy::AccessLevels;
use rustc::middle::resolve_lifetime::DefRegion::*;
use rustc::hir::def::Def;
use rustc::hir::def_id::{self, DefId, DefIndex, CRATE_DEF_INDEX};
use rustc::hir::fold::Folder;
use rustc::hir::print as pprust;
use rustc::ty::subst::Substs;
use rustc::ty::{self, AdtKind};
@ -774,7 +773,20 @@ impl Lifetime {
}
impl Clean<Lifetime> for hir::Lifetime {
fn clean(&self, _: &DocContext) -> Lifetime {
fn clean(&self, cx: &DocContext) -> Lifetime {
if let Some(tcx) = cx.tcx_opt() {
let def = tcx.named_region_map.defs.get(&self.id).cloned();
match def {
Some(DefEarlyBoundRegion(_, node_id)) |
Some(DefLateBoundRegion(_, node_id)) |
Some(DefFreeRegion(_, node_id)) => {
if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
return lt;
}
}
_ => {}
}
}
Lifetime(self.name.to_string())
}
}
@ -1629,42 +1641,6 @@ impl From<ast::FloatTy> for PrimitiveType {
}
}
// Poor man's type parameter substitution at HIR level.
// Used to replace private type aliases in public signatures with their aliased types.
struct SubstAlias<'a, 'tcx: 'a> {
tcx: &'a ty::TyCtxt<'a, 'tcx, 'tcx>,
// Table type parameter definition -> substituted type
ty_substs: FnvHashMap<Def, hir::Ty>,
// Table node id of lifetime parameter definition -> substituted lifetime
lt_substs: FnvHashMap<ast::NodeId, hir::Lifetime>,
}
impl<'a, 'tcx: 'a, 'b: 'tcx> Folder for SubstAlias<'a, 'tcx> {
fn fold_ty(&mut self, ty: P<hir::Ty>) -> P<hir::Ty> {
if let hir::TyPath(..) = ty.node {
let def = self.tcx.expect_def(ty.id);
if let Some(new_ty) = self.ty_substs.get(&def).cloned() {
return P(new_ty);
}
}
hir::fold::noop_fold_ty(ty, self)
}
fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime {
let def = self.tcx.named_region_map.defs.get(&lt.id).cloned();
match def {
Some(DefEarlyBoundRegion(_, node_id)) |
Some(DefLateBoundRegion(_, node_id)) |
Some(DefFreeRegion(_, node_id)) => {
if let Some(lt) = self.lt_substs.get(&node_id).cloned() {
return lt;
}
}
_ => {}
}
hir::fold::noop_fold_lifetime(lt, self)
}
}
impl Clean<Type> for hir::Ty {
fn clean(&self, cx: &DocContext) -> Type {
use rustc::hir::*;
@ -1696,43 +1672,47 @@ impl Clean<Type> for hir::Ty {
},
TyTup(ref tys) => Tuple(tys.clean(cx)),
TyPath(None, ref path) => {
if let Some(tcx) = cx.tcx_opt() {
// Substitute private type aliases
let def = tcx.expect_def(self.id);
let tcx_and_def = cx.tcx_opt().map(|tcx| (tcx, tcx.expect_def(self.id)));
if let Some((_, def)) = tcx_and_def {
if let Some(new_ty) = cx.ty_substs.borrow().get(&def).cloned() {
return new_ty;
}
}
let tcx_and_alias = tcx_and_def.and_then(|(tcx, def)| {
if let Def::TyAlias(def_id) = def {
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
// Substitute private type aliases
tcx.map.as_local_node_id(def_id).and_then(|node_id| {
if !cx.access_levels.borrow().is_exported(def_id) {
let item = tcx.map.expect_item(node_id);
if let hir::ItemTy(ref ty, ref generics) = item.node {
let provided_params = &path.segments.last().unwrap().parameters;
let mut ty_substs = FnvHashMap();
let mut lt_substs = FnvHashMap();
for (i, ty_param) in generics.ty_params.iter().enumerate() {
let ty_param_def = tcx.expect_def(ty_param.id);
if let Some(ty) = provided_params.types().get(i).cloned()
.cloned() {
ty_substs.insert(ty_param_def, ty.unwrap());
} else if let Some(default) = ty_param.default.clone() {
ty_substs.insert(ty_param_def, default.unwrap());
}
}
for (i, lt_param) in generics.lifetimes.iter().enumerate() {
if let Some(lt) = provided_params.lifetimes().get(i)
.cloned()
.cloned() {
lt_substs.insert(lt_param.lifetime.id, lt);
}
}
let mut subst_alias = SubstAlias {
tcx: &tcx,
ty_substs: ty_substs,
lt_substs: lt_substs
};
return subst_alias.fold_ty(ty.clone()).clean(cx);
}
Some((tcx, &tcx.map.expect_item(node_id).node))
} else {
None
}
})
} else {
None
}
});
if let Some((tcx, &hir::ItemTy(ref ty, ref generics))) = tcx_and_alias {
let provided_params = &path.segments.last().unwrap().parameters;
let mut ty_substs = FnvHashMap();
let mut lt_substs = FnvHashMap();
for (i, ty_param) in generics.ty_params.iter().enumerate() {
let ty_param_def = tcx.expect_def(ty_param.id);
if let Some(ty) = provided_params.types().get(i).cloned()
.cloned() {
ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
} else if let Some(default) = ty_param.default.clone() {
ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
}
}
for (i, lt_param) in generics.lifetimes.iter().enumerate() {
if let Some(lt) = provided_params.lifetimes().get(i).cloned()
.cloned() {
lt_substs.insert(lt_param.lifetime.id, lt.clean(cx));
}
}
return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx));
}
resolve_type(cx, path.clean(cx), self.id)
}

View file

@ -14,6 +14,7 @@ use rustc_driver::{driver, target_features, abort_on_err};
use rustc::dep_graph::DepGraph;
use rustc::session::{self, config};
use rustc::hir::def_id::{CrateNum, DefId};
use rustc::hir::def::Def;
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt};
use rustc::hir::map as hir_map;
@ -23,12 +24,13 @@ use rustc_trans::back::link;
use rustc_resolve as resolve;
use rustc_metadata::cstore::CStore;
use syntax::codemap;
use syntax::{ast, codemap};
use syntax::feature_gate::UnstableFeatures;
use errors;
use errors::emitter::ColorConfig;
use std::cell::{RefCell, Cell};
use std::mem;
use std::rc::Rc;
use visit_ast::RustdocVisitor;
@ -63,6 +65,14 @@ pub struct DocContext<'a, 'tcx: 'a> {
pub renderinfo: RefCell<RenderInfo>,
/// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
pub external_traits: RefCell<FnvHashMap<DefId, clean::Trait>>,
// The current set of type and lifetime substitutions,
// for expanding type aliases at the HIR level:
/// Table type parameter definition -> substituted type
pub ty_substs: RefCell<FnvHashMap<Def, clean::Type>>,
/// Table node id of lifetime parameter definition -> substituted lifetime
pub lt_substs: RefCell<FnvHashMap<ast::NodeId, clean::Lifetime>>,
}
impl<'b, 'tcx> DocContext<'b, 'tcx> {
@ -84,6 +94,22 @@ impl<'b, 'tcx> DocContext<'b, 'tcx> {
let tcx_opt = self.tcx_opt();
tcx_opt.expect("tcx not present")
}
/// Call the closure with the given parameters set as
/// the substitutions for a type alias' RHS.
pub fn enter_alias<F, R>(&self,
ty_substs: FnvHashMap<Def, clean::Type>,
lt_substs: FnvHashMap<ast::NodeId, clean::Lifetime>,
f: F) -> R
where F: FnOnce() -> R {
let (old_tys, old_lts) =
(mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs),
mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs));
let r = f();
*self.ty_substs.borrow_mut() = old_tys;
*self.lt_substs.borrow_mut() = old_lts;
r
}
}
pub trait DocAccessLevels {
@ -179,12 +205,14 @@ pub fn run_core(search_paths: SearchPaths,
map: &tcx.map,
maybe_typed: Typed(tcx),
input: input,
populated_crate_impls: RefCell::new(FnvHashSet()),
populated_crate_impls: Default::default(),
deref_trait_did: Cell::new(None),
deref_mut_trait_did: Cell::new(None),
access_levels: RefCell::new(access_levels),
external_traits: RefCell::new(FnvHashMap()),
renderinfo: RefCell::new(Default::default()),
external_traits: Default::default(),
renderinfo: Default::default(),
ty_substs: Default::default(),
lt_substs: Default::default(),
};
debug!("crate: {:?}", ctxt.map.krate());

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cell::{RefCell, Cell};
use std::cell::Cell;
use std::env;
use std::ffi::OsString;
use std::io::prelude::*;
@ -28,7 +28,6 @@ use rustc::session::{self, config};
use rustc::session::config::{get_unstable_features_setting, OutputType,
OutputTypes, Externs};
use rustc::session::search_paths::{SearchPaths, PathKind};
use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
use rustc_back::dynamic_lib::DynamicLibrary;
use rustc_back::tempdir::TempDir;
use rustc_driver::{driver, Compilation};
@ -107,12 +106,14 @@ pub fn run(input: &str,
map: &map,
maybe_typed: core::NotTyped(&sess),
input: input,
external_traits: RefCell::new(FnvHashMap()),
populated_crate_impls: RefCell::new(FnvHashSet()),
external_traits: Default::default(),
populated_crate_impls: Default::default(),
deref_trait_did: Cell::new(None),
deref_mut_trait_did: Cell::new(None),
access_levels: Default::default(),
renderinfo: Default::default(),
ty_substs: Default::default(),
lt_substs: Default::default(),
};
let mut v = RustdocVisitor::new(&ctx);