Skip to content

Commit 0632001

Browse files
bors[bot]Veykril
andauthored
Merge #7021
7021: Track labels in the HIR r=matklad a=Veykril Groundwork for #6966 Co-authored-by: Lukas Wirth <[email protected]>
2 parents 1487f2f + 262b9c3 commit 0632001

File tree

9 files changed

+167
-68
lines changed

9 files changed

+167
-68
lines changed

crates/hir/src/code_model.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use hir_def::{
99
adt::StructKind,
1010
adt::VariantData,
1111
builtin_type::BuiltinType,
12-
expr::{BindingAnnotation, Pat, PatId},
12+
expr::{BindingAnnotation, LabelId, Pat, PatId},
1313
import_map,
1414
item_tree::ItemTreeNode,
1515
lang_item::LangItemTarget,
@@ -1205,6 +1205,34 @@ impl Local {
12051205
}
12061206
}
12071207

1208+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1209+
pub struct Label {
1210+
pub(crate) parent: DefWithBodyId,
1211+
pub(crate) label_id: LabelId,
1212+
}
1213+
1214+
impl Label {
1215+
pub fn module(self, db: &dyn HirDatabase) -> Module {
1216+
self.parent(db).module(db)
1217+
}
1218+
1219+
pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
1220+
self.parent.into()
1221+
}
1222+
1223+
pub fn name(self, db: &dyn HirDatabase) -> Name {
1224+
let body = db.body(self.parent.into());
1225+
body[self.label_id].name.clone()
1226+
}
1227+
1228+
pub fn source(self, db: &dyn HirDatabase) -> InFile<ast::Label> {
1229+
let (_body, source_map) = db.body_with_source_map(self.parent.into());
1230+
let src = source_map.label_syntax(self.label_id);
1231+
let root = src.file_syntax(db.upcast());
1232+
src.map(|ast| ast.to_node(&root))
1233+
}
1234+
}
1235+
12081236
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
12091237
pub enum GenericParam {
12101238
TypeParam(TypeParam),

crates/hir/src/from_id.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
//! are splitting the hir.
55
66
use hir_def::{
7-
expr::PatId, item_scope::ItemInNs, AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId,
8-
GenericDefId, ModuleDefId, VariantId,
7+
expr::{LabelId, PatId},
8+
item_scope::ItemInNs,
9+
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, GenericDefId, ModuleDefId,
10+
VariantId,
911
};
1012

1113
use crate::{
12-
Adt, AssocItem, DefWithBody, Field, GenericDef, Local, MacroDef, ModuleDef, Variant, VariantDef,
14+
Adt, AssocItem, DefWithBody, Field, GenericDef, Label, Local, MacroDef, ModuleDef, Variant,
15+
VariantDef,
1316
};
1417

1518
macro_rules! from_id {
@@ -228,6 +231,12 @@ impl From<(DefWithBodyId, PatId)> for Local {
228231
}
229232
}
230233

234+
impl From<(DefWithBodyId, LabelId)> for Label {
235+
fn from((parent, label_id): (DefWithBodyId, LabelId)) -> Self {
236+
Label { parent, label_id }
237+
}
238+
}
239+
231240
impl From<MacroDef> for ItemInNs {
232241
fn from(macro_def: MacroDef) -> Self {
233242
ItemInNs::Macros(macro_def.into())

crates/hir/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ pub use crate::{
3535
code_model::{
3636
Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const,
3737
Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, GenericDef,
38-
HasVisibility, Impl, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef, Static,
39-
Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
38+
HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef,
39+
Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
4040
},
4141
has_source::HasSource,
4242
semantics::{PathResolution, Semantics, SemanticsScope},

crates/hir/src/semantics.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use itertools::Itertools;
1515
use rustc_hash::{FxHashMap, FxHashSet};
1616
use syntax::{
1717
algo::find_node_at_offset,
18-
ast::{self, GenericParamsOwner},
18+
ast::{self, GenericParamsOwner, LoopBodyOwner},
1919
match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize,
2020
};
2121

@@ -25,8 +25,8 @@ use crate::{
2525
diagnostics::Diagnostic,
2626
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
2727
source_analyzer::{resolve_hir_path, SourceAnalyzer},
28-
AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, LifetimeParam, Local,
29-
MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
28+
AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, Label, LifetimeParam,
29+
Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
3030
VariantDef,
3131
};
3232

@@ -182,6 +182,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
182182
self.imp.resolve_lifetime_param(lifetime)
183183
}
184184

185+
pub fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> {
186+
self.imp.resolve_label(lifetime)
187+
}
188+
185189
pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
186190
self.imp.type_of_expr(expr)
187191
}
@@ -425,6 +429,28 @@ impl<'db> SemanticsImpl<'db> {
425429
ToDef::to_def(self, src)
426430
}
427431

432+
fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> {
433+
let text = lifetime.text();
434+
let label = lifetime.syntax().ancestors().find_map(|syn| {
435+
let label = match_ast! {
436+
match syn {
437+
ast::ForExpr(it) => it.label(),
438+
ast::WhileExpr(it) => it.label(),
439+
ast::LoopExpr(it) => it.label(),
440+
ast::EffectExpr(it) => it.label(),
441+
_ => None,
442+
}
443+
};
444+
label.filter(|l| {
445+
l.lifetime()
446+
.and_then(|lt| lt.lifetime_ident_token())
447+
.map_or(false, |lt| lt.text() == text)
448+
})
449+
})?;
450+
let src = self.find_file(label.syntax().clone()).with_value(label);
451+
ToDef::to_def(self, src)
452+
}
453+
428454
fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
429455
self.analyze(expr.syntax()).type_of_expr(self.db, expr)
430456
}
@@ -720,6 +746,7 @@ to_def_impls![
720746
(crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
721747
(crate::MacroDef, ast::MacroRules, macro_rules_to_def),
722748
(crate::Local, ast::IdentPat, bind_pat_to_def),
749+
(crate::Label, ast::Label, label_to_def),
723750
];
724751

725752
fn find_root(node: &SyntaxNode) -> SyntaxNode {

crates/hir/src/semantics/source_to_def.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use base_db::FileId;
44
use hir_def::{
55
child_by_source::ChildBySource,
66
dyn_map::DynMap,
7-
expr::PatId,
7+
expr::{LabelId, PatId},
88
keys::{self, Key},
99
ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId,
1010
LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
@@ -108,12 +108,21 @@ impl SourceToDefCtx<'_, '_> {
108108
&mut self,
109109
src: InFile<ast::IdentPat>,
110110
) -> Option<(DefWithBodyId, PatId)> {
111-
let container = self.find_pat_container(src.as_ref().map(|it| it.syntax()))?;
111+
let container = self.find_pat_or_label_container(src.as_ref().map(|it| it.syntax()))?;
112112
let (_body, source_map) = self.db.body_with_source_map(container);
113113
let src = src.map(ast::Pat::from);
114114
let pat_id = source_map.node_pat(src.as_ref())?;
115115
Some((container, pat_id))
116116
}
117+
pub(super) fn label_to_def(
118+
&mut self,
119+
src: InFile<ast::Label>,
120+
) -> Option<(DefWithBodyId, LabelId)> {
121+
let container = self.find_pat_or_label_container(src.as_ref().map(|it| it.syntax()))?;
122+
let (_body, source_map) = self.db.body_with_source_map(container);
123+
let label_id = source_map.node_label(src.as_ref())?;
124+
Some((container, label_id))
125+
}
117126

118127
fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
119128
&mut self,
@@ -237,7 +246,7 @@ impl SourceToDefCtx<'_, '_> {
237246
None
238247
}
239248

240-
fn find_pat_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
249+
fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
241250
for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
242251
let res: DefWithBodyId = match_ast! {
243252
match (container.value) {

crates/hir_def/src/body.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub(crate) use lower::LowerCtx;
2626
use crate::{
2727
attr::{Attrs, RawAttrs},
2828
db::DefDatabase,
29-
expr::{Expr, ExprId, Pat, PatId},
29+
expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
3030
item_scope::BuiltinShadowMode,
3131
item_scope::ItemScope,
3232
nameres::CrateDefMap,
@@ -226,6 +226,7 @@ pub(crate) struct Mark {
226226
pub struct Body {
227227
pub exprs: Arena<Expr>,
228228
pub pats: Arena<Pat>,
229+
pub labels: Arena<Label>,
229230
/// The patterns for the function's parameters. While the parameter types are
230231
/// part of the function signature, the patterns are not (they don't change
231232
/// the external type of the function).
@@ -244,6 +245,8 @@ pub type ExprSource = InFile<ExprPtr>;
244245
pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
245246
pub type PatSource = InFile<PatPtr>;
246247

248+
pub type LabelPtr = AstPtr<ast::Label>;
249+
pub type LabelSource = InFile<LabelPtr>;
247250
/// An item body together with the mapping from syntax nodes to HIR expression
248251
/// IDs. This is needed to go from e.g. a position in a file to the HIR
249252
/// expression containing it; but for type inference etc., we want to operate on
@@ -261,6 +264,8 @@ pub struct BodySourceMap {
261264
expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>,
262265
pat_map: FxHashMap<PatSource, PatId>,
263266
pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
267+
label_map: FxHashMap<LabelSource, LabelId>,
268+
label_map_back: ArenaMap<LabelId, LabelSource>,
264269
field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>,
265270
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
266271

@@ -334,6 +339,14 @@ impl Index<PatId> for Body {
334339
}
335340
}
336341

342+
impl Index<LabelId> for Body {
343+
type Output = Label;
344+
345+
fn index(&self, label: LabelId) -> &Label {
346+
&self.labels[label]
347+
}
348+
}
349+
337350
impl BodySourceMap {
338351
pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
339352
self.expr_map_back[expr].clone()
@@ -363,6 +376,15 @@ impl BodySourceMap {
363376
self.pat_map.get(&src).cloned()
364377
}
365378

379+
pub fn label_syntax(&self, label: LabelId) -> LabelSource {
380+
self.label_map_back[label].clone()
381+
}
382+
383+
pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
384+
let src = node.map(|it| AstPtr::new(it));
385+
self.label_map.get(&src).cloned()
386+
}
387+
366388
pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> {
367389
self.field_map[&(expr, field)].clone()
368390
}

0 commit comments

Comments
 (0)