-
Notifications
You must be signed in to change notification settings - Fork 278
Fix the reorganize_definitions refactoring #1364
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
base: master
Are you sure you want to change the base?
Changes from all commits
a64c3c6
513b76d
b00d291
f148365
ec90a40
5ed7076
5c65c97
0970fd0
68f670b
9804b07
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
use rustc_ast::mut_visit::{self, MutVisitor}; | ||
use rustc_ast::ptr::P; | ||
use rustc_ast::*; | ||
use rustc_parse::new_parser_from_file; | ||
use rustc_session::parse::ParseSess; | ||
use rustc_span::source_map::SourceMap; | ||
use rustc_span::FileName; | ||
use smallvec::SmallVec; | ||
use std::path::PathBuf; | ||
|
||
struct LoadModules<'a> { | ||
parse_sess: &'a ParseSess, | ||
source_map: &'a SourceMap, | ||
dir_path: PathBuf, | ||
} | ||
|
||
impl<'a> MutVisitor for LoadModules<'a> { | ||
fn flat_map_item(&mut self, mut i: P<Item>) -> SmallVec<[P<Item>; 1]> { | ||
let Item { | ||
ref mut attrs, | ||
ref span, | ||
ref ident, | ||
kind: ItemKind::Mod(_, ref mut mod_kind), | ||
.. | ||
} = *i else { | ||
return mut_visit::noop_flat_map_item(i, self); | ||
}; | ||
|
||
match mod_kind { | ||
ModKind::Loaded(_items, Inline::Yes, _spans) => { | ||
// TODO: handle #[path="..."] | ||
} | ||
|
||
ModKind::Loaded(_items, Inline::No, _spans) => { | ||
// We shouldn't be seeing any loaded modules at this point | ||
panic!("unexpected loaded module: {i:?}"); | ||
} | ||
Comment on lines
+30
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The conjunction of these two comments is confusing: are inline modules not considered loaded modules (such that we might see them)? Or is it that specifically we shouldn't see any non-inline loaded modules yet? |
||
|
||
ModKind::Unloaded => { | ||
// Look for dir_path/foo.rs, then try dir_path/foo/mod.rs | ||
let mut mod_file_path = self.dir_path.join(ident.as_str()).with_extension("rs"); | ||
if !self.source_map.file_exists(&mod_file_path) { | ||
mod_file_path = self.dir_path.join(ident.as_str()).with_file_name("mod.rs"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't do |
||
} | ||
if !self.source_map.file_exists(&mod_file_path) { | ||
panic!("unable to load module file {mod_file_path:?}"); | ||
} | ||
|
||
let mut parser = | ||
new_parser_from_file(&self.parse_sess, &mod_file_path, Some(*span)); | ||
let (mut inner_attrs, items, inner_span) = parser | ||
.parse_mod(&token::Eof) | ||
.expect("failed to parse {mod_file_path:?}"); | ||
|
||
attrs.append(&mut inner_attrs); | ||
*mod_kind = ModKind::Loaded(items, Inline::No, inner_span); | ||
} | ||
} | ||
|
||
self.dir_path.push(ident.as_str()); | ||
let res = mut_visit::noop_flat_map_item(i, self); | ||
self.dir_path.pop(); | ||
|
||
res | ||
} | ||
} | ||
|
||
pub fn load_modules(krate: &mut Crate, parse_sess: &ParseSess, source_map: &SourceMap) { | ||
let file_path = match source_map.span_to_filename(krate.spans.inner_span) { | ||
FileName::Real(name) => name | ||
.into_local_path() | ||
.expect("attempting to resolve a file path in an external file"), | ||
other => panic!("crate is not from a real file: {other:?}"), | ||
}; | ||
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned(); | ||
|
||
let mut lm = LoadModules { | ||
parse_sess, | ||
source_map, | ||
dir_path, | ||
}; | ||
|
||
lm.visit_crate(krate); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
use rustc_ast::visit::{self, AssocCtxt, Visitor}; | ||
use rustc_ast::*; | ||
use rustc_span::Span; | ||
use std::collections::HashMap; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
pub enum SpanNodeKind { | ||
Crate, | ||
Block, | ||
Pat, | ||
PatField, | ||
Stmt, | ||
Local, | ||
Arm, | ||
ExprField, | ||
Expr, | ||
AssocConstraint, | ||
Ty, | ||
Param, | ||
Variant, | ||
FieldDef, | ||
Item, | ||
ForeignItem, | ||
AssocItem, | ||
// We need a separate kind for ExprKind::Path because | ||
// the rustc macro expander emits `*foo` expressions where | ||
// both the outer and inner expressions have the same span | ||
// We disambiguate by assigning (span, Expr) to the outer one, | ||
// and (span, PathExpr) to the inner expression. | ||
PathExpr, | ||
Comment on lines
+25
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this similar to the |
||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
pub struct NodeSpan { | ||
pub span: Span, | ||
pub kind: SpanNodeKind, | ||
} | ||
|
||
impl NodeSpan { | ||
pub fn new(span: Span, kind: SpanNodeKind) -> Self { | ||
Self { span, kind } | ||
} | ||
} | ||
|
||
#[derive(Default, Clone)] | ||
pub struct AstSpanMaps { | ||
pub node_id_to_span_map: HashMap<NodeId, NodeSpan>, | ||
pub span_to_node_id_map: HashMap<NodeSpan, NodeId>, | ||
Comment on lines
+47
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we use |
||
} | ||
|
||
impl AstSpanMaps { | ||
pub fn new(krate: &Crate) -> Self { | ||
let mut mapper = AstSpanMapper::default(); | ||
mapper.visit_crate(krate); | ||
mapper.0 | ||
} | ||
} | ||
|
||
#[derive(Default, Clone)] | ||
struct AstSpanMapper(AstSpanMaps); | ||
|
||
impl AstSpanMapper { | ||
fn insert_mapping(&mut self, id: NodeId, span: Span, kind: SpanNodeKind) { | ||
if id == DUMMY_NODE_ID || span.is_dummy() { | ||
return; | ||
} | ||
|
||
let ns = NodeSpan { span, kind }; | ||
let old_ns = self.0.node_id_to_span_map.insert(id, ns); | ||
let _old_id = self.0.span_to_node_id_map.insert(ns, id); | ||
|
||
assert!( | ||
old_ns.is_none(), | ||
"id {id:?} already has span {old_ns:?} != {ns:?}" | ||
); | ||
// Some spans can show up in multiple nodes | ||
//assert!(old_id.is_none(), "span {ns:?} already has id {old_id:?} != {id:?}"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this redundant? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh this is |
||
} | ||
} | ||
|
||
impl Visitor<'_> for AstSpanMapper { | ||
fn visit_crate(&mut self, krate: &Crate) { | ||
self.insert_mapping(krate.id, krate.spans.inner_span, SpanNodeKind::Crate); | ||
visit::walk_crate(self, krate); | ||
} | ||
|
||
fn visit_block(&mut self, block: &Block) { | ||
self.insert_mapping(block.id, block.span, SpanNodeKind::Block); | ||
visit::walk_block(self, block); | ||
} | ||
|
||
fn visit_pat(&mut self, pat: &Pat) { | ||
self.insert_mapping(pat.id, pat.span, SpanNodeKind::Pat); | ||
visit::walk_pat(self, pat); | ||
} | ||
|
||
fn visit_pat_field(&mut self, pf: &PatField) { | ||
self.insert_mapping(pf.id, pf.span, SpanNodeKind::PatField); | ||
visit::walk_pat_field(self, pf); | ||
} | ||
|
||
fn visit_stmt(&mut self, stmt: &Stmt) { | ||
self.insert_mapping(stmt.id, stmt.span, SpanNodeKind::Stmt); | ||
visit::walk_stmt(self, stmt); | ||
} | ||
|
||
fn visit_local(&mut self, local: &Local) { | ||
self.insert_mapping(local.id, local.span, SpanNodeKind::Local); | ||
visit::walk_local(self, local); | ||
} | ||
|
||
fn visit_arm(&mut self, arm: &Arm) { | ||
self.insert_mapping(arm.id, arm.span, SpanNodeKind::Arm); | ||
visit::walk_arm(self, arm); | ||
} | ||
|
||
fn visit_expr_field(&mut self, ef: &ExprField) { | ||
self.insert_mapping(ef.id, ef.span, SpanNodeKind::ExprField); | ||
visit::walk_expr_field(self, ef); | ||
} | ||
|
||
fn visit_expr(&mut self, expr: &Expr) { | ||
if matches!(expr.kind, ExprKind::Path(..)) { | ||
self.insert_mapping(expr.id, expr.span, SpanNodeKind::PathExpr); | ||
} else { | ||
self.insert_mapping(expr.id, expr.span, SpanNodeKind::Expr); | ||
} | ||
visit::walk_expr(self, expr); | ||
} | ||
|
||
fn visit_assoc_constraint(&mut self, ac: &AssocConstraint) { | ||
self.insert_mapping(ac.id, ac.span, SpanNodeKind::AssocConstraint); | ||
visit::walk_assoc_constraint(self, ac); | ||
} | ||
|
||
fn visit_ty(&mut self, ty: &Ty) { | ||
self.insert_mapping(ty.id, ty.span, SpanNodeKind::Ty); | ||
visit::walk_ty(self, ty); | ||
} | ||
|
||
fn visit_param(&mut self, param: &Param) { | ||
self.insert_mapping(param.id, param.span, SpanNodeKind::Param); | ||
visit::walk_param(self, param); | ||
} | ||
|
||
fn visit_variant(&mut self, var: &Variant) { | ||
self.insert_mapping(var.id, var.span, SpanNodeKind::Variant); | ||
visit::walk_variant(self, var); | ||
} | ||
|
||
fn visit_field_def(&mut self, fd: &FieldDef) { | ||
self.insert_mapping(fd.id, fd.span, SpanNodeKind::FieldDef); | ||
visit::walk_field_def(self, fd); | ||
} | ||
|
||
fn visit_item(&mut self, i: &Item) { | ||
self.insert_mapping(i.id, i.span, SpanNodeKind::Item); | ||
visit::walk_item(self, i); | ||
} | ||
|
||
fn visit_foreign_item(&mut self, i: &ForeignItem) { | ||
self.insert_mapping(i.id, i.span, SpanNodeKind::ForeignItem); | ||
visit::walk_foreign_item(self, i); | ||
} | ||
|
||
fn visit_assoc_item(&mut self, i: &AssocItem, ctxt: AssocCtxt) { | ||
self.insert_mapping(i.id, i.span, SpanNodeKind::AssocItem); | ||
visit::walk_assoc_item(self, i, ctxt); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.