From f2e19d05935e706547c78c0de04827e69f5fdaa2 Mon Sep 17 00:00:00 2001 From: Sarthak Singh Date: Mon, 22 Jul 2024 14:30:19 +0530 Subject: [PATCH 1/4] Continue inside a labeled block now lowers to a error when to lowering the ast --- compiler/rustc_ast_lowering/messages.ftl | 5 +++ compiler/rustc_ast_lowering/src/errors.rs | 10 +++++ compiler/rustc_ast_lowering/src/expr.rs | 20 ++++++--- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_resolve/src/late.rs | 44 +++++++++++++------ .../rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 3 +- tests/crashes/113379.rs | 7 --- .../label/label_break_value_continue.stderr | 12 ++--- .../cont-in-block/cont-in-fn-issue-113379.rs | 31 +++++++++++++ .../cont-in-fn-issue-113379.stderr | 33 ++++++++++++++ .../cont-in-match-arm-issue-121623.rs} | 4 +- .../cont-in-match-arm-issue-121623.stderr | 14 ++++++ 14 files changed, 153 insertions(+), 37 deletions(-) delete mode 100644 tests/crashes/113379.rs create mode 100644 tests/ui/lowering/cont-in-block/cont-in-fn-issue-113379.rs create mode 100644 tests/ui/lowering/cont-in-block/cont-in-fn-issue-113379.stderr rename tests/{crashes/121623.rs => ui/lowering/cont-in-block/cont-in-match-arm-issue-121623.rs} (64%) create mode 100644 tests/ui/lowering/cont-in-block/cont-in-match-arm-issue-121623.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 9ed93d481e773..566915b85dfb4 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -54,6 +54,11 @@ ast_lowering_clobber_abi_not_supported = ast_lowering_closure_cannot_be_static = closures cannot be static +ast_lowering_continue_labeled_block = + `continue` pointing to a labeled block + .label = labeled blocks cannot be `continue`'d + .block_label = labeled block the `continue` points to + ast_lowering_coroutine_too_many_parameters = too many parameters for a coroutine (expected 0 or 1 parameters) diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 7a6c9d8d0d375..ea1139e972cb6 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -451,3 +451,13 @@ pub(crate) struct YieldInClosure { #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")] pub suggestion: Option, } + +#[derive(Diagnostic)] +#[diag(ast_lowering_continue_labeled_block, code = E0696)] +pub struct ContinueLabeledBlock { + #[primary_span] + #[label] + pub span: Span, + #[label(ast_lowering_block_label)] + pub block_span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 124fe6bd380d2..57107bbc49333 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -15,14 +15,13 @@ use thin_vec::{thin_vec, ThinVec}; use super::errors::{ AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, - ClosureCannotBeStatic, CoroutineTooManyParameters, + ClosureCannotBeStatic, ContinueLabeledBlock, CoroutineTooManyParameters, FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody, - NeverPatternWithBody, NeverPatternWithGuard, UnderscoreExprLhsAssign, + NeverPatternWithBody, NeverPatternWithGuard, UnderscoreExprLhsAssign, YieldInClosure, }; use super::{ ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs, ResolverAstLoweringExt, }; -use crate::errors::YieldInClosure; use crate::{FnDeclKind, ImplTraitPosition}; impl<'hir> LoweringContext<'_, 'hir> { @@ -291,7 +290,16 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Break(self.lower_jump_destination(e.id, *opt_label), opt_expr) } ExprKind::Continue(opt_label) => { - hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label)) + if opt_label.is_some() + && let Some((_, is_loop, block_span)) = self.resolver.get_label_res(e.id) + && !is_loop + { + hir::ExprKind::Err( + self.dcx().emit_err(ContinueLabeledBlock { span: e.span, block_span }), + ) + } else { + hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label)) + } } ExprKind::Ret(e) => { let e = e.as_ref().map(|x| self.lower_expr(x)); @@ -1470,8 +1478,8 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination { let target_id = match destination { Some((id, _)) => { - if let Some(loop_id) = self.resolver.get_label_res(id) { - Ok(self.lower_node_id(loop_id)) + if let Some((id, _is_loop, _)) = self.resolver.get_label_res(id) { + Ok(self.lower_node_id(id)) } else { Err(hir::LoopIdError::UnresolvedLabel) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 224787c335beb..e04b8af135842 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -252,7 +252,7 @@ impl ResolverAstLowering { } /// Obtains resolution for a label with the given `NodeId`. - fn get_label_res(&self, id: NodeId) -> Option { + fn get_label_res(&self, id: NodeId) -> Option<(NodeId, bool, Span)> { self.label_res_map.get(&id).copied() } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9736428e6f7c7..98aabc7b8072a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -203,7 +203,8 @@ pub struct ResolverAstLowering { /// Resolutions for import nodes, which have multiple resolutions in different namespaces. pub import_res_map: NodeMap>>>, /// Resolutions for labels (node IDs of their corresponding blocks or loops). - pub label_res_map: NodeMap, + /// The boolean stores if the node is loop. The span is the span of the node. + pub label_res_map: NodeMap<(ast::NodeId, bool, Span)>, /// Resolutions for lifetimes. pub lifetimes_res_map: NodeMap, /// Lifetime parameters that lowering will have to introduce. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 7e5fd82b80cee..777ae128b79ef 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -672,7 +672,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { last_block_rib: Option>, /// The current set of local scopes, for labels. - label_ribs: Vec>, + label_ribs: Vec>, /// The current set of local scopes for lifetimes. lifetime_ribs: Vec, @@ -2316,7 +2316,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved /// label and reports an error if the label is not found or is unreachable. - fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'a>> { + fn resolve_label( + &mut self, + mut label: Ident, + ) -> Result<((NodeId, bool, Span), Span), ResolutionError<'a>> { let mut suggestion = None; for i in (0..self.label_ribs.len()).rev() { @@ -4333,7 +4336,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { Ok(Some(result)) } - fn with_resolved_label(&mut self, label: Option