Skip to content

Commit 4ccc83a

Browse files
committed
Auto merge of rust-lang#14509 - Veykril:label-lower-body, r=Veykril
internal: Resolve labels in body lowering Fixes rust-lang/rust-analyzer#14503 (comment)
2 parents e9e5772 + fbb1bd5 commit 4ccc83a

File tree

14 files changed

+438
-156
lines changed

14 files changed

+438
-156
lines changed

crates/hir-def/src/body.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use cfg::{CfgExpr, CfgOptions};
1313
use drop_bomb::DropBomb;
1414
use either::Either;
1515
use hir_expand::{
16-
attrs::RawAttrs, hygiene::Hygiene, ExpandError, ExpandResult, HirFileId, InFile, MacroCallId,
16+
attrs::RawAttrs, hygiene::Hygiene, name::Name, ExpandError, ExpandResult, HirFileId, InFile,
17+
MacroCallId,
1718
};
1819
use la_arena::{Arena, ArenaMap};
1920
use limit::Limit;
@@ -343,6 +344,8 @@ pub enum BodyDiagnostic {
343344
MacroError { node: InFile<AstPtr<ast::MacroCall>>, message: String },
344345
UnresolvedProcMacro { node: InFile<AstPtr<ast::MacroCall>>, krate: CrateId },
345346
UnresolvedMacroCall { node: InFile<AstPtr<ast::MacroCall>>, path: ModPath },
347+
UnreachableLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
348+
UndeclaredLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
346349
}
347350

