Skip to content

internal: Build source map for hir_def::TypeRefs #18074

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 7 commits into from
Oct 28, 2024
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
17 changes: 17 additions & 0 deletions crates/hir-def/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::{
nameres::DefMap,
path::{ModPath, Path},
src::HasSource,
type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap},
BlockId, DefWithBodyId, HasModule, Lookup,
};

Expand Down Expand Up @@ -69,6 +70,7 @@ pub struct Body {
pub self_param: Option<BindingId>,
/// The `ExprId` of the actual body expression.
pub body_expr: ExprId,
pub types: TypesMap,
/// Block expressions in this body that may contain inner items.
block_scopes: Vec<BlockId>,

Expand Down Expand Up @@ -139,6 +141,8 @@ pub struct BodySourceMap {
field_map_back: FxHashMap<ExprId, FieldSource>,
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,

types: TypesSourceMap,

// FIXME: Make this a sane struct.
template_map: Option<
Box<(
Expand Down Expand Up @@ -304,6 +308,7 @@ impl Body {
binding_hygiene,
expr_hygiene,
pat_hygiene,
types,
} = self;
block_scopes.shrink_to_fit();
exprs.shrink_to_fit();
Expand All @@ -314,6 +319,7 @@ impl Body {
binding_hygiene.shrink_to_fit();
expr_hygiene.shrink_to_fit();
pat_hygiene.shrink_to_fit();
types.shrink_to_fit();
}

pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
Expand Down Expand Up @@ -542,6 +548,7 @@ impl Default for Body {
binding_hygiene: Default::default(),
expr_hygiene: Default::default(),
pat_hygiene: Default::default(),
types: Default::default(),
}
}
}
Expand Down Expand Up @@ -578,6 +585,14 @@ impl Index<BindingId> for Body {
}
}

impl Index<TypeRefId> for Body {
type Output = TypeRef;

fn index(&self, b: TypeRefId) -> &TypeRef {
&self.types[b]
}
}

// FIXME: Change `node_` prefix to something more reasonable.
// Perhaps `expr_syntax` and `expr_id`?
impl BodySourceMap {
Expand Down Expand Up @@ -691,6 +706,7 @@ impl BodySourceMap {
template_map,
diagnostics,
binding_definitions,
types,
} = self;
if let Some(template_map) = template_map {
template_map.0.shrink_to_fit();
Expand All @@ -707,5 +723,6 @@ impl BodySourceMap {
expansions.shrink_to_fit();
diagnostics.shrink_to_fit();
binding_definitions.shrink_to_fit();
types.shrink_to_fit();
}
}
64 changes: 26 additions & 38 deletions crates/hir-def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use hir_expand::{
span_map::{ExpansionSpanMap, SpanMap},
InFile, MacroDefId,
};
use intern::{sym, Interned, Symbol};
use intern::{sym, Symbol};
use rustc_hash::FxHashMap;
use span::AstIdMap;
use stdx::never;
Expand Down Expand Up @@ -274,8 +274,8 @@ impl ExprCollector<'_> {
(self.body, self.source_map)
}

fn ctx(&self) -> LowerCtx<'_> {
self.expander.ctx(self.db)
fn ctx(&mut self) -> LowerCtx<'_> {
self.expander.ctx(self.db, &mut self.body.types, &mut self.source_map.types)
}

fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
Expand Down Expand Up @@ -436,7 +436,7 @@ impl ExprCollector<'_> {
}
ast::Expr::PathExpr(e) => {
let (path, hygiene) = self
.collect_expr_path(&e)
.collect_expr_path(e)
.map(|(path, hygiene)| (Expr::Path(path), hygiene))
.unwrap_or((Expr::Missing, HygieneId::ROOT));
let expr_id = self.alloc_expr(path, syntax_ptr);
Expand Down Expand Up @@ -486,8 +486,7 @@ impl ExprCollector<'_> {
self.alloc_expr(Expr::Yeet { expr }, syntax_ptr)
}
ast::Expr::RecordExpr(e) => {
let path =
e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
let path = e.path().and_then(|path| self.parse_path(path)).map(Box::new);
let record_lit = if let Some(nfl) = e.record_expr_field_list() {
let fields = nfl
.fields()
Expand Down Expand Up @@ -534,7 +533,7 @@ impl ExprCollector<'_> {
ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e),
ast::Expr::CastExpr(e) => {
let expr = self.collect_expr_opt(e.expr());
let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty());
self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
}
ast::Expr::RefExpr(e) => {
Expand Down Expand Up @@ -573,16 +572,13 @@ impl ExprCollector<'_> {
arg_types.reserve_exact(num_params);
for param in pl.params() {
let pat = this.collect_pat_top(param.pat());
let type_ref =
param.ty().map(|it| Interned::new(TypeRef::from_ast(&this.ctx(), it)));
let type_ref = param.ty().map(|it| TypeRef::from_ast(&this.ctx(), it));
args.push(pat);
arg_types.push(type_ref);
}
}
let ret_type = e
.ret_type()
.and_then(|r| r.ty())
.map(|it| Interned::new(TypeRef::from_ast(&this.ctx(), it)));
let ret_type =
e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&this.ctx(), it));

