From cb1a29b3ff4ae8c9fc814e31fdf5e43814a31293 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 25 Nov 2024 18:58:23 +0100 Subject: [PATCH] Make ice finalizer common for both resolvers. gcc/rust/ChangeLog: * Make-lang.in: * resolve/rust-ast-resolve-expr.cc (funny_ice_finalizer): * resolve/rust-late-name-resolver-2.0.cc (funny_ice_finalizer): (Late::visit): * resolve/rust-ice-finalizer.cc: New file. * resolve/rust-ice-finalizer.h: New file. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/Make-lang.in | 1 + gcc/rust/resolve/rust-ast-resolve-expr.cc | 41 +----------- gcc/rust/resolve/rust-ice-finalizer.cc | 35 ++++++++++ gcc/rust/resolve/rust-ice-finalizer.h | 64 +++++++++++++++++++ .../resolve/rust-late-name-resolver-2.0.cc | 43 +------------ 5 files changed, 103 insertions(+), 81 deletions(-) create mode 100644 gcc/rust/resolve/rust-ice-finalizer.cc create mode 100644 gcc/rust/resolve/rust-ice-finalizer.h diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 6de0a20b6a0a..f729285caf82 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -133,6 +133,7 @@ GRS_OBJS = \ rust/rust-toplevel-name-resolver-2.0.o \ rust/rust-early-name-resolver-2.0.o \ rust/rust-finalize-imports-2.0.o \ + rust/rust-ice-finalizer.o \ rust/rust-late-name-resolver-2.0.o \ rust/rust-immutable-name-resolution-context.o \ rust/rust-early-name-resolver.o \ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 9c2be4a57160..32691cbf7761 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -22,8 +22,8 @@ #include "rust-ast-resolve-type.h" #include "rust-ast-resolve-pattern.h" #include "rust-ast-resolve-path.h" -#include "diagnostic.h" #include "rust-expr.h" +#include "rust-ice-finalizer.h" namespace Rust { namespace Resolver { @@ -108,45 +108,6 @@ ResolveExpr::visit (AST::AssignmentExpr &expr) ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); } -/* The "break rust" Easter egg. - - Backstory: once upon a time, there used to be a bug in rustc: it would ICE - during typechecking on a 'break' with an expression outside of a loop. The - issue has been reported [0] and fixed [1], but in recognition of this, as a - special Easter egg, "break rust" was made to intentionally cause an ICE. - - [0]: https://github.com/rust-lang/rust/issues/43162 - [1]: https://github.com/rust-lang/rust/pull/43745 - - This was made in a way that does not break valid programs: namely, it only - happens when the 'break' is outside of a loop (so invalid anyway). - - GCC Rust supports this essential feature as well, but in a slightly - different way. Instead of delaying the error until type checking, we emit - it here in the resolution phase. We, too, only do this to programs that - are already invalid: we only emit our funny ICE if the name "rust" (which - must be immediately inside a break-with-a-value expression) fails to - resolve. Note that "break (rust)" does not trigger our ICE, only using - "break rust" directly does, and only if there's no "rust" in scope. We do - this in the same way regardless of whether the "break" is outside of a loop - or inside one. - - As a GNU extension, we also support "break gcc", much to the same effect, - subject to the same rules. */ - -/* The finalizer for our funny ICE. This prints a custom message instead of - the default bug reporting instructions, as there is no bug to report. */ - -static void ATTRIBUTE_NORETURN -funny_ice_finalizer (diagnostic_context *context, - const diagnostic_info *diagnostic, diagnostic_t diag_kind) -{ - gcc_assert (diag_kind == DK_ICE_NOBT); - default_diagnostic_finalizer (context, diagnostic, diag_kind); - fnotice (stderr, "You have broken GCC Rust. This is a feature.\n"); - exit (ICE_EXIT_CODE); -} - void ResolveExpr::visit (AST::IdentifierExpr &expr) { diff --git a/gcc/rust/resolve/rust-ice-finalizer.cc b/gcc/rust/resolve/rust-ice-finalizer.cc new file mode 100644 index 000000000000..3ec8438289ba --- /dev/null +++ b/gcc/rust/resolve/rust-ice-finalizer.cc @@ -0,0 +1,35 @@ +// Copyright (C) 2020-2024 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-ice-finalizer.h" + +namespace Rust { +namespace Resolver { + +void ATTRIBUTE_NORETURN +funny_ice_finalizer (diagnostic_context *context, + const diagnostic_info *diagnostic, diagnostic_t diag_kind) +{ + gcc_assert (diag_kind == DK_ICE_NOBT); + default_diagnostic_finalizer (context, diagnostic, diag_kind); + fnotice (stderr, "You have broken GCC Rust. This is a feature.\n"); + exit (ICE_EXIT_CODE); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/resolve/rust-ice-finalizer.h b/gcc/rust/resolve/rust-ice-finalizer.h new file mode 100644 index 000000000000..c73a729fd6da --- /dev/null +++ b/gcc/rust/resolve/rust-ice-finalizer.h @@ -0,0 +1,64 @@ +// Copyright (C) 2020-2024 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_ICE_FINALIZER_H +#define RUST_ICE_FINALIZER_H + +#include "rust-linemap.h" +#include "diagnostic.h" + +namespace Rust { +namespace Resolver { + +/* The "break rust" Easter egg. + + Backstory: once upon a time, there used to be a bug in rustc: it would ICE + during typechecking on a 'break' with an expression outside of a loop. The + issue has been reported [0] and fixed [1], but in recognition of this, as a + special Easter egg, "break rust" was made to intentionally cause an ICE. + + [0]: https://github.com/rust-lang/rust/issues/43162 + [1]: https://github.com/rust-lang/rust/pull/43745 + + This was made in a way that does not break valid programs: namely, it only + happens when the 'break' is outside of a loop (so invalid anyway). + + GCC Rust supports this essential feature as well, but in a slightly + different way. Instead of delaying the error until type checking, we emit + it here in the resolution phase. We, too, only do this to programs that + are already invalid: we only emit our funny ICE if the name "rust" (which + must be immediately inside a break-with-a-value expression) fails to + resolve. Note that "break (rust)" does not trigger our ICE, only using + "break rust" directly does, and only if there's no "rust" in scope. We do + this in the same way regardless of whether the "break" is outside of a loop + or inside one. + + As a GNU extension, we also support "break gcc", much to the same effect, + subject to the same rules. */ + +/* The finalizer for our funny ICE. This prints a custom message instead of + the default bug reporting instructions, as there is no bug to report. */ + +void ATTRIBUTE_NORETURN +funny_ice_finalizer (diagnostic_context *context, + const diagnostic_info *diagnostic, diagnostic_t diag_kind); + +} // namespace Resolver +} // namespace Rust + +#endif /* ! RUST_ICE_FINALIZER_H */ diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 13b1dd8a094b..e991a75c2c3a 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -27,7 +27,7 @@ #include "rust-system.h" #include "rust-tyty.h" #include "rust-hir-type-check.h" -#include "diagnostic.h" +#include "rust-ice-finalizer.h" namespace Rust { namespace Resolver2_0 { @@ -206,45 +206,6 @@ Late::visit (AST::BreakExpr &expr) funny_error = false; } -/* The "break rust" Easter egg. - - Backstory: once upon a time, there used to be a bug in rustc: it would ICE - during typechecking on a 'break' with an expression outside of a loop. The - issue has been reported [0] and fixed [1], but in recognition of this, as a - special Easter egg, "break rust" was made to intentionally cause an ICE. - - [0]: https://github.com/rust-lang/rust/issues/43162 - [1]: https://github.com/rust-lang/rust/pull/43745 - - This was made in a way that does not break valid programs: namely, it only - happens when the 'break' is outside of a loop (so invalid anyway). - - GCC Rust supports this essential feature as well, but in a slightly - different way. Instead of delaying the error until type checking, we emit - it here in the resolution phase. We, too, only do this to programs that - are already invalid: we only emit our funny ICE if the name "rust" (which - must be immediately inside a break-with-a-value expression) fails to - resolve. Note that "break (rust)" does not trigger our ICE, only using - "break rust" directly does, and only if there's no "rust" in scope. We do - this in the same way regardless of whether the "break" is outside of a loop - or inside one. - - As a GNU extension, we also support "break gcc", much to the same effect, - subject to the same rules. */ - -/* The finalizer for our funny ICE. This prints a custom message instead of - the default bug reporting instructions, as there is no bug to report. */ - -static void ATTRIBUTE_NORETURN -funny_ice_finalizer (diagnostic_context *context, - const diagnostic_info *diagnostic, diagnostic_t diag_kind) -{ - gcc_assert (diag_kind == DK_ICE_NOBT); - default_diagnostic_finalizer (context, diagnostic, diag_kind); - fnotice (stderr, "You have broken GCC Rust. This is a feature.\n"); - exit (ICE_EXIT_CODE); -} - void Late::visit (AST::IdentifierExpr &expr) { @@ -262,7 +223,7 @@ Late::visit (AST::IdentifierExpr &expr) } else if (funny_error) { - diagnostic_finalizer (global_dc) = funny_ice_finalizer; + diagnostic_finalizer (global_dc) = Resolver::funny_ice_finalizer; emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1, "are you trying to break %s? how dare you?", expr.as_string ().c_str ());