348351
impl Body {

crates/hir-def/src/body/lower.rs

+199-76
Large diffs are not rendered by default.

crates/hir-def/src/body/pretty.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,14 @@ impl<'a> Printer<'a> {
219219
}
220220
Expr::Continue { label } => {
221221
w!(self, "continue");
222-
if let Some(label) = label {
223-
w!(self, " {}", label);
222+
if let Some(lbl) = label {
223+
w!(self, " {}", self.body[*lbl].name);
224224
}
225225
}
226226
Expr::Break { expr, label } => {
227227
w!(self, "break");
228-
if let Some(label) = label {
229-
w!(self, " {}", label);
228+
if let Some(lbl) = label {
229+
w!(self, " {}", self.body[*lbl].name);
230230
}
231231
if let Some(expr) = expr {
232232
self.whitespace();

crates/hir-def/src/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,11 @@ pub enum Expr {
168168
arms: Box<[MatchArm]>,
169169
},
170170
Continue {
171-
label: Option<Name>,
171+
label: Option<LabelId>,
172172
},
173173
Break {
174174
expr: Option<ExprId>,
175-
label: Option<Name>,
175+
label: Option<LabelId>,
176176
},
177177
Return {
178178
expr: Option<ExprId>,

crates/hir-expand/src/name.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,7 @@ impl Name {
120120
use std::sync::atomic::{AtomicUsize, Ordering};
121121
static CNT: AtomicUsize = AtomicUsize::new(0);
122122
let c = CNT.fetch_add(1, Ordering::Relaxed);
123-
// FIXME: Currently a `__RA_generated_name` in user code will break our analysis
124-
Name::new_text(format!("__RA_geneated_name_{c}").into())
123+
Name::new_text(format!("<ra@gennew>{c}").into())
125124
}
126125

127126
/// Returns the tuple index this name represents if it is a tuple field.

crates/hir-ty/src/infer.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::{convert::identity, ops::Index};
1818

1919
use chalk_ir::{cast::Cast, DebruijnIndex, Mutability, Safety, Scalar, TypeFlags};
2020
use either::Either;
21+
use hir_def::expr::LabelId;
2122
use hir_def::{
2223
body::Body,
2324
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
@@ -188,7 +189,7 @@ pub enum InferenceDiagnostic {
188189
/// Contains the type the field resolves to
189190
field_with_same_name: Option<Ty>,
190191
},
191-
// FIXME: Make this proper
192+
// FIXME: This should be emitted in body lowering
192193
BreakOutsideOfLoop {
193194
expr: ExprId,
194195
is_break: bool,
@@ -468,7 +469,7 @@ struct BreakableContext {
468469
/// The coercion target of the context.
469470
coerce: Option<CoerceMany>,
470471
/// The optional label of the context.
471-
label: Option<name::Name>,
472+
label: Option<LabelId>,
472473
kind: BreakableKind,
473474
}
474475

@@ -483,21 +484,21 @@ enum BreakableKind {
483484

484485
fn find_breakable<'c>(
485486
ctxs: &'c mut [BreakableContext],
486-
label: Option<&name::Name>,
487+
label: Option<LabelId>,
487488
) -> Option<&'c mut BreakableContext> {
488489
let mut ctxs = ctxs
489490
.iter_mut()
490491
.rev()
491492
.take_while(|it| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));
492493
match label {
493-
Some(_) => ctxs.find(|ctx| ctx.label.as_ref() == label),
494+
Some(_) => ctxs.find(|ctx| ctx.label == label),
494495
None => ctxs.find(|ctx| matches!(ctx.kind, BreakableKind::Loop)),
495496
}
496497
}
497498

498499
fn find_continuable<'c>(
499500
ctxs: &'c mut [BreakableContext],
500-
label: Option<&name::Name>,
501+
label: Option<LabelId>,
501502
) -> Option<&'c mut BreakableContext> {
502503
match label {
503504
Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),

crates/hir-ty/src/infer/expr.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,8 @@ impl<'a> InferenceContext<'a> {
459459
self.resolver.reset_to_guard(g);
460460
ty
461461
}
462-
Expr::Continue { label } => {
463-
if let None = find_continuable(&mut self.breakables, label.as_ref()) {
462+
&Expr::Continue { label } => {
463+
if let None = find_continuable(&mut self.breakables, label) {
464464
self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
465465
expr: tgt_expr,
466466
is_break: false,
@@ -469,9 +469,9 @@ impl<'a> InferenceContext<'a> {
469469
};
470470
self.result.standard_types.never.clone()
471471
}
472-
Expr::Break { expr, label } => {
473-
let val_ty = if let Some(expr) = *expr {
474-
let opt_coerce_to = match find_breakable(&mut self.breakables, label.as_ref()) {
472+
&Expr::Break { expr, label } => {
473+
let val_ty = if let Some(expr) = expr {
474+
let opt_coerce_to = match find_breakable(&mut self.breakables, label) {
475475
Some(ctxt) => match &ctxt.coerce {
476476
Some(coerce) => coerce.expected_ty(),
477477
None => {
@@ -490,13 +490,13 @@ impl<'a> InferenceContext<'a> {
490490
TyBuilder::unit()
491491
};
492492

493-
match find_breakable(&mut self.breakables, label.as_ref()) {
493+
match find_breakable(&mut self.breakables, label) {
494494
Some(ctxt) => match ctxt.coerce.take() {
495495
Some(mut coerce) => {
496-
coerce.coerce(self, *expr, &val_ty);
496+
coerce.coerce(self, expr, &val_ty);
497497

498498
// Avoiding borrowck
499-
let ctxt = find_breakable(&mut self.breakables, label.as_ref())
499+
let ctxt = find_breakable(&mut self.breakables, label)
500500
.expect("breakable stack changed during coercion");
501501
ctxt.may_break = true;
502502
ctxt.coerce = Some(coerce);
@@ -1900,7 +1900,6 @@ impl<'a> InferenceContext<'a> {
19001900
cb: impl FnOnce(&mut Self) -> T,
19011901
) -> (Option<Ty>, T) {
19021902
self.breakables.push({
1903-
let label = label.map(|label| self.body[label].name.clone());
19041903
BreakableContext { kind, may_break: false, coerce: ty.map(CoerceMany::new), label }
19051904
});
19061905
let res = cb(self);

crates/hir-ty/src/mir/lower.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct MirLowerCtx<'a> {
4747
current_loop_blocks: Option<LoopBlocks>,
4848
// FIXME: we should resolve labels in HIR lowering and always work with label id here, not
4949
// with raw names.
50-
labeled_loop_blocks: FxHashMap<Name, LoopBlocks>,
50+
labeled_loop_blocks: FxHashMap<LabelId, LoopBlocks>,
5151
discr_temp: Option<Place>,
5252
db: &'a dyn HirDatabase,
5353
body: &'a Body,
@@ -579,19 +579,19 @@ impl MirLowerCtx<'_> {
579579
Ok(None)
580580
}
581581
},
582-
Expr::Break { expr, label } => {
582+
&Expr::Break { expr, label } => {
583583
if let Some(expr) = expr {
584584
let loop_data = match label {
585-
Some(l) => self.labeled_loop_blocks.get(l).ok_or(MirLowerError::UnresolvedLabel)?,
585+
Some(l) => self.labeled_loop_blocks.get(&l).ok_or(MirLowerError::UnresolvedLabel)?,
586586
None => self.current_loop_blocks.as_ref().ok_or(MirLowerError::BreakWithoutLoop)?,
587587
};
588-
let Some(c) = self.lower_expr_to_place(*expr, loop_data.place.clone(), current)? else {
588+
let Some(c) = self.lower_expr_to_place(expr, loop_data.place.clone(), current)? else {
589589
return Ok(None);
590590
};
591591
current = c;
592592
}
593593
let end = match label {
594-
Some(l) => self.labeled_loop_blocks.get(l).ok_or(MirLowerError::UnresolvedLabel)?.end.expect("We always generate end for labeled loops"),
594+
Some(l) => self.labeled_loop_blocks.get(&l).ok_or(MirLowerError::UnresolvedLabel)?.end.expect("We always generate end for labeled loops"),
595595
None => self.current_loop_end()?,
596596
};
597597
self.set_goto(current, end);
@@ -1119,10 +1119,8 @@ impl MirLowerCtx<'_> {
11191119
// bad as we may emit end (unneccessary unreachable block) for unterminating loop, but
11201120
// it should not affect correctness.
11211121
self.current_loop_end()?;
1122-
self.labeled_loop_blocks.insert(
1123-
self.body.labels[label].name.clone(),
1124-
self.current_loop_blocks.as_ref().unwrap().clone(),
1125-
)
1122+
self.labeled_loop_blocks
1123+
.insert(label, self.current_loop_blocks.as_ref().unwrap().clone())
11261124
} else {
11271125
None
11281126
};
@@ -1131,7 +1129,7 @@ impl MirLowerCtx<'_> {
11311129
let my = mem::replace(&mut self.current_loop_blocks, prev)
11321130
.ok_or(MirLowerError::ImplementationError("current_loop_blocks is corrupt"))?;
11331131
if let Some(prev) = prev_label {
1134-
self.labeled_loop_blocks.insert(self.body.labels[label.unwrap()].name.clone(), prev);
1132+
self.labeled_loop_blocks.insert(label.unwrap(), prev);
11351133
}
11361134
Ok(my.end)
11371135
}

crates/hir/src/diagnostics.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ diagnostics![
5050
PrivateField,
5151
ReplaceFilterMapNextWithFindMap,
5252
TypeMismatch,
53+
UndeclaredLabel,
5354
UnimplementedBuiltinMacro,
55+
UnreachableLabel,
5456
UnresolvedExternCrate,
5557
UnresolvedField,
5658
UnresolvedImport,
@@ -61,6 +63,13 @@ diagnostics![
6163
UnusedMut,
6264
];
6365

66+
#[derive(Debug)]
67+
pub struct BreakOutsideOfLoop {
68+
pub expr: InFile<AstPtr<ast::Expr>>,
69+
pub is_break: bool,
70+
pub bad_value_break: bool,
71+
}
72+
6473
#[derive(Debug)]
6574
pub struct UnresolvedModule {
6675
pub decl: InFile<AstPtr<ast::Module>>,
@@ -84,6 +93,17 @@ pub struct UnresolvedMacroCall {
8493
pub path: ModPath,
8594
pub is_bang: bool,
8695
}
96+
#[derive(Debug, Clone, Eq, PartialEq)]
97+
pub struct UnreachableLabel {
98+
pub node: InFile<AstPtr<ast::Lifetime>>,
99+
pub name: Name,
100+
}
101+
102+
#[derive(Debug, Clone, Eq, PartialEq)]
103+
pub struct UndeclaredLabel {
104+
pub node: InFile<AstPtr<ast::Lifetime>>,
105+
pub name: Name,
106+
}
87107

88108
#[derive(Debug, Clone, Eq, PartialEq)]
89109
pub struct InactiveCode {
@@ -166,13 +186,6 @@ pub struct PrivateField {
166186
pub field: Field,
167187
}
168188

169-
#[derive(Debug)]
170-
pub struct BreakOutsideOfLoop {
171-
pub expr: InFile<AstPtr<ast::Expr>>,
172-
pub is_break: bool,
173-
pub bad_value_break: bool,
174-
}
175-
176189
#[derive(Debug)]
177190
pub struct MissingUnsafe {
178191
pub expr: InFile<AstPtr<ast::Expr>>,

crates/hir/src/lib.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,10 @@ pub use crate::{
8888
AnyDiagnostic, BreakOutsideOfLoop, ExpectedFunction, InactiveCode, IncoherentImpl,
8989
IncorrectCase, InvalidDeriveTarget, MacroError, MalformedDerive, MismatchedArgCount,
9090
MissingFields, MissingMatchArms, MissingUnsafe, NeedMut, NoSuchField, PrivateAssocItem,
91-
PrivateField, ReplaceFilterMapNextWithFindMap, TypeMismatch, UnimplementedBuiltinMacro,
92-
UnresolvedExternCrate, UnresolvedField, UnresolvedImport, UnresolvedMacroCall,
93-
UnresolvedMethodCall, UnresolvedModule, UnresolvedProcMacro, UnusedMut,
91+
PrivateField, ReplaceFilterMapNextWithFindMap, TypeMismatch, UndeclaredLabel,
92+
UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate, UnresolvedField,
93+
UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule,
94+
UnresolvedProcMacro, UnusedMut,
9495
},
9596
has_source::HasSource,
9697
semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
@@ -1393,6 +1394,12 @@ impl DefWithBody {
13931394
}
13941395
.into(),
13951396
),
1397+
BodyDiagnostic::UnreachableLabel { node, name } => {
1398+
acc.push(UnreachableLabel { node: node.clone(), name: name.clone() }.into())
1399+
}
1400+
BodyDiagnostic::UndeclaredLabel { node, name } => {
1401+
acc.push(UndeclaredLabel { node: node.clone(), name: name.clone() }.into())
1402+
}
13961403
}
13971404
}
13981405

@@ -1405,14 +1412,6 @@ impl DefWithBody {
14051412
let field = source_map.field_syntax(expr);
14061413
acc.push(NoSuchField { field }.into())
14071414
}
1408-
&hir_ty::InferenceDiagnostic::BreakOutsideOfLoop {
1409-
expr,
1410-
is_break,
1411-
bad_value_break,
1412-
} => {
1413-
let expr = expr_syntax(expr);
1414-
acc.push(BreakOutsideOfLoop { expr, is_break, bad_value_break }.into())
1415-
}
14161415
&hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
14171416
acc.push(
14181417
MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found }
@@ -1484,6 +1483,14 @@ impl DefWithBody {
14841483
.into(),
14851484
)
14861485
}
1486+
&hir_ty::InferenceDiagnostic::BreakOutsideOfLoop {
1487+
expr,
1488+
is_break,
1489+
bad_value_break,
1490+
} => {
1491+
let expr = expr_syntax(expr);
1492+
acc.push(BreakOutsideOfLoop { expr, is_break, bad_value_break }.into())
1493+
}
14871494
}
14881495
}
14891496
for (pat_or_expr, mismatch) in infer.type_mismatches() {

0 commit comments

Comments
 (0)