Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/body.rs')
| -rw-r--r-- | crates/hir-def/src/body.rs | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 867bee95be..433a956ff9 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -18,6 +18,7 @@ use smallvec::SmallVec; use span::{Edition, MacroFileId}; use syntax::{ast, AstPtr, SyntaxNodePtr}; use triomphe::Arc; +use tt::TextRange; use crate::{ db::DefDatabase, @@ -143,15 +144,7 @@ pub struct BodySourceMap { pub types: TypesSourceMap, - // FIXME: Make this a sane struct. - template_map: Option< - Box<( - // format_args! - FxHashMap<ExprId, (HygieneId, Vec<(syntax::TextRange, Name)>)>, - // asm! - FxHashMap<ExprId, Vec<Vec<(syntax::TextRange, usize)>>>, - )>, - >, + template_map: Option<Box<FormatTemplate>>, expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, MacroFileId>, @@ -160,6 +153,20 @@ pub struct BodySourceMap { diagnostics: Vec<BodyDiagnostic>, } +#[derive(Default, Debug, Eq, PartialEq)] +struct FormatTemplate { + /// A map from `format_args!()` expressions to their captures. + format_args_to_captures: FxHashMap<ExprId, (HygieneId, Vec<(syntax::TextRange, Name)>)>, + /// A map from `asm!()` expressions to their captures. + asm_to_captures: FxHashMap<ExprId, Vec<Vec<(syntax::TextRange, usize)>>>, + /// A map from desugared expressions of implicit captures to their source. + /// + /// The value stored for each capture is its template literal and offset inside it. The template literal + /// is from the `format_args[_nl]!()` macro and so needs to be mapped up once to go to the user-written + /// template. + implicit_capture_to_source: FxHashMap<ExprId, InFile<(AstPtr<ast::Expr>, TextRange)>>, +} + #[derive(Debug, Eq, PartialEq)] pub enum BodyDiagnostic { InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions }, @@ -798,18 +805,29 @@ impl BodySourceMap { node: InFile<&ast::FormatArgsExpr>, ) -> Option<(HygieneId, &[(syntax::TextRange, Name)])> { let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>); - let (hygiene, names) = - self.template_map.as_ref()?.0.get(&self.expr_map.get(&src)?.as_expr()?)?; + let (hygiene, names) = self + .template_map + .as_ref()? + .format_args_to_captures + .get(&self.expr_map.get(&src)?.as_expr()?)?; Some((*hygiene, &**names)) } + pub fn format_args_implicit_capture( + &self, + capture_expr: ExprId, + ) -> Option<InFile<(AstPtr<ast::Expr>, TextRange)>> { + self.template_map.as_ref()?.implicit_capture_to_source.get(&capture_expr).copied() + } + pub fn asm_template_args( &self, node: InFile<&ast::AsmExpr>, ) -> Option<(ExprId, &[Vec<(syntax::TextRange, usize)>])> { let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>); let expr = self.expr_map.get(&src)?.as_expr()?; - Some(expr).zip(self.template_map.as_ref()?.1.get(&expr).map(std::ops::Deref::deref)) + Some(expr) + .zip(self.template_map.as_ref()?.asm_to_captures.get(&expr).map(std::ops::Deref::deref)) } /// Get a reference to the body source map's diagnostics. @@ -835,8 +853,14 @@ impl BodySourceMap { types, } = self; if let Some(template_map) = template_map { - template_map.0.shrink_to_fit(); - template_map.1.shrink_to_fit(); + let FormatTemplate { + format_args_to_captures, + asm_to_captures, + implicit_capture_to_source, + } = &mut **template_map; + format_args_to_captures.shrink_to_fit(); + asm_to_captures.shrink_to_fit(); + implicit_capture_to_source.shrink_to_fit(); } expr_map.shrink_to_fit(); expr_map_back.shrink_to_fit(); |