let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine);
let prev_try_block_label = this.current_try_block_label.take();
Expand Down Expand Up @@ -709,23 +705,23 @@ impl ExprCollector<'_> {
ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr),
ast::Expr::OffsetOfExpr(e) => {
let container = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
let container = TypeRef::from_ast_opt(&self.ctx(), e.ty());
let fields = e.fields().map(|it| it.as_name()).collect();
self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr)
}
ast::Expr::FormatArgsExpr(f) => self.collect_format_args(f, syntax_ptr),
})
}

fn collect_expr_path(&mut self, e: &ast::PathExpr) -> Option<(Path, HygieneId)> {
fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
self.expander.parse_path(self.db, path, &mut self.body.types, &mut self.source_map.types)
}

fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> {
e.path().and_then(|path| {
let path = self.expander.parse_path(self.db, path)?;
let Path::Normal { type_anchor, mod_path, generic_args } = &path else {
panic!("path parsing produced a non-normal path");
};
let path = self.parse_path(path)?;
// Need to enable `mod_path.len() < 1` for `self`.
let may_be_variable =
type_anchor.is_none() && mod_path.len() <= 1 && generic_args.is_none();
let may_be_variable = matches!(&path, Path::BarePath(mod_path) if mod_path.len() <= 1);
let hygiene = if may_be_variable {
self.hygiene_id_for(e.syntax().text_range().start())
} else {
Expand Down Expand Up @@ -790,17 +786,14 @@ impl ExprCollector<'_> {
}
ast::Expr::CallExpr(e) => {
let path = collect_path(self, e.expr()?)?;
let path = path
.path()
.and_then(|path| self.expander.parse_path(self.db, path))
.map(Box::new);
let path = path.path().and_then(|path| self.parse_path(path)).map(Box::new);
let (ellipsis, args) = collect_tuple(self, e.arg_list()?.args());
self.alloc_pat_from_expr(Pat::TupleStruct { path, args, ellipsis }, syntax_ptr)
}
ast::Expr::PathExpr(e) => {
let (path, hygiene) = self
.collect_expr_path(e)
.map(|(path, hygiene)| (Pat::Path(Box::new(path)), hygiene))
.collect_expr_path(e.clone())
.map(|(path, hygiene)| (Pat::Path(path), hygiene))
.unwrap_or((Pat::Missing, HygieneId::ROOT));
let pat_id = self.alloc_pat_from_expr(path, syntax_ptr);
if !hygiene.is_root() {
Expand All @@ -819,8 +812,7 @@ impl ExprCollector<'_> {
id
}
ast::Expr::RecordExpr(e) => {
let path =
e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
let path = e.path().and_then(|path| self.parse_path(path)).map(Box::new);
let record_field_list = e.record_expr_field_list()?;
let ellipsis = record_field_list.dotdot_token().is_some();
// FIXME: Report an error here if `record_field_list.spread().is_some()`.
Expand Down Expand Up @@ -1063,7 +1055,7 @@ impl ExprCollector<'_> {
syntax_ptr,
);
let none_arm = MatchArm {
pat: self.alloc_pat_desugared(Pat::Path(Box::new(option_none))),
pat: self.alloc_pat_desugared(Pat::Path(option_none)),
guard: None,
expr: self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr),
};
Expand Down Expand Up @@ -1325,8 +1317,7 @@ impl ExprCollector<'_> {
return;
}
let pat = self.collect_pat_top(stmt.pat());
let type_ref =
stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
let else_branch = stmt
.let_else()
Expand Down Expand Up @@ -1552,8 +1543,7 @@ impl ExprCollector<'_> {
return pat;
}
ast::Pat::TupleStructPat(p) => {
let path =
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
let path = p.path().and_then(|path| self.parse_path(path)).map(Box::new);
let (args, ellipsis) = self.collect_tuple_pat(
p.fields(),
comma_follows_token(p.l_paren_token()),
Expand All @@ -1567,8 +1557,7 @@ impl ExprCollector<'_> {
Pat::Ref { pat, mutability }
}
ast::Pat::PathPat(p) => {
let path =
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
let path = p.path().and_then(|path| self.parse_path(path));
path.map(Pat::Path).unwrap_or(Pat::Missing)
}
ast::Pat::OrPat(p) => 'b: {
Expand Down Expand Up @@ -1611,8 +1600,7 @@ impl ExprCollector<'_> {
}
ast::Pat::WildcardPat(_) => Pat::Wild,
ast::Pat::RecordPat(p) => {
let path =
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
let path = p.path().and_then(|path| self.parse_path(path)).map(Box::new);
let record_pat_field_list =
&p.record_pat_field_list().expect("every struct should have a field list");
let args = record_pat_field_list
Expand Down
4 changes: 1 addition & 3 deletions crates/hir-def/src/body/lower/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,7 @@ impl ExprCollector<'_> {
AsmOperand::Const(self.collect_expr_opt(c.expr()))
}
ast::AsmOperand::AsmSym(s) => {
let Some(path) =
s.path().and_then(|p| self.expander.parse_path(self.db, p))
else {
let Some(path) = s.path().and_then(|p| self.parse_path(p)) else {
continue;
};
AsmOperand::Sym(path)
Expand Down
27 changes: 13 additions & 14 deletions crates/hir-def/src/body/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::{
Statement,
},
pretty::{print_generic_args, print_path, print_type_ref},
type_ref::TypeRef,
};

use super::*;
Expand Down Expand Up @@ -69,20 +68,20 @@ pub(super) fn print_body_hir(
};
if let DefWithBodyId::FunctionId(it) = owner {
p.buf.push('(');
let function_data = &db.function_data(it);
let function_data = db.function_data(it);
let (mut params, ret_type) = (function_data.params.iter(), &function_data.ret_type);
if let Some(self_param) = body.self_param {
p.print_binding(self_param);
p.buf.push_str(": ");
if let Some(ty) = params.next() {
p.print_type_ref(ty);
p.print_type_ref(*ty, &function_data.types_map);
p.buf.push_str(", ");
}
}
body.params.iter().zip(params).for_each(|(&param, ty)| {
p.print_pat(param);
p.buf.push_str(": ");
p.print_type_ref(ty);
p.print_type_ref(*ty, &function_data.types_map);
p.buf.push_str(", ");
});
// remove the last ", " in param list
Expand All @@ -92,7 +91,7 @@ pub(super) fn print_body_hir(
p.buf.push(')');
// return type
p.buf.push_str(" -> ");
p.print_type_ref(ret_type);
p.print_type_ref(*ret_type, &function_data.types_map);
p.buf.push(' ');
}
p.print_expr(body.body_expr);
Expand Down Expand Up @@ -242,7 +241,7 @@ impl Printer<'_> {
Expr::InlineAsm(_) => w!(self, "builtin#asm(_)"),
Expr::OffsetOf(offset_of) => {
w!(self, "builtin#offset_of(");
self.print_type_ref(&offset_of.container);
self.print_type_ref(offset_of.container, &self.body.types);
let edition = self.edition;
w!(
self,
Expand Down Expand Up @@ -296,7 +295,7 @@ impl Printer<'_> {
if let Some(args) = generic_args {
w!(self, "::<");
let edition = self.edition;
print_generic_args(self.db, args, self, edition).unwrap();
print_generic_args(self.db, args, &self.body.types, self, edition).unwrap();
w!(self, ">");
}
w!(self, "(");
Expand Down Expand Up @@ -405,7 +404,7 @@ impl Printer<'_> {
Expr::Cast { expr, type_ref } => {
self.print_expr(*expr);
w!(self, " as ");
self.print_type_ref(type_ref);
self.print_type_ref(*type_ref, &self.body.types);
}
Expr::Ref { expr, rawness, mutability } => {
w!(self, "&");
Expand Down Expand Up @@ -493,13 +492,13 @@ impl Printer<'_> {
self.print_pat(*pat);
if let Some(ty) = ty {
w!(self, ": ");
self.print_type_ref(ty);
self.print_type_ref(*ty, &self.body.types);
}
}
w!(self, "|");
if let Some(ret_ty) = ret_type {
w!(self, " -> ");
self.print_type_ref(ret_ty);
self.print_type_ref(*ret_ty, &self.body.types);
}
self.whitespace();
self.print_expr(*body);
Expand Down Expand Up @@ -734,7 +733,7 @@ impl Printer<'_> {
self.print_pat(*pat);
if let Some(ty) = type_ref {
w!(self, ": ");
self.print_type_ref(ty);
self.print_type_ref(*ty, &self.body.types);
}
if let Some(init) = initializer {
w!(self, " = ");
Expand Down Expand Up @@ -792,14 +791,14 @@ impl Printer<'_> {
}
}

fn print_type_ref(&mut self, ty: &TypeRef) {
fn print_type_ref(&mut self, ty: TypeRefId, map: &TypesMap) {
let edition = self.edition;
print_type_ref(self.db, ty, self, edition).unwrap();
print_type_ref(self.db, ty, map, self, edition).unwrap();
}

fn print_path(&mut self, path: &Path) {
let edition = self.edition;
print_path(self.db, path, self, edition).unwrap();
print_path(self.db, path, &self.body.types, self, edition).unwrap();
}

fn print_binding(&mut self, id: BindingId) {
Expand Down
Loading