use std::{mem, ops::Index, sync::Arc};
-use arena::{map::ArenaMap, Arena};
use base_db::CrateId;
use cfg::CfgOptions;
use drop_bomb::DropBomb;
ast_id_map::AstIdMap, diagnostics::DiagnosticSink, hygiene::Hygiene, AstId, ExpandResult,
HirFileId, InFile, MacroDefId,
};
+use la_arena::{Arena, ArenaMap};
+use profile::Count;
use rustc_hash::FxHashMap;
use syntax::{ast, AstNode, AstPtr};
use test_utils::mark;
use crate::{
attr::{Attrs, RawAttrs},
db::DefDatabase,
- expr::{Expr, ExprId, Pat, PatId},
+ expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
item_scope::BuiltinShadowMode,
item_scope::ItemScope,
- nameres::CrateDefMap,
+ nameres::DefMap,
path::{ModPath, Path},
src::HasSource,
AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
pub(crate) struct Expander {
cfg_expander: CfgExpander,
- crate_def_map: Arc<CrateDefMap>,
+ def_map: Arc<DefMap>,
current_file_id: HirFileId,
ast_id_map: Arc<AstIdMap>,
module: ModuleId,
module: ModuleId,
) -> Expander {
let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
- let crate_def_map = db.crate_def_map(module.krate);
+ let crate_def_map = module.def_map(db);
let ast_id_map = db.ast_id_map(current_file_id);
Expander {
cfg_expander,
- crate_def_map,
+ def_map: crate_def_map,
current_file_id,
ast_id_map,
module,
pub(crate) fn enter_expand<T: ast::AstNode>(
&mut self,
db: &dyn DefDatabase,
- local_scope: Option<&ItemScope>,
macro_call: ast::MacroCall,
) -> ExpandResult<Option<(Mark, T)>> {
if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT {
let macro_call = InFile::new(self.current_file_id, ¯o_call);
- let resolver = |path: ModPath| -> Option<MacroDefId> {
- if let Some(local_scope) = local_scope {
- if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) {
- return Some(def);
- }
- }
- self.resolve_path_as_macro(db, &path)
- };
+ let resolver =
+ |path: ModPath| -> Option<MacroDefId> { self.resolve_path_as_macro(db, &path) };
let mut err = None;
let call_id =
- macro_call.as_call_id_with_errors(db, self.crate_def_map.krate, resolver, &mut |e| {
+ macro_call.as_call_id_with_errors(db, self.def_map.krate(), resolver, &mut |e| {
err.get_or_insert(e);
});
let call_id = match call_id {
}
fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
- self.crate_def_map
+ self.def_map
.resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
.0
.take_macros()
pub struct Body {
pub exprs: Arena<Expr>,
pub pats: Arena<Pat>,
+ pub labels: Arena<Label>,
/// The patterns for the function's parameters. While the parameter types are
/// part of the function signature, the patterns are not (they don't change
/// the external type of the function).
/// The `ExprId` of the actual body expression.
pub body_expr: ExprId,
pub item_scope: ItemScope,
+ _c: Count<Self>,
}
pub type ExprPtr = AstPtr<ast::Expr>;
pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
pub type PatSource = InFile<PatPtr>;
+pub type LabelPtr = AstPtr<ast::Label>;
+pub type LabelSource = InFile<LabelPtr>;
/// An item body together with the mapping from syntax nodes to HIR expression
/// IDs. This is needed to go from e.g. a position in a file to the HIR
/// expression containing it; but for type inference etc., we want to operate on
expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>,
pat_map: FxHashMap<PatSource, PatId>,
pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
+ label_map: FxHashMap<LabelSource, LabelId>,
+ label_map_back: ArenaMap<LabelId, LabelSource>,
field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>,
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
}
}
+impl Index<LabelId> for Body {
+ type Output = Label;
+
+ fn index(&self, label: LabelId) -> &Label {
+ &self.labels[label]
+ }
+}
+
impl BodySourceMap {
pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
self.expr_map_back[expr].clone()
self.pat_map.get(&src).cloned()
}
+ pub fn label_syntax(&self, label: LabelId) -> LabelSource {
+ self.label_map_back[label].clone()
+ }
+
+ pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
+ let src = node.map(|it| AstPtr::new(it));
+ self.label_map.get(&src).cloned()
+ }
+
pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> {
self.field_map[&(expr, field)].clone()
}