diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 334177751e..73c3f421aa 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -59,6 +59,27 @@ impl HygieneId { } } +pub type ExprPtr = AstPtr; +pub type ExprSource = InFile; + +pub type PatPtr = AstPtr; +pub type PatSource = InFile; + +pub type LabelPtr = AstPtr; +pub type LabelSource = InFile; + +pub type FieldPtr = AstPtr; +pub type FieldSource = InFile; + +pub type PatFieldPtr = AstPtr>; +pub type PatFieldSource = InFile; + +pub type ExprOrPatPtr = AstPtr>; +pub type ExprOrPatSource = InFile; + +pub type SelfParamPtr = AstPtr; +pub type MacroCallPtr = AstPtr; + /// The body of an item (function, const etc.). #[derive(Debug, Eq, PartialEq)] pub struct Body { @@ -112,6 +133,73 @@ pub struct BodyCollector { ident_hygiene: FxHashMap, } +/// 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 +/// a structure that is agnostic to the actual positions of expressions in the +/// file, so that we don't recompute types whenever some whitespace is typed. +/// +/// One complication here is that, due to macro expansion, a single `Body` might +/// be spread across several files. So, for each ExprId and PatId, we record +/// both the HirFileId and the position inside the file. However, we only store +/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle +/// this properly for macros. +#[derive(Default, Debug, Eq, PartialEq)] +pub struct BodySourceMap { + // AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map + // to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected). + expr_map: FxHashMap, + expr_map_back: ArenaMap, + + pat_map: FxHashMap, + pat_map_back: ArenaMap, + + label_map: FxHashMap, + label_map_back: ArenaMap, + + self_param: Option>, + binding_definitions: FxHashMap>, + + /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). + /// Instead, we use id of expression (`92`) to identify the field. + field_map_back: FxHashMap, + pat_field_map_back: FxHashMap, + + pub types: TypesSourceMap, + + template_map: Option>, + + expansions: FxHashMap, MacroFileId>, + + /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in + /// the source map (since they're just as volatile). + diagnostics: Vec, +} + +#[derive(Default, Debug, Eq, PartialEq)] +struct FormatTemplate { + /// A map from `format_args!()` expressions to their captures. + format_args_to_captures: FxHashMap)>, + /// A map from `asm!()` expressions to their captures. + asm_to_captures: FxHashMap>>, + /// 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>, +} + +#[derive(Debug, Eq, PartialEq)] +pub enum BodyDiagnostic { + InactiveCode { node: InFile, cfg: CfgExpr, opts: CfgOptions }, + MacroError { node: InFile, err: ExpandError }, + UnresolvedMacroCall { node: InFile, path: ModPath }, + UnreachableLabel { node: InFile>, name: Name }, + AwaitOutsideOfAsync { node: InFile>, location: String }, + UndeclaredLabel { node: InFile>, name: Name }, +} + impl BodyCollector { fn finish( self, @@ -156,91 +244,6 @@ impl BodyCollector { } } -pub type ExprPtr = AstPtr; -pub type ExprSource = InFile; - -pub type PatPtr = AstPtr; -pub type PatSource = InFile; - -pub type LabelPtr = AstPtr; -pub type LabelSource = InFile; - -pub type FieldPtr = AstPtr; -pub type FieldSource = InFile; - -pub type PatFieldPtr = AstPtr>; -pub type PatFieldSource = InFile; - -pub type ExprOrPatPtr = AstPtr>; -pub type ExprOrPatSource = InFile; - -/// 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 -/// a structure that is agnostic to the actual positions of expressions in the -/// file, so that we don't recompute types whenever some whitespace is typed. -/// -/// One complication here is that, due to macro expansion, a single `Body` might -/// be spread across several files. So, for each ExprId and PatId, we record -/// both the HirFileId and the position inside the file. However, we only store -/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle -/// this properly for macros. -#[derive(Default, Debug, Eq, PartialEq)] -pub struct BodySourceMap { - // AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map - // to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected). - expr_map: FxHashMap, - expr_map_back: ArenaMap, - - pat_map: FxHashMap, - pat_map_back: ArenaMap, - - label_map: FxHashMap, - label_map_back: ArenaMap, - - self_param: Option>>, - binding_definitions: FxHashMap>, - - /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). - /// Instead, we use id of expression (`92`) to identify the field. - field_map_back: FxHashMap, - pat_field_map_back: FxHashMap, - - pub types: TypesSourceMap, - - template_map: Option>, - - expansions: FxHashMap>, MacroFileId>, - - /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in - /// the source map (since they're just as volatile). - diagnostics: Vec, -} - -#[derive(Default, Debug, Eq, PartialEq)] -struct FormatTemplate { - /// A map from `format_args!()` expressions to their captures. - format_args_to_captures: FxHashMap)>, - /// A map from `asm!()` expressions to their captures. - asm_to_captures: FxHashMap>>, - /// 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, TextRange)>>, -} - -#[derive(Debug, Eq, PartialEq)] -pub enum BodyDiagnostic { - InactiveCode { node: InFile, cfg: CfgExpr, opts: CfgOptions }, - MacroError { node: InFile>, err: ExpandError }, - UnresolvedMacroCall { node: InFile>, path: ModPath }, - UnreachableLabel { node: InFile>, name: Name }, - AwaitOutsideOfAsync { node: InFile>, location: String }, - UndeclaredLabel { node: InFile>, name: Name }, -} - impl Body { pub(crate) fn body_with_source_map_query( db: &dyn DefDatabase, @@ -765,9 +768,7 @@ impl BodySourceMap { self.expansions.get(&src).cloned() } - pub fn macro_calls( - &self, - ) -> impl Iterator>, MacroFileId)> + '_ { + pub fn macro_calls(&self) -> impl Iterator, MacroFileId)> + '_ { self.expansions.iter().map(|(&a, &b)| (a, b)) } @@ -775,7 +776,7 @@ impl BodySourceMap { self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax) } - pub fn self_param_syntax(&self) -> Option>> { + pub fn self_param_syntax(&self) -> Option> { self.self_param } @@ -809,9 +810,7 @@ impl BodySourceMap { self.expr_map.get(&src).copied() } - pub fn expansions( - &self, - ) -> impl Iterator>, &MacroFileId)> { + pub fn expansions(&self) -> impl Iterator, &MacroFileId)> { self.expansions.iter() } @@ -831,7 +830,7 @@ impl BodySourceMap { pub fn format_args_implicit_capture( &self, capture_expr: ExprId, - ) -> Option, TextRange)>> { + ) -> Option> { self.template_map.as_ref()?.implicit_capture_to_source.get(&capture_expr).copied() }