Skip to content

Commit d073a85

Browse files
When resolving labels in break and continue for the IDE, do not resolve them textually, instead reuse the results of HIR lowering
This fixes a bug where labels inside macros were not resolved, but more importantly this prepares us to a future where we have hygiene, and textual equivalence isn't enough to resolve identifiers.
1 parent 8e4570a commit d073a85

3 files changed

Lines changed: 40 additions & 24 deletions

File tree

‎src/tools/rust-analyzer/crates/hir/src/semantics.rs‎

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ use span::{EditionedFileId, FileId, HirFileIdRepr};
3636
use stdx::TupleExt;
3737
use syntax::{
3838
algo::skip_trivia_token,
39-
ast::{self,HasAttrsas _,HasGenericParams,HasLoopBody,IsStringas _},
40-
match_ast,AstNode,AstToken,Direction,SyntaxKind,SyntaxNode,SyntaxNodePtr,SyntaxToken,
41-
TextRange,TextSize,
39+
ast::{self,HasAttrsas _,HasGenericParams,IsStringas _},
40+
AstNode,AstToken,Direction,SyntaxKind,SyntaxNode,SyntaxNodePtr,SyntaxToken,TextRange,
41+
TextSize,
4242
};
4343

4444
usecrate::{
@@ -1221,26 +1221,10 @@ impl<'db> SemanticsImpl<'db> {
12211221
ToDef::to_def(self, src.as_ref())
12221222
}
12231223

1224-
pubfnresolve_label(&self,lifetime:&ast::Lifetime) -> Option<Label>{
1225-
let text = lifetime.text();
1226-
let label = lifetime.syntax().ancestors().find_map(|syn| {
1227-
let label = match_ast!{
1228-
match syn {
1229-
ast::ForExpr(it) => it.label(),
1230-
ast::WhileExpr(it) => it.label(),
1231-
ast::LoopExpr(it) => it.label(),
1232-
ast::BlockExpr(it) => it.label(),
1233-
_ => None,
1234-
}
1235-
};
1236-
label.filter(|l| {
1237-
l.lifetime()
1238-
.and_then(|lt| lt.lifetime_ident_token())
1239-
.map_or(false, |lt| lt.text() == text)
1240-
})
1241-
})?;
1242-
let src = self.wrap_node_infile(label);
1243-
ToDef::to_def(self, src.as_ref())
1224+
pubfnresolve_label(&self,label:&ast::Lifetime) -> Option<Label>{
1225+
let(parent, label_id) = self
1226+
.with_ctx(|ctx| ctx.label_ref_to_def(self.wrap_node_infile(label.clone()).as_ref()))?;
1227+
Some(Label{ parent, label_id })
12441228
}
12451229

12461230
pubfnresolve_type(&self,ty:&ast::Type) -> Option<Type>{

‎src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ use hir_def::{
9292
keys::{self,Key},
9393
DynMap,
9494
},
95-
hir::{BindingId,LabelId},
95+
hir::{BindingId,Expr,LabelId},
9696
AdtId,BlockId,ConstId,ConstParamId,DefWithBodyId,EnumId,EnumVariantId,ExternCrateId,
9797
FieldId,FunctionId,GenericDefId,GenericParamId,ImplId,LifetimeParamId,Lookup,MacroId,
9898
ModuleId,StaticId,StructId,TraitAliasId,TraitId,TypeAliasId,TypeParamId,UnionId,UseId,
@@ -343,6 +343,20 @@ impl SourceToDefCtx<'_, '_> {
343343
Some((container, label_id))
344344
}
345345

346+
pub(super)fnlabel_ref_to_def(
347+
&mutself,
348+
src:InFile<&ast::Lifetime>,
349+
) -> Option<(DefWithBodyId,LabelId)>{
350+
let break_or_continue = ast::Expr::cast(src.value.syntax().parent()?)?;
351+
let container = self.find_pat_or_label_container(src.syntax_ref())?;
352+
let(body, source_map) = self.db.body_with_source_map(container);
353+
let break_or_continue = source_map.node_expr(src.with_value(&break_or_continue))?;
354+
let(Expr::Break{ label, .. } | Expr::Continue{ label }) = body[break_or_continue]else{
355+
returnNone;
356+
};
357+
Some((container, label?))
358+
}
359+
346360
pub(super)fnitem_to_macro_call(&mutself,src:InFile<&ast::Item>) -> Option<MacroCallId>{
347361
let map = self.dyn_map(src)?;
348362
map[keys::ATTR_MACRO_CALL].get(&AstPtr::new(src.value)).copied()

‎src/tools/rust-analyzer/crates/ide/src/goto_definition.rs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2660,6 +2660,24 @@ fn foo() {
26602660
);
26612661
}
26622662

2663+
#[test]
2664+
fnlabel_inside_macro(){
2665+
check(
2666+
r#"
2667+
macro_rules! m {
2668+
($s:stmt) => { $s };
2669+
}
2670+
2671+
fn foo() {
2672+
'label: loop {
2673+
// ^^^^^^
2674+
m!(continue 'label$0);
2675+
}
2676+
}
2677+
"#,
2678+
);
2679+
}
2680+
26632681
#[test]
26642682
fngoto_def_on_return_in_try(){
26652683
check(

0 commit comments

Comments
 (0)