| use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; |
| |
| // Diagnostic: break-outside-of-loop |
| // |
| // This diagnostic is triggered if the `break` keyword is used outside of a loop. |
| pub(crate) fn break_outside_of_loop( |
| ctx: &DiagnosticsContext<'_>, |
| d: &hir::BreakOutsideOfLoop, |
| ) -> Diagnostic { |
| let message = if d.bad_value_break { |
| "can't break with a value in this position".to_owned() |
| } else { |
| let construct = if d.is_break { "break" } else { "continue" }; |
| format!("{construct} outside of loop") |
| }; |
| Diagnostic::new_with_syntax_node_ptr( |
| ctx, |
| DiagnosticCode::RustcHardError("E0268"), |
| message, |
| d.expr.map(|it| it.into()), |
| ) |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use crate::tests::check_diagnostics; |
| |
| #[test] |
| fn outside_of_loop() { |
| check_diagnostics( |
| r#" |
| fn foo() { |
| break; |
| //^^^^^ error: break outside of loop |
| continue; |
| //^^^^^^^^ error: continue outside of loop |
| } |
| "#, |
| ); |
| } |
| |
| #[test] |
| fn async_blocks_are_borders() { |
| check_diagnostics( |
| r#" |
| fn foo() { |
| 'a: loop { |
| async { |
| break; |
| //^^^^^ error: break outside of loop |
| continue; |
| //^^^^^^^^ error: continue outside of loop |
| }; |
| } |
| } |
| "#, |
| ); |
| } |
| |
| #[test] |
| fn closures_are_borders() { |
| check_diagnostics( |
| r#" |
| fn foo() { |
| 'a: loop { |
| || { |
| break; |
| //^^^^^ error: break outside of loop |
| continue; |
| //^^^^^^^^ error: continue outside of loop |
| }; |
| } |
| } |
| "#, |
| ); |
| } |
| |
| #[test] |
| fn blocks_pass_through() { |
| check_diagnostics( |
| r#" |
| fn foo() { |
| 'a: loop { |
| { |
| break; |
| continue; |
| } |
| } |
| } |
| "#, |
| ); |
| } |
| |
| #[test] |
| fn try_blocks_pass_through() { |
| check_diagnostics( |
| r#" |
| fn foo() { |
| 'a: loop { |
| try { |
| break; |
| continue; |
| }; |
| } |
| } |
| "#, |
| ); |
| } |
| |
| #[test] |
| fn label_blocks() { |
| check_diagnostics( |
| r#" |
| fn foo() { |
| 'a: { |
| break; |
| //^^^^^ error: break outside of loop |
| continue; |
| //^^^^^^^^ error: continue outside of loop |
| } |
| } |
| "#, |
| ); |
| } |
| |
| #[test] |
| fn value_break_in_for_loop() { |
| // FIXME: the error is correct, but the message is terrible |
| check_diagnostics( |
| r#" |
| //- minicore: iterator |
| fn test() { |
| for _ in [()] { |
| break 3; |
| // ^ error: expected (), found i32 |
| } |
| } |
| "#, |
| ); |
| } |
| |
| #[test] |
| fn try_block_desugaring_inside_closure() { |
| // regression test for #14701 |
| check_diagnostics( |
| r#" |
| //- minicore: option, try |
| fn test() { |
| try { |
| || { |
| let x = Some(2); |
| Some(x?) |
| }; |
| }; |
| } |
| "#, |
| ); |
| } |
| } |