diff options
Diffstat (limited to 'gcc/rust/checks')
35 files changed, 1712 insertions, 875 deletions
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index e2cc2dd..de8a830 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -24,7 +24,6 @@ #include "rust-hir-item.h" #include "rust-hir-type-check.h" #include "rust-hir-visitor.h" -#include "rust-name-resolver.h" #include "rust-bir.h" #include "rust-bir-free-region.h" #include "rust-immutable-name-resolution-context.h" @@ -75,7 +74,7 @@ struct BuilderContext // External context. Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; // BIR output BasicBlocks basic_blocks; @@ -104,7 +103,7 @@ struct BuilderContext public: BuilderContext () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()) + resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()) { basic_blocks.emplace_back (); // StartBB } @@ -403,69 +402,31 @@ protected: // HIR resolution helpers template <typename T> NodeId resolve_label (T &expr) { - NodeId resolved_label; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - resolved_label = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_label ( - expr.get_mappings ().get_nodeid (), &resolved_label); - rust_assert (ok); - } - return resolved_label; + auto res = ctx.resolver.lookup (expr.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return res.value (); } template <typename T> PlaceId resolve_variable (T &variable) { - NodeId variable_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - variable_id = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); - } - return ctx.place_db.lookup_variable (variable_id); + auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return ctx.place_db.lookup_variable (res.value ()); } template <typename T> PlaceId resolve_variable_or_fn (T &variable, TyTy::BaseType *ty) { ty = (ty) ? ty : lookup_type (variable); + // Unlike variables, // functions do not have to be declared in PlaceDB before use. - NodeId variable_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - variable_id = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); - } if (ty->is<TyTy::FnType> ()) return ctx.place_db.get_constant (ty); - else - return ctx.place_db.lookup_or_add_variable (variable_id, ty); + + auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return ctx.place_db.lookup_or_add_variable (res.value (), ty); } protected: // Implicit conversions. diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc index 2d655f9..e78d750 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc @@ -70,11 +70,34 @@ PatternBindingBuilder::visit (HIR::SlicePattern &pattern) return ty->as<TyTy::SliceType> ()->get_element_type (); }); - // Regions are unchnaged. + // Regions are unchanged. - for (auto &item : pattern.get_items ()) + switch (pattern.get_items ().get_item_type ()) { - item->accept_vis (*this); + case HIR::SlicePatternItems::NO_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &member : items.get_patterns ()) + { + member->accept_vis (*this); + } + break; + } + case HIR::SlicePatternItems::HAS_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (auto &member : items.get_lower_patterns ()) + { + member->accept_vis (*this); + } + for (auto &member : items.get_upper_patterns ()) + { + member->accept_vis (*this); + } + break; + } } } @@ -202,17 +225,17 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::MULTIPLE: + case HIR::TuplePatternItems::NO_REST: { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } - case HIR::TuplePatternItems::RANGED: + case HIR::TuplePatternItems::HAS_REST: { auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); auto tyty = ctx.place_db[init.value ()].tyty; rust_assert (tyty->get_kind () == TyTy::TUPLE); @@ -249,10 +272,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { auto &items - = static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ()); + = static_cast<HIR::TupleStructItemsHasRest &> (pattern.get_items ()); rust_assert (type->get_kind () == TyTy::ADT); auto adt_ty = static_cast<TyTy::ADTType *> (type); @@ -267,10 +290,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) visit_tuple_fields (items.get_upper_patterns (), saved, index); break; } - case HIR::TupleStructItems::MULTIPLE: + case HIR::TupleStructItems::NO_REST: { auto &items - = static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ()); + = static_cast<HIR::TupleStructItemsNoRest &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h index d87ff8c..6cb87c7 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h @@ -225,11 +225,11 @@ protected: rust_unreachable (); } void visit (HIR::StructPattern &pattern) override { rust_unreachable (); } - void visit (HIR::TupleStructItemsNoRange &tuple_items) override + void visit (HIR::TupleStructItemsNoRest &tuple_items) override { rust_unreachable (); } - void visit (HIR::TupleStructItemsRange &tuple_items) override + void visit (HIR::TupleStructItemsHasRest &tuple_items) override { rust_unreachable (); } @@ -237,15 +237,23 @@ protected: { rust_unreachable (); } - void visit (HIR::TuplePatternItemsMultiple &tuple_items) override + void visit (HIR::TuplePatternItemsNoRest &tuple_items) override { rust_unreachable (); } - void visit (HIR::TuplePatternItemsRanged &tuple_items) override + void visit (HIR::TuplePatternItemsHasRest &tuple_items) override { rust_unreachable (); } void visit (HIR::TuplePattern &pattern) override { rust_unreachable (); } + void visit (HIR::SlicePatternItemsNoRest &tuple_items) override + { + rust_unreachable (); + } + void visit (HIR::SlicePatternItemsHasRest &tuple_items) override + { + rust_unreachable (); + } void visit (HIR::SlicePattern &pattern) override { rust_unreachable (); } void visit (HIR::AltPattern &pattern) override { rust_unreachable (); } void visit (HIR::EmptyStmt &stmt) override { rust_unreachable (); } diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h index 86f96c1..63f2a95 100644 --- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h @@ -170,12 +170,14 @@ public: void visit (HIR::StructPatternFieldIdentPat &field) override {} void visit (HIR::StructPatternFieldIdent &field) override {} void visit (HIR::StructPattern &pattern) override {} - void visit (HIR::TupleStructItemsNoRange &tuple_items) override {} - void visit (HIR::TupleStructItemsRange &tuple_items) override {} + void visit (HIR::TupleStructItemsNoRest &tuple_items) override {} + void visit (HIR::TupleStructItemsHasRest &tuple_items) override {} void visit (HIR::TupleStructPattern &pattern) override {} - void visit (HIR::TuplePatternItemsMultiple &tuple_items) override {} - void visit (HIR::TuplePatternItemsRanged &tuple_items) override {} + void visit (HIR::TuplePatternItemsNoRest &tuple_items) override {} + void visit (HIR::TuplePatternItemsHasRest &tuple_items) override {} void visit (HIR::TuplePattern &pattern) override {} + void visit (HIR::SlicePatternItemsNoRest &tuple_items) override {} + void visit (HIR::SlicePatternItemsHasRest &tuple_items) override {} void visit (HIR::SlicePattern &pattern) override {} void visit (HIR::AltPattern &pattern) override {} void visit (HIR::EmptyStmt &stmt) override {} diff --git a/gcc/rust/checks/errors/feature/contrib/.gitignore b/gcc/rust/checks/errors/feature/contrib/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/.gitignore @@ -0,0 +1 @@ +/build diff --git a/gcc/rust/checks/errors/feature/contrib/Makefile b/gcc/rust/checks/errors/feature/contrib/Makefile new file mode 100644 index 0000000..7c828ab --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/Makefile @@ -0,0 +1,59 @@ +# Copyright (C) 2025 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 +# <http://www.gnu.org/licenses/>. + +OUT = ../rust-feature-defs.h + +all: $(OUT) + +mk-build-dir: + mkdir -p build + +build/parse.c: parse.y mk-build-dir + $(YACC) $(YFLAGS) -o $@ --defines=build/parse.h $< + +build/parse.h: build/parse.c; + +build/scan.c: scan.l + $(LEX) $(LFLAGS) -o $@ -Ca --header-file=build/scan.h $< + +build/scan.h: build/scan.c; + +build/%.o: build/%.c build/parse.h build/scan.h + $(CC) $(CFLAGS) -c -Ibuild -o $@ $< + +build/feature-extract: build/parse.o build/scan.o + $(CC) $(LDFLAGS) $(LDLIBS) -o $@ $^ + +build/download.rs: fetch + ./$< $@ + +$(OUT): build/feature-extract build/download.rs + # add copyright header + newline + echo | \ + cat copyright-stub.h - | \ + sed "s/YYYY/$$(date +%Y)/" > build/rust-feature-defs.h + cat build/download.rs | ./$< >> build/rust-feature-defs.h + clang-format -i build/rust-feature-defs.h \ + --style=file:../../../../../../contrib/clang-format + mv build/rust-feature-defs.h $(OUT) + +clean: + $(RM) -r build + +clean-all: clean + $(RM) $(OUT) diff --git a/gcc/rust/checks/errors/feature/contrib/README b/gcc/rust/checks/errors/feature/contrib/README new file mode 100644 index 0000000..e85fe09 --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/README @@ -0,0 +1,3 @@ +This program is intended for use in generating rust-feature-defs.h + +To use, run `./regen` diff --git a/gcc/rust/checks/errors/feature/contrib/copyright-stub.h b/gcc/rust/checks/errors/feature/contrib/copyright-stub.h new file mode 100644 index 0000000..1a5f52c --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/copyright-stub.h @@ -0,0 +1,19 @@ +// Copyright (C) YYYY 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 +// <http://www.gnu.org/licenses/>. + +// AUTO-GENERATED -- SEE LOCAL contrib SUBDIRECTORY diff --git a/gcc/rust/checks/errors/feature/contrib/fetch b/gcc/rust/checks/errors/feature/contrib/fetch new file mode 100755 index 0000000..b26ed3c --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/fetch @@ -0,0 +1,30 @@ +#!/bin/sh + +# Copyright (C) 2025 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 +# <http://www.gnu.org/licenses/>. + +RUST_VERSION="1.49.0" + +[ $# = 1 ] || exit 1 + +# Fetches files from the official rustc git repository + +URL_PREFIX='https://raw.githubusercontent.com/rust-lang/rust/refs/tags' +URL_TEMPLATE="$URL_PREFIX/$RUST_VERSION/compiler/rustc_feature/src" + +wget -O $1 "$URL_TEMPLATE"/{accepted,active,removed}.rs diff --git a/gcc/rust/checks/errors/feature/contrib/parse.y b/gcc/rust/checks/errors/feature/contrib/parse.y new file mode 100644 index 0000000..34c0138 --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/parse.y @@ -0,0 +1,143 @@ +/* Copyright (C) 2025 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 +<http://www.gnu.org/licenses/>. */ + +%{ + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +int yylex (void); +void yyerror (char const *); + +#include "scan.h" + +// expands to three %s parameters +#define UNWRAP_OPT_STR(prefix, s) (s ? prefix "_SOME (" : prefix "_NONE"), (s ? s : ""), (s ? ")" : "") + +%} + +%union +{ + char *str; +}; + +%token <str> IDENT STR NUM +%token SCOPE +%token K_SOME K_NONE +%token K_ACTIVE K_ACCEPTED K_REMOVED K_STABLE_REMOVED +%token K_E_START K_E_2018 + +%type <str> issue +%type <str> edition +%type <str> reason + +%% + +multi_database: multi_database database +| database +; + +database: '(' entry_list ')'; + +entry_list: entry_list entry ',' +| entry ',' +; + +entry: '(' K_ACTIVE ',' IDENT ',' STR ',' issue ',' edition ')' { + char *ident_upper = strdup ($4); + for (size_t i = 0; ident_upper[i]; i++) + ident_upper[i] = toupper (ident_upper[i]); + printf ("FEATURE_ACTIVE (\"%s\", %s, %s, %s%s%s, EDITION_%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8), $10 ? $10 : "NONE"); + free ($4); + free (ident_upper); + free ($6); + free ($8); +} +| '(' K_ACCEPTED ',' IDENT ',' STR ',' issue ',' K_NONE ')' { + char *ident_upper = strdup ($4); + for (size_t i = 0; ident_upper[i]; i++) + ident_upper[i] = toupper (ident_upper[i]); + printf ("FEATURE_ACCEPTED (\"%s\", %s, %s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8)); + free ($4); + free (ident_upper); + free ($6); + free ($8); +} +| '(' K_REMOVED ',' IDENT ',' STR ',' issue ',' K_NONE ',' reason ')' { + char *ident_upper; + // HACK: convert no_debug to F_NO_DEBUG instead + // since NO_DEBUG is used as an unrelated macro + if (!strcmp ($4, "no_debug")) + { + ident_upper = strdup ("F_NO_DEBUG"); + } + else + { + ident_upper = strdup ($4); + for (size_t i = 0; ident_upper[i]; i++) + ident_upper[i] = toupper (ident_upper[i]); + } + printf ("FEATURE_REMOVED (\"%s\", %s, %s, %s%s%s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8), UNWRAP_OPT_STR ("REASON", $12)); + free ($4); + free (ident_upper); + free ($6); + free ($8); + free ($12); +} +| '(' K_STABLE_REMOVED ',' IDENT ',' STR ',' issue ',' K_NONE ')' { + char *ident_upper = strdup ($4); + for (size_t i = 0; ident_upper[i]; i++) + ident_upper[i] = toupper (ident_upper[i]); + printf ("FEATURE_STABLE_REMOVED (\"%s\", %s, %s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8)); + free ($4); + free (ident_upper); + free ($6); + free ($8); +} +; + +issue: K_SOME '(' NUM ')' { $$ = $3; } +| K_NONE { $$ = NULL; } +; + +/* TODO: expand this as needed */ +edition: K_NONE { $$ = NULL; } +| K_SOME '(' K_E_START SCOPE K_E_2018 ')' { $$ = "2018"; } +; + +reason: K_SOME '(' STR ')' { $$ = $3; } +| K_NONE { $$ = NULL; } +; + +%% + +void yyerror (const char *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int yywrap (void) +{ + return 1; +} + +int main (void) +{ + return yyparse (); +} diff --git a/gcc/rust/checks/errors/feature/contrib/regen b/gcc/rust/checks/errors/feature/contrib/regen new file mode 100755 index 0000000..0dc6cc5 --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/regen @@ -0,0 +1,23 @@ +#!/bin/sh + +# Copyright (C) 2025 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 +# <http://www.gnu.org/licenses/>. + +cd "$(dirname "$0")" +rm -f ../rust-feature-defs.h +make all diff --git a/gcc/rust/checks/errors/feature/contrib/scan.l b/gcc/rust/checks/errors/feature/contrib/scan.l new file mode 100644 index 0000000..768f4c7 --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/scan.l @@ -0,0 +1,55 @@ +/* Copyright (C) 2025 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 +<http://www.gnu.org/licenses/>. */ + +%{ + +#include "parse.h" + +static int p_count = 0; + +%} + +%x INSIDE COMMENT + +%% + +declare_features! BEGIN (INSIDE); +.|\n /* ignore */ + +<INSIDE>\( p_count++; return '('; +<INSIDE>\) if (!--p_count) { BEGIN (0); } return ')'; +<INSIDE>, return ','; +<INSIDE>:: return SCOPE; +<INSIDE>Some return K_SOME; +<INSIDE>None return K_NONE; +<INSIDE>active return K_ACTIVE; +<INSIDE>accepted return K_ACCEPTED; +<INSIDE>removed return K_REMOVED; +<INSIDE>stable_removed return K_STABLE_REMOVED; +<INSIDE>Edition return K_E_START; +<INSIDE>Edition2018 return K_E_2018; + +<INSIDE>[A-Za-z_][A-Za-z0-9_]* yylval.str = strdup (yytext); return IDENT; +<INSIDE>[1-9][0-9]* yylval.str = strdup (yytext); return NUM; +<INSIDE>\"[^"]+\" yylval.str = strdup (yytext); return STR; +<INSIDE>"/""/" BEGIN (COMMENT); +<INSIDE>[ \n] /* ignore */ +<INSIDE>. { fprintf (stderr, "unrecognized character %u\n", (unsigned int) yytext[0]); exit (1); } + +<COMMENT>. /* skip */ +<COMMENT>\n BEGIN (INSIDE); diff --git a/gcc/rust/checks/errors/feature/rust-feature-defs.h b/gcc/rust/checks/errors/feature/rust-feature-defs.h new file mode 100644 index 0000000..d8514e1 --- /dev/null +++ b/gcc/rust/checks/errors/feature/rust-feature-defs.h @@ -0,0 +1,600 @@ +// Copyright (C) 2025 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 +// <http://www.gnu.org/licenses/>. + +// AUTO-GENERATED -- SEE LOCAL contrib SUBDIRECTORY + +FEATURE_ACCEPTED ("issue_5723_bootstrap", ISSUE_5723_BOOTSTRAP, "1.0.0", + ISSUE_NONE) +FEATURE_ACCEPTED ("test_accepted_feature", TEST_ACCEPTED_FEATURE, "1.0.0", + ISSUE_NONE) +FEATURE_ACCEPTED ("associated_types", ASSOCIATED_TYPES, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("default_type_params", DEFAULT_TYPE_PARAMS, "1.0.0", + ISSUE_NONE) +FEATURE_ACCEPTED ("globs", GLOBS, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("macro_rules", MACRO_RULES, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("slicing_syntax", SLICING_SYNTAX, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("struct_variant", STRUCT_VARIANT, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("tuple_indexing", TUPLE_INDEXING, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("if_let", IF_LET, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("while_let", WHILE_LET, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("no_std", NO_STD, "1.6.0", ISSUE_NONE) +FEATURE_ACCEPTED ("augmented_assignments", AUGMENTED_ASSIGNMENTS, "1.8.0", + ISSUE_SOME (28235)) +FEATURE_ACCEPTED ("braced_empty_structs", BRACED_EMPTY_STRUCTS, "1.8.0", + ISSUE_SOME (29720)) +FEATURE_ACCEPTED ("deprecated", DEPRECATED, "1.9.0", ISSUE_SOME (29935)) +FEATURE_ACCEPTED ("type_macros", TYPE_MACROS, "1.13.0", ISSUE_SOME (27245)) +FEATURE_ACCEPTED ("question_mark", QUESTION_MARK, "1.13.0", ISSUE_SOME (31436)) +FEATURE_ACCEPTED ("dotdot_in_tuple_patterns", DOTDOT_IN_TUPLE_PATTERNS, + "1.14.0", ISSUE_SOME (33627)) +FEATURE_ACCEPTED ("item_like_imports", ITEM_LIKE_IMPORTS, "1.15.0", + ISSUE_SOME (35120)) +FEATURE_ACCEPTED ("more_struct_aliases", MORE_STRUCT_ALIASES, "1.16.0", + ISSUE_SOME (37544)) +FEATURE_ACCEPTED ("static_in_const", STATIC_IN_CONST, "1.17.0", + ISSUE_SOME (35897)) +FEATURE_ACCEPTED ("field_init_shorthand", FIELD_INIT_SHORTHAND, "1.17.0", + ISSUE_SOME (37340)) +FEATURE_ACCEPTED ("static_recursion", STATIC_RECURSION, "1.17.0", + ISSUE_SOME (29719)) +FEATURE_ACCEPTED ("pub_restricted", PUB_RESTRICTED, "1.18.0", + ISSUE_SOME (32409)) +FEATURE_ACCEPTED ("windows_subsystem", WINDOWS_SUBSYSTEM, "1.18.0", + ISSUE_SOME (37499)) +FEATURE_ACCEPTED ("loop_break_value", LOOP_BREAK_VALUE, "1.19.0", + ISSUE_SOME (37339)) +FEATURE_ACCEPTED ("relaxed_adts", RELAXED_ADTS, "1.19.0", ISSUE_SOME (35626)) +FEATURE_ACCEPTED ("closure_to_fn_coercion", CLOSURE_TO_FN_COERCION, "1.19.0", + ISSUE_SOME (39817)) +FEATURE_ACCEPTED ("struct_field_attributes", STRUCT_FIELD_ATTRIBUTES, "1.20.0", + ISSUE_SOME (38814)) +FEATURE_ACCEPTED ("associated_consts", ASSOCIATED_CONSTS, "1.20.0", + ISSUE_SOME (29646)) +FEATURE_ACCEPTED ("compile_error", COMPILE_ERROR, "1.20.0", ISSUE_SOME (40872)) +FEATURE_ACCEPTED ("rvalue_static_promotion", RVALUE_STATIC_PROMOTION, "1.21.0", + ISSUE_SOME (38865)) +FEATURE_ACCEPTED ("drop_types_in_const", DROP_TYPES_IN_CONST, "1.22.0", + ISSUE_SOME (33156)) +FEATURE_ACCEPTED ("abi_sysv64", ABI_SYSV64, "1.24.0", ISSUE_SOME (36167)) +FEATURE_ACCEPTED ("repr_align", REPR_ALIGN, "1.25.0", ISSUE_SOME (33626)) +FEATURE_ACCEPTED ("match_beginning_vert", MATCH_BEGINNING_VERT, "1.25.0", + ISSUE_SOME (44101)) +FEATURE_ACCEPTED ("use_nested_groups", USE_NESTED_GROUPS, "1.25.0", + ISSUE_SOME (44494)) +FEATURE_ACCEPTED ("const_indexing", CONST_INDEXING, "1.26.0", + ISSUE_SOME (29947)) +FEATURE_ACCEPTED ("inclusive_range_syntax", INCLUSIVE_RANGE_SYNTAX, "1.26.0", + ISSUE_SOME (28237)) +FEATURE_ACCEPTED ("dotdoteq_in_patterns", DOTDOTEQ_IN_PATTERNS, "1.26.0", + ISSUE_SOME (28237)) +FEATURE_ACCEPTED ("termination_trait", TERMINATION_TRAIT, "1.26.0", + ISSUE_SOME (43301)) +FEATURE_ACCEPTED ("clone_closures", CLONE_CLOSURES, "1.26.0", + ISSUE_SOME (44490)) +FEATURE_ACCEPTED ("copy_closures", COPY_CLOSURES, "1.26.0", ISSUE_SOME (44490)) +FEATURE_ACCEPTED ("universal_impl_trait", UNIVERSAL_IMPL_TRAIT, "1.26.0", + ISSUE_SOME (34511)) +FEATURE_ACCEPTED ("conservative_impl_trait", CONSERVATIVE_IMPL_TRAIT, "1.26.0", + ISSUE_SOME (34511)) +FEATURE_ACCEPTED ("i128_type", I128_TYPE, "1.26.0", ISSUE_SOME (35118)) +FEATURE_ACCEPTED ("match_default_bindings", MATCH_DEFAULT_BINDINGS, "1.26.0", + ISSUE_SOME (42640)) +FEATURE_ACCEPTED ("underscore_lifetimes", UNDERSCORE_LIFETIMES, "1.26.0", + ISSUE_SOME (44524)) +FEATURE_ACCEPTED ("generic_param_attrs", GENERIC_PARAM_ATTRS, "1.27.0", + ISSUE_SOME (48848)) +FEATURE_ACCEPTED ("cfg_target_feature", CFG_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (29717)) +FEATURE_ACCEPTED ("target_feature", TARGET_FEATURE, "1.27.0", ISSUE_NONE) +FEATURE_ACCEPTED ("dyn_trait", DYN_TRAIT, "1.27.0", ISSUE_SOME (44662)) +FEATURE_ACCEPTED ("fn_must_use", FN_MUST_USE, "1.27.0", ISSUE_SOME (43302)) +FEATURE_ACCEPTED ("macro_lifetime_matcher", MACRO_LIFETIME_MATCHER, "1.27.0", + ISSUE_SOME (34303)) +FEATURE_ACCEPTED ("termination_trait_test", TERMINATION_TRAIT_TEST, "1.27.0", + ISSUE_SOME (48854)) +FEATURE_ACCEPTED ("global_allocator", GLOBAL_ALLOCATOR, "1.28.0", + ISSUE_SOME (27389)) +FEATURE_ACCEPTED ("repr_transparent", REPR_TRANSPARENT, "1.28.0", + ISSUE_SOME (43036)) +FEATURE_ACCEPTED ("proc_macro", PROC_MACRO, "1.29.0", ISSUE_SOME (38356)) +FEATURE_ACCEPTED ("non_modrs_mods", NON_MODRS_MODS, "1.30.0", + ISSUE_SOME (44660)) +FEATURE_ACCEPTED ("macro_vis_matcher", MACRO_VIS_MATCHER, "1.30.0", + ISSUE_SOME (41022)) +FEATURE_ACCEPTED ("use_extern_macros", USE_EXTERN_MACROS, "1.30.0", + ISSUE_SOME (35896)) +FEATURE_ACCEPTED ("raw_identifiers", RAW_IDENTIFIERS, "1.30.0", + ISSUE_SOME (48589)) +FEATURE_ACCEPTED ("tool_attributes", TOOL_ATTRIBUTES, "1.30.0", + ISSUE_SOME (44690)) +FEATURE_ACCEPTED ("proc_macro_path_invoc", PROC_MACRO_PATH_INVOC, "1.30.0", + ISSUE_SOME (38356)) +FEATURE_ACCEPTED ("attr_literals", ATTR_LITERALS, "1.30.0", ISSUE_SOME (34981)) +FEATURE_ACCEPTED ("infer_outlives_requirements", INFER_OUTLIVES_REQUIREMENTS, + "1.30.0", ISSUE_SOME (44493)) +FEATURE_ACCEPTED ("panic_handler", PANIC_HANDLER, "1.30.0", ISSUE_SOME (44489)) +FEATURE_ACCEPTED ("used", USED, "1.30.0", ISSUE_SOME (40289)) +FEATURE_ACCEPTED ("crate_in_paths", CRATE_IN_PATHS, "1.30.0", + ISSUE_SOME (45477)) +FEATURE_ACCEPTED ("extern_absolute_paths", EXTERN_ABSOLUTE_PATHS, "1.30.0", + ISSUE_SOME (44660)) +FEATURE_ACCEPTED ("extern_prelude", EXTERN_PRELUDE, "1.30.0", + ISSUE_SOME (44660)) +FEATURE_ACCEPTED ("pattern_parentheses", PATTERN_PARENTHESES, "1.31.0", + ISSUE_SOME (51087)) +FEATURE_ACCEPTED ("min_const_fn", MIN_CONST_FN, "1.31.0", ISSUE_SOME (53555)) +FEATURE_ACCEPTED ("tool_lints", TOOL_LINTS, "1.31.0", ISSUE_SOME (44690)) +FEATURE_ACCEPTED ("impl_header_lifetime_elision", IMPL_HEADER_LIFETIME_ELISION, + "1.31.0", ISSUE_SOME (15872)) +FEATURE_ACCEPTED ("extern_crate_item_prelude", EXTERN_CRATE_ITEM_PRELUDE, + "1.31.0", ISSUE_SOME (55599)) +FEATURE_ACCEPTED ("macro_literal_matcher", MACRO_LITERAL_MATCHER, "1.32.0", + ISSUE_SOME (35625)) +FEATURE_ACCEPTED ("macro_at_most_once_rep", MACRO_AT_MOST_ONCE_REP, "1.32.0", + ISSUE_SOME (48075)) +FEATURE_ACCEPTED ("self_struct_ctor", SELF_STRUCT_CTOR, "1.32.0", + ISSUE_SOME (51994)) +FEATURE_ACCEPTED ("self_in_typedefs", SELF_IN_TYPEDEFS, "1.32.0", + ISSUE_SOME (49303)) +FEATURE_ACCEPTED ("uniform_paths", UNIFORM_PATHS, "1.32.0", ISSUE_SOME (53130)) +FEATURE_ACCEPTED ("exhaustive_integer_patterns", EXHAUSTIVE_INTEGER_PATTERNS, + "1.33.0", ISSUE_SOME (50907)) +FEATURE_ACCEPTED ("underscore_imports", UNDERSCORE_IMPORTS, "1.33.0", + ISSUE_SOME (48216)) +FEATURE_ACCEPTED ("repr_packed", REPR_PACKED, "1.33.0", ISSUE_SOME (33158)) +FEATURE_ACCEPTED ("irrefutable_let_patterns", IRREFUTABLE_LET_PATTERNS, + "1.33.0", ISSUE_SOME (44495)) +FEATURE_ACCEPTED ("min_const_unsafe_fn", MIN_CONST_UNSAFE_FN, "1.33.0", + ISSUE_SOME (55607)) +FEATURE_ACCEPTED ("const_let", CONST_LET, "1.33.0", ISSUE_SOME (48821)) +FEATURE_ACCEPTED ("cfg_attr_multi", CFG_ATTR_MULTI, "1.33.0", + ISSUE_SOME (54881)) +FEATURE_ACCEPTED ("if_while_or_patterns", IF_WHILE_OR_PATTERNS, "1.33.0", + ISSUE_SOME (48215)) +FEATURE_ACCEPTED ("cfg_target_vendor", CFG_TARGET_VENDOR, "1.33.0", + ISSUE_SOME (29718)) +FEATURE_ACCEPTED ("extern_crate_self", EXTERN_CRATE_SELF, "1.34.0", + ISSUE_SOME (56409)) +FEATURE_ACCEPTED ("unrestricted_attribute_tokens", + UNRESTRICTED_ATTRIBUTE_TOKENS, "1.34.0", ISSUE_SOME (55208)) +FEATURE_ACCEPTED ("type_alias_enum_variants", TYPE_ALIAS_ENUM_VARIANTS, + "1.37.0", ISSUE_SOME (49683)) +FEATURE_ACCEPTED ("repr_align_enum", REPR_ALIGN_ENUM, "1.37.0", + ISSUE_SOME (57996)) +FEATURE_ACCEPTED ("underscore_const_names", UNDERSCORE_CONST_NAMES, "1.37.0", + ISSUE_SOME (54912)) +FEATURE_ACCEPTED ("async_await", ASYNC_AWAIT, "1.39.0", ISSUE_SOME (50547)) +FEATURE_ACCEPTED ("bind_by_move_pattern_guards", BIND_BY_MOVE_PATTERN_GUARDS, + "1.39.0", ISSUE_SOME (15287)) +FEATURE_ACCEPTED ("param_attrs", PARAM_ATTRS, "1.39.0", ISSUE_SOME (60406)) +FEATURE_ACCEPTED ("macros_in_extern", MACROS_IN_EXTERN, "1.40.0", + ISSUE_SOME (49476)) +FEATURE_ACCEPTED ("non_exhaustive", NON_EXHAUSTIVE, "1.40.0", + ISSUE_SOME (44109)) +FEATURE_ACCEPTED ("const_constructor", CONST_CONSTRUCTOR, "1.40.0", + ISSUE_SOME (61456)) +FEATURE_ACCEPTED ("cfg_doctest", CFG_DOCTEST, "1.40.0", ISSUE_SOME (62210)) +FEATURE_ACCEPTED ("re_rebalance_coherence", RE_REBALANCE_COHERENCE, "1.41.0", + ISSUE_SOME (55437)) +FEATURE_ACCEPTED ("transparent_enums", TRANSPARENT_ENUMS, "1.42.0", + ISSUE_SOME (60405)) +FEATURE_ACCEPTED ("slice_patterns", SLICE_PATTERNS, "1.42.0", + ISSUE_SOME (62254)) +FEATURE_ACCEPTED ("const_if_match", CONST_IF_MATCH, "1.46.0", + ISSUE_SOME (49146)) +FEATURE_ACCEPTED ("const_loop", CONST_LOOP, "1.46.0", ISSUE_SOME (52000)) +FEATURE_ACCEPTED ("track_caller", TRACK_CALLER, "1.46.0", ISSUE_SOME (47809)) +FEATURE_ACCEPTED ("doc_alias", DOC_ALIAS, "1.48.0", ISSUE_SOME (50146)) +FEATURE_ACCEPTED ("move_ref_pattern", MOVE_REF_PATTERN, "1.48.0", + ISSUE_SOME (68354)) +FEATURE_ACTIVE ("rustc_attrs", RUSTC_ATTRS, "1.0.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("rustc_private", RUSTC_PRIVATE, "1.0.0", ISSUE_SOME (27812), + EDITION_NONE) +FEATURE_ACTIVE ("intrinsics", INTRINSICS, "1.0.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("lang_items", LANG_ITEMS, "1.0.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("staged_api", STAGED_API, "1.0.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("allow_internal_unstable", ALLOW_INTERNAL_UNSTABLE, "1.0.0", + ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("allow_internal_unsafe", ALLOW_INTERNAL_UNSAFE, "1.0.0", + ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("link_llvm_intrinsics", LINK_LLVM_INTRINSICS, "1.0.0", + ISSUE_SOME (29602), EDITION_NONE) +FEATURE_ACTIVE ("box_syntax", BOX_SYNTAX, "1.0.0", ISSUE_SOME (49733), + EDITION_NONE) +FEATURE_ACTIVE ("main", MAIN, "1.0.0", ISSUE_SOME (29634), EDITION_NONE) +FEATURE_ACTIVE ("start", START, "1.0.0", ISSUE_SOME (29633), EDITION_NONE) +FEATURE_ACTIVE ("fundamental", FUNDAMENTAL, "1.0.0", ISSUE_SOME (29635), + EDITION_NONE) +FEATURE_ACTIVE ("unboxed_closures", UNBOXED_CLOSURES, "1.0.0", + ISSUE_SOME (29625), EDITION_NONE) +FEATURE_ACTIVE ("linkage", LINKAGE, "1.0.0", ISSUE_SOME (29603), EDITION_NONE) +FEATURE_ACTIVE ("optin_builtin_traits", OPTIN_BUILTIN_TRAITS, "1.0.0", + ISSUE_SOME (13231), EDITION_NONE) +FEATURE_ACTIVE ("box_patterns", BOX_PATTERNS, "1.0.0", ISSUE_SOME (29641), + EDITION_NONE) +FEATURE_ACTIVE ("prelude_import", PRELUDE_IMPORT, "1.2.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("omit_gdb_pretty_printer_section", + OMIT_GDB_PRETTY_PRINTER_SECTION, "1.5.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("abi_vectorcall", ABI_VECTORCALL, "1.7.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("structural_match", STRUCTURAL_MATCH, "1.8.0", + ISSUE_SOME (31434), EDITION_NONE) +FEATURE_ACTIVE ("dropck_eyepatch", DROPCK_EYEPATCH, "1.10.0", + ISSUE_SOME (34761), EDITION_NONE) +FEATURE_ACTIVE ("panic_runtime", PANIC_RUNTIME, "1.10.0", ISSUE_SOME (32837), + EDITION_NONE) +FEATURE_ACTIVE ("needs_panic_runtime", NEEDS_PANIC_RUNTIME, "1.10.0", + ISSUE_SOME (32837), EDITION_NONE) +FEATURE_ACTIVE ("compiler_builtins", COMPILER_BUILTINS, "1.13.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("abi_unadjusted", ABI_UNADJUSTED, "1.16.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("profiler_runtime", PROFILER_RUNTIME, "1.18.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("abi_thiscall", ABI_THISCALL, "1.19.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("allocator_internals", ALLOCATOR_INTERNALS, "1.20.0", + ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("test_2018_feature", TEST_2018_FEATURE, "1.31.0", ISSUE_NONE, + EDITION_2018) +FEATURE_ACTIVE ("no_niche", NO_NICHE, "1.42.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("rustc_allow_const_fn_unstable", RUSTC_ALLOW_CONST_FN_UNSTABLE, + "1.49.0", ISSUE_SOME (69399), EDITION_NONE) +FEATURE_ACTIVE ("arm_target_feature", ARM_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("aarch64_target_feature", AARCH64_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("hexagon_target_feature", HEXAGON_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("powerpc_target_feature", POWERPC_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("mips_target_feature", MIPS_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("avx512_target_feature", AVX512_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("sse4a_target_feature", SSE4A_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("tbm_target_feature", TBM_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("wasm_target_feature", WASM_TARGET_FEATURE, "1.30.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("adx_target_feature", ADX_TARGET_FEATURE, "1.32.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("cmpxchg16b_target_feature", CMPXCHG16B_TARGET_FEATURE, + "1.32.0", ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("movbe_target_feature", MOVBE_TARGET_FEATURE, "1.34.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("rtm_target_feature", RTM_TARGET_FEATURE, "1.35.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("f16c_target_feature", F16C_TARGET_FEATURE, "1.36.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("riscv_target_feature", RISCV_TARGET_FEATURE, "1.45.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("ermsb_target_feature", ERMSB_TARGET_FEATURE, "1.49.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("link_args", LINK_ARGS, "1.0.0", ISSUE_SOME (29596), + EDITION_NONE) +FEATURE_ACTIVE ("non_ascii_idents", NON_ASCII_IDENTS, "1.0.0", + ISSUE_SOME (55467), EDITION_NONE) +FEATURE_ACTIVE ("plugin_registrar", PLUGIN_REGISTRAR, "1.0.0", + ISSUE_SOME (29597), EDITION_NONE) +FEATURE_ACTIVE ("plugin", PLUGIN, "1.0.0", ISSUE_SOME (29597), EDITION_NONE) +FEATURE_ACTIVE ("thread_local", THREAD_LOCAL, "1.0.0", ISSUE_SOME (29594), + EDITION_NONE) +FEATURE_ACTIVE ("simd_ffi", SIMD_FFI, "1.0.0", ISSUE_SOME (27731), EDITION_NONE) +FEATURE_ACTIVE ("nll", NLL, "1.0.0", ISSUE_SOME (43234), EDITION_NONE) +FEATURE_ACTIVE ("const_fn", CONST_FN, "1.2.0", ISSUE_SOME (57563), EDITION_NONE) +FEATURE_ACTIVE ("associated_type_defaults", ASSOCIATED_TYPE_DEFAULTS, "1.2.0", + ISSUE_SOME (29661), EDITION_NONE) +FEATURE_ACTIVE ("no_core", NO_CORE, "1.3.0", ISSUE_SOME (29639), EDITION_NONE) +FEATURE_ACTIVE ("default_type_parameter_fallback", + DEFAULT_TYPE_PARAMETER_FALLBACK, "1.3.0", ISSUE_SOME (27336), + EDITION_NONE) +FEATURE_ACTIVE ("repr_simd", REPR_SIMD, "1.4.0", ISSUE_SOME (27731), + EDITION_NONE) +FEATURE_ACTIVE ("platform_intrinsics", PLATFORM_INTRINSICS, "1.4.0", + ISSUE_SOME (27731), EDITION_NONE) +FEATURE_ACTIVE ("unwind_attributes", UNWIND_ATTRIBUTES, "1.4.0", + ISSUE_SOME (58760), EDITION_NONE) +FEATURE_ACTIVE ("stmt_expr_attributes", STMT_EXPR_ATTRIBUTES, "1.6.0", + ISSUE_SOME (15701), EDITION_NONE) +FEATURE_ACTIVE ("type_ascription", TYPE_ASCRIPTION, "1.6.0", ISSUE_SOME (23416), + EDITION_NONE) +FEATURE_ACTIVE ("cfg_target_thread_local", CFG_TARGET_THREAD_LOCAL, "1.7.0", + ISSUE_SOME (29594), EDITION_NONE) +FEATURE_ACTIVE ("specialization", SPECIALIZATION, "1.7.0", ISSUE_SOME (31844), + EDITION_NONE) +FEATURE_ACTIVE ("min_specialization", MIN_SPECIALIZATION, "1.7.0", + ISSUE_SOME (31844), EDITION_NONE) +FEATURE_ACTIVE ("naked_functions", NAKED_FUNCTIONS, "1.9.0", ISSUE_SOME (32408), + EDITION_NONE) +FEATURE_ACTIVE ("cfg_target_has_atomic", CFG_TARGET_HAS_ATOMIC, "1.9.0", + ISSUE_SOME (32976), EDITION_NONE) +FEATURE_ACTIVE ("exclusive_range_pattern", EXCLUSIVE_RANGE_PATTERN, "1.11.0", + ISSUE_SOME (37854), EDITION_NONE) +FEATURE_ACTIVE ("never_type", NEVER_TYPE, "1.13.0", ISSUE_SOME (35121), + EDITION_NONE) +FEATURE_ACTIVE ("exhaustive_patterns", EXHAUSTIVE_PATTERNS, "1.13.0", + ISSUE_SOME (51085), EDITION_NONE) +FEATURE_ACTIVE ("untagged_unions", UNTAGGED_UNIONS, "1.13.0", + ISSUE_SOME (55149), EDITION_NONE) +FEATURE_ACTIVE ("link_cfg", LINK_CFG, "1.14.0", ISSUE_SOME (37406), + EDITION_NONE) +FEATURE_ACTIVE ("abi_ptx", ABI_PTX, "1.15.0", ISSUE_SOME (38788), EDITION_NONE) +FEATURE_ACTIVE ("repr128", REPR128, "1.16.0", ISSUE_SOME (56071), EDITION_NONE) +FEATURE_ACTIVE ("static_nobundle", STATIC_NOBUNDLE, "1.16.0", + ISSUE_SOME (37403), EDITION_NONE) +FEATURE_ACTIVE ("abi_msp430_interrupt", ABI_MSP430_INTERRUPT, "1.16.0", + ISSUE_SOME (38487), EDITION_NONE) +FEATURE_ACTIVE ("decl_macro", DECL_MACRO, "1.17.0", ISSUE_SOME (39412), + EDITION_NONE) +FEATURE_ACTIVE ("abi_x86_interrupt", ABI_X86_INTERRUPT, "1.17.0", + ISSUE_SOME (40180), EDITION_NONE) +FEATURE_ACTIVE ("allow_fail", ALLOW_FAIL, "1.19.0", ISSUE_SOME (46488), + EDITION_NONE) +FEATURE_ACTIVE ("unsized_tuple_coercion", UNSIZED_TUPLE_COERCION, "1.20.0", + ISSUE_SOME (42877), EDITION_NONE) +FEATURE_ACTIVE ("generators", GENERATORS, "1.21.0", ISSUE_SOME (43122), + EDITION_NONE) +FEATURE_ACTIVE ("doc_cfg", DOC_CFG, "1.21.0", ISSUE_SOME (43781), EDITION_NONE) +FEATURE_ACTIVE ("doc_masked", DOC_MASKED, "1.21.0", ISSUE_SOME (44027), + EDITION_NONE) +FEATURE_ACTIVE ("doc_spotlight", DOC_SPOTLIGHT, "1.22.0", ISSUE_SOME (45040), + EDITION_NONE) +FEATURE_ACTIVE ("external_doc", EXTERNAL_DOC, "1.22.0", ISSUE_SOME (44732), + EDITION_NONE) +FEATURE_ACTIVE ("crate_visibility_modifier", CRATE_VISIBILITY_MODIFIER, + "1.23.0", ISSUE_SOME (53120), EDITION_NONE) +FEATURE_ACTIVE ("extern_types", EXTERN_TYPES, "1.23.0", ISSUE_SOME (43467), + EDITION_NONE) +FEATURE_ACTIVE ("arbitrary_self_types", ARBITRARY_SELF_TYPES, "1.23.0", + ISSUE_SOME (44874), EDITION_NONE) +FEATURE_ACTIVE ("in_band_lifetimes", IN_BAND_LIFETIMES, "1.23.0", + ISSUE_SOME (44524), EDITION_NONE) +FEATURE_ACTIVE ("generic_associated_types", GENERIC_ASSOCIATED_TYPES, "1.23.0", + ISSUE_SOME (44265), EDITION_NONE) +FEATURE_ACTIVE ("trait_alias", TRAIT_ALIAS, "1.24.0", ISSUE_SOME (41517), + EDITION_NONE) +FEATURE_ACTIVE ("infer_static_outlives_requirements", + INFER_STATIC_OUTLIVES_REQUIREMENTS, "1.26.0", + ISSUE_SOME (54185), EDITION_NONE) +FEATURE_ACTIVE ("const_fn_union", CONST_FN_UNION, "1.27.0", ISSUE_SOME (51909), + EDITION_NONE) +FEATURE_ACTIVE ("const_raw_ptr_to_usize_cast", CONST_RAW_PTR_TO_USIZE_CAST, + "1.27.0", ISSUE_SOME (51910), EDITION_NONE) +FEATURE_ACTIVE ("const_raw_ptr_deref", CONST_RAW_PTR_DEREF, "1.27.0", + ISSUE_SOME (51911), EDITION_NONE) +FEATURE_ACTIVE ("trivial_bounds", TRIVIAL_BOUNDS, "1.28.0", ISSUE_SOME (48214), + EDITION_NONE) +FEATURE_ACTIVE ("label_break_value", LABEL_BREAK_VALUE, "1.28.0", + ISSUE_SOME (48594), EDITION_NONE) +FEATURE_ACTIVE ("doc_keyword", DOC_KEYWORD, "1.28.0", ISSUE_SOME (51315), + EDITION_NONE) +FEATURE_ACTIVE ("try_blocks", TRY_BLOCKS, "1.29.0", ISSUE_SOME (31436), + EDITION_NONE) +FEATURE_ACTIVE ("alloc_error_handler", ALLOC_ERROR_HANDLER, "1.29.0", + ISSUE_SOME (51540), EDITION_NONE) +FEATURE_ACTIVE ("abi_amdgpu_kernel", ABI_AMDGPU_KERNEL, "1.29.0", + ISSUE_SOME (51575), EDITION_NONE) +FEATURE_ACTIVE ("const_panic", CONST_PANIC, "1.30.0", ISSUE_SOME (51999), + EDITION_NONE) +FEATURE_ACTIVE ("marker_trait_attr", MARKER_TRAIT_ATTR, "1.30.0", + ISSUE_SOME (29864), EDITION_NONE) +FEATURE_ACTIVE ("proc_macro_hygiene", PROC_MACRO_HYGIENE, "1.30.0", + ISSUE_SOME (54727), EDITION_NONE) +FEATURE_ACTIVE ("unsized_locals", UNSIZED_LOCALS, "1.30.0", ISSUE_SOME (48055), + EDITION_NONE) +FEATURE_ACTIVE ("custom_test_frameworks", CUSTOM_TEST_FRAMEWORKS, "1.30.0", + ISSUE_SOME (50297), EDITION_NONE) +FEATURE_ACTIVE ("custom_inner_attributes", CUSTOM_INNER_ATTRIBUTES, "1.30.0", + ISSUE_SOME (54726), EDITION_NONE) +FEATURE_ACTIVE ("impl_trait_in_bindings", IMPL_TRAIT_IN_BINDINGS, "1.30.0", + ISSUE_SOME (63065), EDITION_NONE) +FEATURE_ACTIVE ("lint_reasons", LINT_REASONS, "1.31.0", ISSUE_SOME (54503), + EDITION_NONE) +FEATURE_ACTIVE ("precise_pointer_size_matching", PRECISE_POINTER_SIZE_MATCHING, + "1.32.0", ISSUE_SOME (56354), EDITION_NONE) +FEATURE_ACTIVE ("ffi_returns_twice", FFI_RETURNS_TWICE, "1.34.0", + ISSUE_SOME (58314), EDITION_NONE) +FEATURE_ACTIVE ("const_generics", CONST_GENERICS, "1.34.0", ISSUE_SOME (44580), + EDITION_NONE) +FEATURE_ACTIVE ("optimize_attribute", OPTIMIZE_ATTRIBUTE, "1.34.0", + ISSUE_SOME (54882), EDITION_NONE) +FEATURE_ACTIVE ("c_variadic", C_VARIADIC, "1.34.0", ISSUE_SOME (44930), + EDITION_NONE) +FEATURE_ACTIVE ("associated_type_bounds", ASSOCIATED_TYPE_BOUNDS, "1.34.0", + ISSUE_SOME (52662), EDITION_NONE) +FEATURE_ACTIVE ("let_chains", LET_CHAINS, "1.37.0", ISSUE_SOME (53667), + EDITION_NONE) +FEATURE_ACTIVE ("transparent_unions", TRANSPARENT_UNIONS, "1.37.0", + ISSUE_SOME (60405), EDITION_NONE) +FEATURE_ACTIVE ("arbitrary_enum_discriminant", ARBITRARY_ENUM_DISCRIMINANT, + "1.37.0", ISSUE_SOME (60553), EDITION_NONE) +FEATURE_ACTIVE ("member_constraints", MEMBER_CONSTRAINTS, "1.37.0", + ISSUE_SOME (61997), EDITION_NONE) +FEATURE_ACTIVE ("async_closure", ASYNC_CLOSURE, "1.37.0", ISSUE_SOME (62290), + EDITION_NONE) +FEATURE_ACTIVE ("const_in_array_repeat_expressions", + CONST_IN_ARRAY_REPEAT_EXPRESSIONS, "1.37.0", ISSUE_SOME (49147), + EDITION_NONE) +FEATURE_ACTIVE ("type_alias_impl_trait", TYPE_ALIAS_IMPL_TRAIT, "1.38.0", + ISSUE_SOME (63063), EDITION_NONE) +FEATURE_ACTIVE ("or_patterns", OR_PATTERNS, "1.38.0", ISSUE_SOME (54883), + EDITION_NONE) +FEATURE_ACTIVE ("const_extern_fn", CONST_EXTERN_FN, "1.40.0", + ISSUE_SOME (64926), EDITION_NONE) +FEATURE_ACTIVE ("raw_dylib", RAW_DYLIB, "1.40.0", ISSUE_SOME (58713), + EDITION_NONE) +FEATURE_ACTIVE ("object_safe_for_dispatch", OBJECT_SAFE_FOR_DISPATCH, "1.40.0", + ISSUE_SOME (43561), EDITION_NONE) +FEATURE_ACTIVE ("abi_efiapi", ABI_EFIAPI, "1.40.0", ISSUE_SOME (65815), + EDITION_NONE) +FEATURE_ACTIVE ("raw_ref_op", RAW_REF_OP, "1.41.0", ISSUE_SOME (64490), + EDITION_NONE) +FEATURE_ACTIVE ("never_type_fallback", NEVER_TYPE_FALLBACK, "1.41.0", + ISSUE_SOME (65992), EDITION_NONE) +FEATURE_ACTIVE ("register_attr", REGISTER_ATTR, "1.41.0", ISSUE_SOME (66080), + EDITION_NONE) +FEATURE_ACTIVE ("register_tool", REGISTER_TOOL, "1.41.0", ISSUE_SOME (66079), + EDITION_NONE) +FEATURE_ACTIVE ("cfg_sanitize", CFG_SANITIZE, "1.41.0", ISSUE_SOME (39699), + EDITION_NONE) +FEATURE_ACTIVE ("half_open_range_patterns", HALF_OPEN_RANGE_PATTERNS, "1.41.0", + ISSUE_SOME (67264), EDITION_NONE) +FEATURE_ACTIVE ("const_mut_refs", CONST_MUT_REFS, "1.41.0", ISSUE_SOME (57349), + EDITION_NONE) +FEATURE_ACTIVE ("bindings_after_at", BINDINGS_AFTER_AT, "1.41.0", + ISSUE_SOME (65490), EDITION_NONE) +FEATURE_ACTIVE ("const_trait_impl", CONST_TRAIT_IMPL, "1.42.0", + ISSUE_SOME (67792), EDITION_NONE) +FEATURE_ACTIVE ("const_trait_bound_opt_out", CONST_TRAIT_BOUND_OPT_OUT, + "1.42.0", ISSUE_SOME (67794), EDITION_NONE) +FEATURE_ACTIVE ("no_sanitize", NO_SANITIZE, "1.42.0", ISSUE_SOME (39699), + EDITION_NONE) +FEATURE_ACTIVE ("const_eval_limit", CONST_EVAL_LIMIT, "1.43.0", + ISSUE_SOME (67217), EDITION_NONE) +FEATURE_ACTIVE ("negative_impls", NEGATIVE_IMPLS, "1.44.0", ISSUE_SOME (68318), + EDITION_NONE) +FEATURE_ACTIVE ("target_feature_11", TARGET_FEATURE_11, "1.45.0", + ISSUE_SOME (69098), EDITION_NONE) +FEATURE_ACTIVE ("cfg_version", CFG_VERSION, "1.45.0", ISSUE_SOME (64796), + EDITION_NONE) +FEATURE_ACTIVE ("ffi_pure", FFI_PURE, "1.45.0", ISSUE_SOME (58329), + EDITION_NONE) +FEATURE_ACTIVE ("ffi_const", FFI_CONST, "1.45.0", ISSUE_SOME (58328), + EDITION_NONE) +FEATURE_ACTIVE ("unsafe_block_in_unsafe_fn", UNSAFE_BLOCK_IN_UNSAFE_FN, + "1.45.0", ISSUE_SOME (71668), EDITION_NONE) +FEATURE_ACTIVE ("abi_avr_interrupt", ABI_AVR_INTERRUPT, "1.45.0", + ISSUE_SOME (69664), EDITION_NONE) +FEATURE_ACTIVE ("const_precise_live_drops", CONST_PRECISE_LIVE_DROPS, "1.46.0", + ISSUE_SOME (73255), EDITION_NONE) +FEATURE_ACTIVE ("format_args_capture", FORMAT_ARGS_CAPTURE, "1.46.0", + ISSUE_SOME (67984), EDITION_NONE) +FEATURE_ACTIVE ("lazy_normalization_consts", LAZY_NORMALIZATION_CONSTS, + "1.46.0", ISSUE_SOME (72219), EDITION_NONE) +FEATURE_ACTIVE ("const_fn_transmute", CONST_FN_TRANSMUTE, "1.46.0", + ISSUE_SOME (53605), EDITION_NONE) +FEATURE_ACTIVE ("min_const_generics", MIN_CONST_GENERICS, "1.47.0", + ISSUE_SOME (74878), EDITION_NONE) +FEATURE_ACTIVE ("if_let_guard", IF_LET_GUARD, "1.47.0", ISSUE_SOME (51114), + EDITION_NONE) +FEATURE_ACTIVE ("const_evaluatable_checked", CONST_EVALUATABLE_CHECKED, + "1.48.0", ISSUE_SOME (76560), EDITION_NONE) +FEATURE_ACTIVE ("const_fn_floating_point_arithmetic", + CONST_FN_FLOATING_POINT_ARITHMETIC, "1.48.0", + ISSUE_SOME (57241), EDITION_NONE) +FEATURE_ACTIVE ("const_fn_fn_ptr_basics", CONST_FN_FN_PTR_BASICS, "1.48.0", + ISSUE_SOME (57563), EDITION_NONE) +FEATURE_ACTIVE ("cmse_nonsecure_entry", CMSE_NONSECURE_ENTRY, "1.48.0", + ISSUE_SOME (75835), EDITION_NONE) +FEATURE_ACTIVE ("default_alloc_error_handler", DEFAULT_ALLOC_ERROR_HANDLER, + "1.48.0", ISSUE_SOME (66741), EDITION_NONE) +FEATURE_ACTIVE ("const_impl_trait", CONST_IMPL_TRAIT, "1.48.0", + ISSUE_SOME (77463), EDITION_NONE) +FEATURE_ACTIVE ("isa_attribute", ISA_ATTRIBUTE, "1.48.0", ISSUE_SOME (74727), + EDITION_NONE) +FEATURE_ACTIVE ("inline_const", INLINE_CONST, "1.49.0", ISSUE_SOME (76001), + EDITION_NONE) +FEATURE_ACTIVE ("unsized_fn_params", UNSIZED_FN_PARAMS, "1.49.0", + ISSUE_SOME (48055), EDITION_NONE) +FEATURE_ACTIVE ("destructuring_assignment", DESTRUCTURING_ASSIGNMENT, "1.49.0", + ISSUE_SOME (71126), EDITION_NONE) +FEATURE_ACTIVE ("cfg_panic", CFG_PANIC, "1.49.0", ISSUE_SOME (77443), + EDITION_NONE) +FEATURE_REMOVED ("import_shadowing", IMPORT_SHADOWING, "1.0.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("managed_boxes", MANAGED_BOXES, "1.0.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("negate_unsigned", NEGATE_UNSIGNED, "1.0.0", + ISSUE_SOME (29645), REASON_NONE) +FEATURE_REMOVED ("reflect", REFLECT, "1.0.0", ISSUE_SOME (27749), REASON_NONE) +FEATURE_REMOVED ("opt_out_copy", OPT_OUT_COPY, "1.0.0", ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("quad_precision_float", QUAD_PRECISION_FLOAT, "1.0.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("struct_inherit", STRUCT_INHERIT, "1.0.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("test_removed_feature", TEST_REMOVED_FEATURE, "1.0.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("visible_private_types", VISIBLE_PRIVATE_TYPES, "1.0.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("unsafe_no_drop_flag", UNSAFE_NO_DROP_FLAG, "1.0.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("unmarked_api", UNMARKED_API, "1.0.0", ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("allocator", ALLOCATOR, "1.0.0", ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("simd", SIMD, "1.0.0", ISSUE_SOME (27731), + REASON_SOME ("removed in favor of `#[repr(simd)]`")) +FEATURE_REMOVED ("advanced_slice_patterns", ADVANCED_SLICE_PATTERNS, "1.0.0", + ISSUE_SOME (62254), + REASON_SOME ("merged into `#![feature(slice_patterns)]`")) +FEATURE_REMOVED ("macro_reexport", MACRO_REEXPORT, "1.0.0", ISSUE_SOME (29638), + REASON_SOME ("subsumed by `pub use`")) +FEATURE_REMOVED ( + "custom_attribute", CUSTOM_ATTRIBUTE, "1.0.0", ISSUE_SOME (29642), + REASON_SOME ( + "removed in favor of `#![register_tool]` and `#![register_attr]`")) +FEATURE_REMOVED ("pushpop_unsafe", PUSHPOP_UNSAFE, "1.2.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("needs_allocator", NEEDS_ALLOCATOR, "1.4.0", + ISSUE_SOME (27389), + REASON_SOME ("subsumed by `#![feature(allocator_internals)]`")) +FEATURE_REMOVED ("sanitizer_runtime", SANITIZER_RUNTIME, "1.17.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("proc_macro_mod", PROC_MACRO_MOD, "1.27.0", ISSUE_SOME (54727), + REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`")) +FEATURE_REMOVED ("proc_macro_expr", PROC_MACRO_EXPR, "1.27.0", + ISSUE_SOME (54727), + REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`")) +FEATURE_REMOVED ("proc_macro_non_items", PROC_MACRO_NON_ITEMS, "1.27.0", + ISSUE_SOME (54727), + REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`")) +FEATURE_REMOVED ("proc_macro_gen", PROC_MACRO_GEN, "1.27.0", ISSUE_SOME (54727), + REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`")) +FEATURE_REMOVED ("panic_implementation", PANIC_IMPLEMENTATION, "1.28.0", + ISSUE_SOME (44489), + REASON_SOME ("subsumed by `#[panic_handler]`")) +FEATURE_REMOVED ("custom_derive", CUSTOM_DERIVE, "1.32.0", ISSUE_SOME (29644), + REASON_SOME ("subsumed by `#[proc_macro_derive]`")) +FEATURE_REMOVED ("extern_in_paths", EXTERN_IN_PATHS, "1.33.0", + ISSUE_SOME (55600), + REASON_SOME ("subsumed by `::foo::bar` paths")) +FEATURE_REMOVED ("quote", QUOTE, "1.33.0", ISSUE_SOME (29601), REASON_NONE) +FEATURE_REMOVED ("dropck_parametricity", DROPCK_PARAMETRICITY, "1.38.0", + ISSUE_SOME (28498), REASON_NONE) +FEATURE_REMOVED ("await_macro", AWAIT_MACRO, "1.38.0", ISSUE_SOME (50547), + REASON_SOME ("subsumed by `.await` syntax")) +FEATURE_REMOVED ( + "existential_type", EXISTENTIAL_TYPE, "1.38.0", ISSUE_SOME (63063), + REASON_SOME ("removed in favor of `#![feature(type_alias_impl_trait)]`")) +FEATURE_REMOVED ("rustc_diagnostic_macros", RUSTC_DIAGNOSTIC_MACROS, "1.38.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("on_unimplemented", ON_UNIMPLEMENTED, "1.40.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ( + "overlapping_marker_traits", OVERLAPPING_MARKER_TRAITS, "1.42.0", + ISSUE_SOME (29864), + REASON_SOME ("removed in favor of `#![feature(marker_trait_attr)]`")) +FEATURE_REMOVED ("no_debug", F_NO_DEBUG, "1.43.0", ISSUE_SOME (29721), + REASON_SOME ("removed due to lack of demand")) +FEATURE_REMOVED ( + "const_compare_raw_pointers", CONST_COMPARE_RAW_POINTERS, "1.46.0", + ISSUE_SOME (53020), + REASON_SOME ("cannot be allowed in const eval in any meaningful way")) +FEATURE_STABLE_REMOVED ("no_stack_check", NO_STACK_CHECK, "1.0.0", ISSUE_NONE) diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/feature/rust-feature-gate.cc index 44007f9..9df822b 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.cc +++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc @@ -34,7 +34,10 @@ FeatureGate::check (AST::Crate &crate) void FeatureGate::visit (AST::Crate &crate) { - valid_features.clear (); + valid_lang_features.clear (); + valid_lib_features.clear (); + + // avoid clearing defined features (?) for (const auto &attr : crate.inner_attrs) { @@ -58,31 +61,47 @@ FeatureGate::visit (AST::Crate &crate) for (const auto &item : meta_item->get_items ()) { const auto &name_str = item->as_string (); - auto tname = Feature::as_name (name_str); - if (tname.has_value ()) - { - auto name = tname.value (); - valid_features.insert (name); - } + // TODO: detect duplicates + if (auto tname = Feature::as_name (name_str)) + valid_lang_features.insert (tname.value ()); else - rust_error_at (item->get_locus (), ErrorCode::E0635, - "unknown feature %qs", name_str.c_str ()); + valid_lib_features.emplace (name_str, item->get_locus ()); } } } } AST::DefaultASTVisitor::visit (crate); + + for (auto &ent : valid_lib_features) + { + const std::string &feature = ent.first; + location_t locus = ent.second; + + // rustc treats these as valid, + // but apparently has special handling for them + if (feature == "libc" || feature == "test") + continue; + + if (defined_lib_features.find (feature) != defined_lib_features.end ()) + { + // TODO: emit warning if stable + continue; + } + + rust_error_at (locus, ErrorCode::E0635, "unknown feature %qs", + feature.c_str ()); + } } void FeatureGate::gate (Feature::Name name, location_t loc, const std::string &error_msg) { - if (!valid_features.count (name)) + if (!valid_lang_features.count (name)) { - auto feature = Feature::create (name); + auto &feature = Feature::lookup (name); if (auto issue = feature.issue ()) { auto issue_number = issue.value (); @@ -147,9 +166,77 @@ FeatureGate::check_may_dangle_attribute ( } void +FeatureGate::check_lang_item_attribute ( + const std::vector<AST::Attribute> &attributes) +{ + for (const AST::Attribute &attr : attributes) + { + const auto &str_path = attr.get_path ().as_string (); + bool is_lang_item = str_path == Values::Attributes::LANG + && attr.has_attr_input () + && attr.get_attr_input ().get_attr_input_type () + == AST::AttrInput::AttrInputType::LITERAL; + + if (is_lang_item) + gate (Feature::Name::LANG_ITEMS, attr.get_locus (), + "lang items are subject to change"); + } +} + +void +FeatureGate::note_stability_attribute ( + const std::vector<AST::Attribute> &attributes) +{ + for (const AST::Attribute &attr : attributes) + { + std::string attr_name = attr.get_path ().as_string (); + + Stability stability; + + if (attr_name == Values::Attributes::STABLE) + stability = Stability::STABLE; + else if (attr_name == Values::Attributes::UNSTABLE) + stability = Stability::UNSTABLE; + else if (attr_name == Values::Attributes::RUSTC_CONST_STABLE) + stability = Stability::STABLE; + else if (attr_name == Values::Attributes::RUSTC_CONST_UNSTABLE) + stability = Stability::UNSTABLE; + else + continue; + + if (attr.empty_input ()) + // TODO: error? + continue; + + auto &attr_input = attr.get_attr_input (); + if (attr_input.get_attr_input_type () + != AST::AttrInput::AttrInputType::TOKEN_TREE) + // TODO: error? + continue; + + std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item ( + static_cast<const AST::DelimTokenTree &> (attr_input) + .parse_to_meta_item ()); + + for (auto &item : meta_item->get_items ()) + { + // TODO: more thorough error checking? + // ~only the standard libraries should ever exercise this + if (item->is_key_value_pair ()) + { + auto &pair = static_cast<const AST::MetaNameValueStr &> (*item); + if (pair.get_name ().as_string () == "feature") + defined_lib_features.emplace (pair.get_value (), stability); + } + } + } +} + +void FeatureGate::visit (AST::MacroRulesDefinition &rules_def) { check_rustc_attri (rules_def.get_outer_attrs ()); + note_stability_attribute (rules_def.get_outer_attrs ()); } void @@ -158,6 +245,10 @@ FeatureGate::visit (AST::Function &function) if (!function.is_external ()) check_rustc_attri (function.get_outer_attrs ()); + check_lang_item_attribute (function.get_outer_attrs ()); + + note_stability_attribute (function.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (function); } @@ -184,8 +275,9 @@ void FeatureGate::visit (AST::Trait &trait) { if (trait.is_auto ()) - gate (Feature::Name::AUTO_TRAITS, trait.get_locus (), + gate (Feature::Name::OPTIN_BUILTIN_TRAITS, trait.get_locus (), "auto traits are experimental and possibly buggy"); + check_lang_item_attribute (trait.get_outer_attrs ()); AST::DefaultASTVisitor::visit (trait); } @@ -243,4 +335,32 @@ FeatureGate::visit (AST::UseTreeGlob &use) // #[feature(prelude_import)] } +void +FeatureGate::visit (AST::StructStruct &struct_item) +{ + check_lang_item_attribute (struct_item.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (struct_item); +} + +void +FeatureGate::visit (AST::TraitItemType &trait_item_type) +{ + check_lang_item_attribute (trait_item_type.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (trait_item_type); +} + +void +FeatureGate::visit (AST::Enum &enum_item) +{ + check_lang_item_attribute (enum_item.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (enum_item); +} + +void +FeatureGate::visit (AST::EnumItem &enum_variant) +{ + check_lang_item_attribute (enum_variant.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (enum_variant); +} + } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/feature/rust-feature-gate.h index f1011e5..8ff491c 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.h +++ b/gcc/rust/checks/errors/feature/rust-feature-gate.h @@ -47,13 +47,30 @@ public: void visit (AST::ExternBlock &block) override; void visit (AST::MacroRulesDefinition &rules_def) override; void visit (AST::RangePattern &pattern) override; + void visit (AST::StructStruct &struct_item) override; + void visit (AST::TraitItemType &trait_item_type) override; + void visit (AST::Enum &enum_item) override; + void visit (AST::EnumItem &enum_variant) override; private: void gate (Feature::Name name, location_t loc, const std::string &error_msg); void check_rustc_attri (const std::vector<AST::Attribute> &attributes); void check_may_dangle_attribute (const std::vector<AST::Attribute> &attributes); - std::set<Feature::Name> valid_features; + void + check_lang_item_attribute (const std::vector<AST::Attribute> &attributes); + void note_stability_attribute (const std::vector<AST::Attribute> &attributes); + + std::set<Feature::Name> valid_lang_features; + std::map<std::string, location_t> valid_lib_features; + + enum class Stability + { + STABLE, + UNSTABLE, + }; + + std::map<std::string, Stability> defined_lib_features; }; } // namespace Rust #endif diff --git a/gcc/rust/checks/errors/feature/rust-feature.cc b/gcc/rust/checks/errors/feature/rust-feature.cc new file mode 100644 index 0000000..1a967aa --- /dev/null +++ b/gcc/rust/checks/errors/feature/rust-feature.cc @@ -0,0 +1,100 @@ +// Copyright (C) 2020-2025 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 +// <http://www.gnu.org/licenses/>. + +#include "rust-feature.h" + +namespace Rust { + +Feature Feature::feature_list[] = { +#define ISSUE_SOME(n) n +#define ISSUE_NONE tl::nullopt +#define EDITION_2018 Edition::E2018 +#define EDITION_NONE tl::nullopt +#define REASON_SOME(r) r +#define REASON_NONE tl::nullopt + +#define FEATURE_BASE(state, name_str, name, rust_since, issue, ...) \ + Feature (Feature::Name::name, Feature::State::state, name_str, rust_since, \ + issue, __VA_ARGS__), + +#define FEATURE_ACTIVE(a, b, c, d, edition) \ + FEATURE_BASE (ACTIVE, a, b, c, d, edition, tl::nullopt) + +#define FEATURE_ACCEPTED(a, b, c, d) \ + FEATURE_BASE (ACCEPTED, a, b, c, d, tl::nullopt, tl::nullopt) + +#define FEATURE_REMOVED(a, b, c, d, reason) \ + FEATURE_BASE (REMOVED, a, b, c, d, tl::nullopt, reason) + +#define FEATURE_STABLE_REMOVED(a, b, c, d) \ + FEATURE_BASE (ACCEPTED, a, b, c, d, tl::nullopt, tl::nullopt) + +#include "rust-feature-defs.h" + +#undef ISSUE_SOME +#undef ISSUE_NONE +#undef EDITION_2018 +#undef EDITION_NONE +#undef REASON_SOME +#undef REASON_NONE + +#undef FEATURE_BASE +#undef FEATURE_ACTIVE +#undef FEATURE_ACCEPTED +#undef FEATURE_REMOVED +#undef FEATURE_STABLE_REMOVED +}; + +const std::map<std::string, Feature::Name> Feature::name_hash_map = { +#define FEATURE(s, name, ...) {s, Feature::Name::name}, +#define FEATURE_ACTIVE(...) FEATURE (__VA_ARGS__) +#define FEATURE_ACCEPTED(...) FEATURE (__VA_ARGS__) +#define FEATURE_REMOVED(...) FEATURE (__VA_ARGS__) +#define FEATURE_STABLE_REMOVED(...) FEATURE (__VA_ARGS__) +#include "rust-feature-defs.h" +#undef FEATURE +#undef FEATURE_ACTIVE +#undef FEATURE_ACCEPTED +#undef FEATURE_REMOVED +#undef FEATURE_STABLE_REMOVED +}; + +tl::optional<Feature::Name> +Feature::as_name (const std::string &name) +{ + auto it = Feature::name_hash_map.find (name); + if (it == Feature::name_hash_map.end ()) + return tl::nullopt; + else + return it->second; +} + +tl::optional<std::reference_wrapper<const Feature>> +Feature::lookup (const std::string &name) +{ + return as_name (name).map ( + [] (Name n) { return std::ref (Feature::lookup (n)); }); +} + +const Feature & +Feature::lookup (Feature::Name name) +{ + return feature_list[static_cast<size_t> (name)]; +} + +} // namespace Rust diff --git a/gcc/rust/checks/errors/feature/rust-feature.h b/gcc/rust/checks/errors/feature/rust-feature.h new file mode 100644 index 0000000..8686cf4 --- /dev/null +++ b/gcc/rust/checks/errors/feature/rust-feature.h @@ -0,0 +1,85 @@ +// Copyright (C) 2020-2025 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_FEATURE_H +#define RUST_FEATURE_H + +#include "rust-edition.h" +#include "optional.h" + +namespace Rust { + +class Feature +{ +public: + enum class State + { + ACCEPTED, // stabilized + ACTIVE, // unstable + REMOVED, // removed + STABILIZED, // removed after stabilization + }; + + enum class Name + { +#define FEATURE_ACTIVE(x, name, ...) name, +#define FEATURE_ACCEPTED(x, name, ...) name, +#define FEATURE_REMOVED(x, name, ...) name, +#define FEATURE_STABLE_REMOVED(x, name, ...) name, +#include "rust-feature-defs.h" +#undef FEATURE_ACTIVE +#undef FEATURE_ACCEPTED +#undef FEATURE_REMOVED +#undef FEATURE_STABLE_REMOVED + }; + + const std::string &as_string () const { return m_name_str; } + + Name name () const { return m_name; } + State state () const { return m_state; } + tl::optional<unsigned> issue () const { return m_issue; } + + static tl::optional<Name> as_name (const std::string &name); + + static tl::optional<std::reference_wrapper<const Feature>> + lookup (const std::string &name); + static const Feature &lookup (Name name); + +private: + Feature (Name name, State state, const char *name_str, const char *rust_since, + tl::optional<unsigned> issue_number, tl::optional<Edition> edition, + tl::optional<const char *> reason) + : m_name (name), m_state (state), m_name_str (name_str), + m_rust_since (rust_since), m_issue (issue_number), edition (edition), + m_reason (reason) + {} + + Name m_name; + State m_state; + std::string m_name_str; + std::string m_rust_since; + tl::optional<unsigned> m_issue; + tl::optional<Edition> edition; + tl::optional<const char *> m_reason; + + static Feature feature_list[]; + static const std::map<std::string, Name> name_hash_map; +}; + +} // namespace Rust +#endif diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc index 5291276..90248d3 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc @@ -20,7 +20,7 @@ #include "rust-reachability.h" #include "rust-hir-type-check.h" #include "rust-hir-map.h" -#include "rust-name-resolver.h" +#include "rust-immutable-name-resolution-context.h" #include "rust-visibility-resolver.h" #include "rust-pub-restricted-visitor.h" #include "rust-privacy-reporter.h" @@ -35,12 +35,13 @@ Resolver::resolve (HIR::Crate &crate) { PrivacyContext ctx; auto &mappings = Analysis::Mappings::get (); - auto resolver = Rust::Resolver::Resolver::get (); + auto &resolver + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get (); - VisibilityResolver (mappings, *resolver).go (crate); + VisibilityResolver (mappings, resolver).go (crate); PubRestrictedVisitor (mappings).go (crate); - PrivacyReporter (mappings, *resolver, *ty_ctx).go (crate); + PrivacyReporter (mappings, resolver, *ty_ctx).go (crate); auto visitor = ReachabilityVisitor (ctx, *ty_ctx); diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index 4af9639..c1a3d45 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -28,7 +28,8 @@ namespace Rust { namespace Privacy { PrivacyReporter::PrivacyReporter ( - Analysis::Mappings &mappings, Resolver::Resolver &resolver, + Analysis::Mappings &mappings, + const Resolver2_0::NameResolutionContext &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx) : mappings (mappings), resolver (resolver), ty_ctx (ty_ctx), current_module (tl::nullopt) @@ -90,59 +91,18 @@ PrivacyReporter::go (HIR::Crate &crate) } } -static bool -is_child_module (Analysis::Mappings &mappings, NodeId parent, - NodeId possible_child) -{ - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - return nr_ctx.values.is_module_descendant (parent, possible_child); - } - - auto children = mappings.lookup_module_children (parent); - - if (!children) - return false; - - // Visit all toplevel children - for (auto &child : *children) - if (child == possible_child) - return true; - - // Now descend recursively in the child module tree - for (auto &child : *children) - if (is_child_module (mappings, child, possible_child)) - return true; - - return false; -} - // FIXME: This function needs a lot of refactoring void PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, const location_t locus) { - NodeId ref_node_id = UNKNOWN_NODEID; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (use_id)) - ref_node_id = *id; - } - // FIXME: Don't assert here - we might be dealing with a type - else if (!resolver.lookup_resolved_name (use_id, &ref_node_id)) - resolver.lookup_resolved_type (use_id, &ref_node_id); + NodeId ref_node_id; // FIXME: Assert here. For now, we return since this causes issues when // checking inferred types (#1260) - // rust_assert (ref_node_id != UNKNOWN_NODEID); - if (ref_node_id == UNKNOWN_NODEID) + if (auto id = resolver.lookup (use_id)) + ref_node_id = *id; + else return; auto vis = mappings.lookup_visibility (ref_node_id); @@ -175,7 +135,9 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, // FIXME: This needs a LOT of TLC: hinting about the definition, a // string to say if it's a module, function, type, etc... - if (!is_child_module (mappings, mod_node_id, current_module.value ())) + + if (!resolver.values.is_module_descendant (mod_node_id, + current_module.value ())) valid = false; } break; diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h index 72716a6..d64b7a7 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h @@ -22,8 +22,9 @@ #include "rust-hir-expr.h" #include "rust-hir-map.h" #include "rust-hir-visitor.h" +#include "rust-hir-type-check.h" #include "rust-mapping-common.h" -#include "rust-name-resolver.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Privacy { @@ -38,7 +39,7 @@ class PrivacyReporter : public HIR::HIRExpressionVisitor, { public: PrivacyReporter (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver, + const Resolver2_0::NameResolutionContext &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx); /** @@ -157,7 +158,7 @@ types virtual void visit (HIR::ExprStmt &stmt); Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; const Rust::Resolver::TypeCheckContext &ty_ctx; // `None` means we're in the root module - the crate diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc index c59763d..4240673 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc @@ -20,16 +20,14 @@ #include "rust-ast.h" #include "rust-hir.h" #include "rust-hir-item.h" -#include "rust-immutable-name-resolution-context.h" - -// for flag_name_resolution_2_0 -#include "options.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Privacy { -VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings, - Resolver::Resolver &resolver) +VisibilityResolver::VisibilityResolver ( + Analysis::Mappings &mappings, + const Resolver2_0::NameResolutionContext &resolver) : mappings (mappings), resolver (resolver) {} @@ -64,23 +62,12 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction, = Error (restriction.get_locus (), "cannot use non-module path as privacy restrictor"); - NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) + NodeId ref_node_id; + if (auto id = resolver.lookup (ast_node_id)) { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (ast_node_id)) - { - ref_node_id = *id; - } - else - { - invalid_path.emit (); - return false; - } + ref_node_id = *id; } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + else { invalid_path.emit (); return false; diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h index 4dfba4c..ddd70a8 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h @@ -24,7 +24,7 @@ #include "rust-hir-stmt.h" #include "rust-hir-item.h" #include "rust-hir-map.h" -#include "rust-name-resolver.h" +#include "rust-name-resolution-context.h" #include "rust-hir-visitor.h" namespace Rust { @@ -34,7 +34,7 @@ class VisibilityResolver : public HIR::HIRVisItemVisitor { public: VisibilityResolver (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver); + const Resolver2_0::NameResolutionContext &resolver); /** * Perform visibility resolving on an entire crate @@ -93,7 +93,7 @@ public: private: Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; DefId current_module; }; diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc index c40f9db..782d694 100644 --- a/gcc/rust/checks/errors/rust-const-checker.cc +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -813,11 +813,11 @@ ConstChecker::visit (StructPattern &) {} void -ConstChecker::visit (TupleStructItemsNoRange &) +ConstChecker::visit (TupleStructItemsNoRest &) {} void -ConstChecker::visit (TupleStructItemsRange &) +ConstChecker::visit (TupleStructItemsHasRest &) {} void @@ -825,11 +825,11 @@ ConstChecker::visit (TupleStructPattern &) {} void -ConstChecker::visit (TuplePatternItemsMultiple &) +ConstChecker::visit (TuplePatternItemsNoRest &) {} void -ConstChecker::visit (TuplePatternItemsRanged &) +ConstChecker::visit (TuplePatternItemsHasRest &) {} void @@ -837,6 +837,14 @@ ConstChecker::visit (TuplePattern &) {} void +ConstChecker::visit (SlicePatternItemsNoRest &) +{} + +void +ConstChecker::visit (SlicePatternItemsHasRest &) +{} + +void ConstChecker::visit (SlicePattern &) {} diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h index eb63095..d464b7b 100644 --- a/gcc/rust/checks/errors/rust-const-checker.h +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -180,12 +180,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc deleted file mode 100644 index 071d3f8..0000000 --- a/gcc/rust/checks/errors/rust-feature.cc +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (C) 2020-2025 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 -// <http://www.gnu.org/licenses/>. - -#include "rust-feature.h" - -namespace Rust { - -Feature -Feature::create (Feature::Name f) -{ - switch (f) - { - case Feature::Name::ASSOCIATED_TYPE_BOUNDS: - return Feature (Feature::Name::ASSOCIATED_TYPE_BOUNDS, - Feature::State::ACCEPTED, "associated_type_bounds", - "1.34.0", 52662); - case Feature::Name::INTRINSICS: - return Feature (f, Feature::State::ACCEPTED, "intrinsics", "1.0.0"); - case Feature::Name::RUSTC_ATTRS: - return Feature (f, Feature::State::ACCEPTED, "rustc_attrs", "1.0.0"); - case Feature::Name::DECL_MACRO: - return Feature (f, Feature::State::ACCEPTED, "decl_macro", "1.0.0", - 39412); - case Feature::Name::EXTERN_TYPES: - return Feature (f, Feature::State::ACTIVE, "extern_types", "1.23.0", - 43467); - case Feature::Name::NEGATIVE_IMPLS: - return Feature (f, Feature::State::ACTIVE, "negative_impls", "1.0.0", - 68318); - case Feature::Name::BOX_SYNTAX: - return Feature (f, Feature::State::ACTIVE, "box_syntax", "1.0.0", 49733); - case Feature::Name::DROPCK_EYEPATCH: - return Feature (f, Feature::State::ACTIVE, "dropck_eyepatch", "1.10.0", - 34761); - case Feature::Name::RAW_REF_OP: - return Feature (f, Feature::State::ACTIVE, "raw_ref_op", "1.41.0", 64490); - case Feature::Name::EXCLUSIVE_RANGE_PATTERN: - return Feature (Feature::Name::EXCLUSIVE_RANGE_PATTERN, - Feature::State::ACTIVE, "exclusive_range_pattern", - "1.11.0", 37854); - case Feature::Name::PRELUDE_IMPORT: - return Feature (f, Feature::State::ACTIVE, "prelude_import", "1.0.0"); - case Feature::Name::MIN_SPECIALIZATION: - return Feature (f, Feature::State::ACTIVE, "min_specialization", - "1.0.0" /* FIXME: What version here? */, 31844); - case Feature::Name::AUTO_TRAITS: - return Feature (f, Feature::State::ACTIVE, "optin_builtin_traits", - "1.0.0", 13231); - default: - rust_unreachable (); - } -} - -const std::map<std::string, Feature::Name> Feature::name_hash_map = { - {"associated_type_bounds", Feature::Name::ASSOCIATED_TYPE_BOUNDS}, - {"intrinsics", Feature::Name::INTRINSICS}, - {"rustc_attrs", Feature::Name::RUSTC_ATTRS}, - {"decl_macro", Feature::Name::DECL_MACRO}, - {"negative_impls", Feature::Name::NEGATIVE_IMPLS}, - // TODO: Rename to "auto_traits" when supporting - // later Rust versions - {"optin_builtin_traits", Feature::Name::AUTO_TRAITS}, - {"extern_types", Feature::Name::EXTERN_TYPES}, - {"lang_items", Feature::Name::LANG_ITEMS}, - {"no_core", Feature::Name::NO_CORE}, - {"box_syntax", Feature::Name::BOX_SYNTAX}, - {"dropck_eyepatch", Feature::Name::DROPCK_EYEPATCH}, - {"raw_ref_op", Feature::Name::RAW_REF_OP}, - {"exclusive_range_pattern", Feature::Name::EXCLUSIVE_RANGE_PATTERN}, - {"prelude_import", Feature::Name::PRELUDE_IMPORT}, - {"min_specialization", Feature::Name::MIN_SPECIALIZATION}, -}; - -tl::optional<Feature::Name> -Feature::as_name (const std::string &name) -{ - if (Feature::name_hash_map.count (name)) - return Feature::name_hash_map.at (name); - - return tl::nullopt; -} - -} // namespace Rust diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h deleted file mode 100644 index e7cb0af..0000000 --- a/gcc/rust/checks/errors/rust-feature.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2020-2025 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 -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_FEATURE_H -#define RUST_FEATURE_H - -#include "rust-edition.h" -#include "optional.h" - -namespace Rust { - -class Feature -{ -public: - enum class State - { - ACCEPTED, - ACTIVE, - REMOVED, - STABILIZED, - }; - - enum class Name - { - ASSOCIATED_TYPE_BOUNDS, - INTRINSICS, - NEGATIVE_IMPLS, - RUSTC_ATTRS, - DECL_MACRO, - AUTO_TRAITS, - EXTERN_TYPES, - LANG_ITEMS, - NO_CORE, - BOX_SYNTAX, - DROPCK_EYEPATCH, - RAW_REF_OP, - EXCLUSIVE_RANGE_PATTERN, - PRELUDE_IMPORT, - MIN_SPECIALIZATION, - }; - - const std::string &as_string () { return m_name_str; } - Name name () { return m_name; } - const std::string &description () { return m_description; } - State state () { return m_state; } - tl::optional<unsigned> issue () { return m_issue; } - - static tl::optional<Name> as_name (const std::string &name); - static Feature create (Name name); - -private: - Feature (Name name, State state, const char *name_str, - const char *rustc_since, - tl::optional<unsigned> issue_number = tl::nullopt, - const tl::optional<Edition> &edition = tl::nullopt, - const char *description = "") - : m_state (state), m_name (name), m_name_str (name_str), - m_rustc_since (rustc_since), m_issue (issue_number), edition (edition), - m_description (description) - {} - - State m_state; - Name m_name; - std::string m_name_str; - std::string m_rustc_since; - tl::optional<unsigned> m_issue; - tl::optional<Edition> edition; - std::string m_description; // TODO: Switch to optional? - - static const std::map<std::string, Name> name_hash_map; -}; - -} // namespace Rust -#endif diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 2566971..f132e04 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -28,15 +28,12 @@ #include "rust-tyty.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Analysis { PatternChecker::PatternChecker () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()), + resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()), mappings (Analysis::Mappings::get ()) {} @@ -238,17 +235,9 @@ PatternChecker::visit (CallExpr &expr) NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid (); NodeId ref_node_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (ast_node_id)) - ref_node_id = *id; - else - return; - } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + if (auto id = resolver.lookup (ast_node_id)) + ref_node_id = *id; + else return; if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id)) @@ -640,11 +629,11 @@ PatternChecker::visit (StructPattern &) {} void -PatternChecker::visit (TupleStructItemsNoRange &) +PatternChecker::visit (TupleStructItemsNoRest &) {} void -PatternChecker::visit (TupleStructItemsRange &) +PatternChecker::visit (TupleStructItemsHasRest &) {} void @@ -652,11 +641,11 @@ PatternChecker::visit (TupleStructPattern &) {} void -PatternChecker::visit (TuplePatternItemsMultiple &) +PatternChecker::visit (TuplePatternItemsNoRest &) {} void -PatternChecker::visit (TuplePatternItemsRanged &) +PatternChecker::visit (TuplePatternItemsHasRest &) {} void @@ -664,6 +653,14 @@ PatternChecker::visit (TuplePattern &) {} void +PatternChecker::visit (SlicePatternItemsNoRest &) +{} + +void +PatternChecker::visit (SlicePatternItemsHasRest &) +{} + +void PatternChecker::visit (SlicePattern &) {} @@ -980,7 +977,7 @@ Matrix::specialize (const Constructor &ctor) const if (ctor.is_covered_by (hd.ctor ())) { pats.pop_head_constructor (ctor, subfields_place_info.size ()); - new_rows.push_back (MatrixRow (pats, row.is_under_guard ())); + new_rows.emplace_back (pats, row.is_under_guard ()); } } @@ -1186,7 +1183,7 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, } } - stack.push_back (WitnessPat (ctor, subfield, ty)); + stack.emplace_back (ctor, subfield, ty); } } @@ -1213,27 +1210,54 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx, std::vector<DeconstructedPat> fields; switch (elems.get_item_type ()) { - case HIR::TupleStructItems::ItemType::MULTIPLE: + case HIR::TupleStructItems::ItemType::NO_REST: { - HIR::TupleStructItemsNoRange &multiple - = static_cast<HIR::TupleStructItemsNoRange &> (elems); + HIR::TupleStructItemsNoRest &items_no_rest + = static_cast<HIR::TupleStructItemsNoRest &> (elems); rust_assert (variant->get_fields ().size () - == multiple.get_patterns ().size ()); + == items_no_rest.get_patterns ().size ()); - for (size_t i = 0; i < multiple.get_patterns ().size (); i++) + for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++) { fields.push_back ( - lower_pattern (ctx, *multiple.get_patterns ().at (i), + lower_pattern (ctx, *items_no_rest.get_patterns ().at (i), variant->get_fields ().at (i)->get_field_type ())); } return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; - case HIR::TupleStructItems::ItemType::RANGED: + case HIR::TupleStructItems::ItemType::HAS_REST: { - // TODO: ranged tuple struct items - rust_unreachable (); + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (elems); + + size_t num_patterns = items_has_rest.get_lower_patterns ().size () + + items_has_rest.get_upper_patterns ().size (); + + rust_assert (num_patterns <= variant->num_fields ()); + + size_t i = 0; + for (auto &pattern_member : items_has_rest.get_lower_patterns ()) + { + fields.push_back (lower_pattern ( + ctx, *pattern_member, + variant->get_fields ().at (i++)->get_field_type ())); + } + while (i < variant->num_fields () + - items_has_rest.get_upper_patterns ().size ()) + { + fields.push_back ( + DeconstructedPat::make_wildcard (pattern.get_locus ())); + i++; + } + for (auto &pattern_member : items_has_rest.get_upper_patterns ()) + { + fields.push_back (lower_pattern ( + ctx, *pattern_member, + variant->get_fields ().at (i++)->get_field_type ())); + } + return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; default: @@ -1597,7 +1621,7 @@ check_match_usefulness (Resolver::TypeCheckContext *ctx, MatchArm lowered = lower_arm (ctx, arm, scrutinee_ty); PatOrWild pat = PatOrWild::make_pattern (lowered.get_pat ()); pats.push (pat); - rows.push_back (MatrixRow (pats, lowered.has_guard ())); + rows.emplace_back (pats, lowered.has_guard ()); } std::vector<PlaceInfo> place_infos = {{PlaceInfo (scrutinee_ty)}}; diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h index dd44abc..645e61d 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h @@ -26,7 +26,7 @@ #include "rust-tyty.h" #include "optional.h" #include "rust-hir-visitor.h" -#include "rust-name-resolver.h" +#include "rust-immutable-name-resolution-context.h" namespace Rust { namespace Analysis { @@ -46,7 +46,7 @@ public: private: Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; Analysis::Mappings &mappings; virtual void visit (Lifetime &lifetime) override; @@ -153,12 +153,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/errors/rust-readonly-check.cc b/gcc/rust/checks/errors/rust-readonly-check.cc index c128933..f484047 100644 --- a/gcc/rust/checks/errors/rust-readonly-check.cc +++ b/gcc/rust/checks/errors/rust-readonly-check.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -17,184 +17,252 @@ // <http://www.gnu.org/licenses/>. #include "rust-readonly-check.h" -#include "rust-tree.h" -#include "rust-gcc.h" -#include "print-tree.h" +#include "rust-hir-expr.h" +#include "rust-hir-node.h" +#include "rust-hir-path.h" +#include "rust-hir-map.h" +#include "rust-hir-pattern.h" +#include "rust-mapping-common.h" +#include "rust-system.h" +#include "rust-immutable-name-resolution-context.h" +#include "rust-tyty.h" namespace Rust { -namespace Analysis { +namespace HIR { -static std::map<tree, int> assignment_map = {}; +static std::set<HirId> already_assigned_variables = {}; + +ReadonlyChecker::ReadonlyChecker () + : resolver (*Resolver::Resolver::get ()), + mappings (Analysis::Mappings::get ()), + context (*Resolver::TypeCheckContext::get ()) +{} + +void +ReadonlyChecker::go (Crate &crate) +{ + for (auto &item : crate.get_items ()) + item->accept_vis (*this); +} -// ported over from c-family/c-warn.cc void -readonly_error (location_t loc, tree arg, enum lvalue_use use) +ReadonlyChecker::visit (AssignmentExpr &expr) { - gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement - || use == lv_asm); - STRIP_ANY_LOCATION_WRAPPER (arg); - /* Using this macro rather than (for example) arrays of messages - ensures that all the format strings are checked at compile - time. */ -#define READONLY_MSG(A, I, D, AS) \ - (use == lv_assign \ - ? (A) \ - : (use == lv_increment ? (I) : (use == lv_decrement ? (D) : (AS)))) - if (TREE_CODE (arg) == COMPONENT_REF) + Expr &lhs = expr.get_lhs (); + mutable_context.enter (expr.get_mappings ().get_hirid ()); + lhs.accept_vis (*this); + mutable_context.exit (); +} + +void +ReadonlyChecker::visit (PathInExpression &expr) +{ + if (!mutable_context.is_in_context ()) + return; + + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + NodeId def_id; + + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + if (auto id = nr_ctx.lookup (ast_node_id)) + def_id = *id; + else + return; + + auto hir_id = mappings.lookup_node_to_hir (def_id); + if (!hir_id) + return; + + // Check if the local variable is mutable. + auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id); + if (maybe_pattern + && maybe_pattern.value ()->get_pattern_type () + == HIR::Pattern::PatternType::IDENTIFIER) + check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()), + expr.get_locus ()); + + // Check if the static item is mutable. + auto maybe_item = mappings.lookup_hir_item (*hir_id); + if (maybe_item + && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static) { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - error_at (loc, - READONLY_MSG (G_ ("assignment of member " - "%qD in read-only object"), - G_ ("increment of member " - "%qD in read-only object"), - G_ ("decrement of member " - "%qD in read-only object"), - G_ ("member %qD in read-only object " - "used as %<asm%> output")), - TREE_OPERAND (arg, 1)); - else - error_at ( - loc, - READONLY_MSG (G_ ("assignment of read-only member %qD"), - G_ ("increment of read-only member %qD"), - G_ ("decrement of read-only member %qD"), - G_ ("read-only member %qD used as %<asm%> output")), - TREE_OPERAND (arg, 1)); + auto static_item = static_cast<HIR::StaticItem *> (*maybe_item); + if (!static_item->is_mut ()) + rust_error_at (expr.get_locus (), + "assignment of read-only location '%s'", + static_item->get_identifier ().as_string ().c_str ()); } - else if (VAR_P (arg)) - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only variable %qD"), - G_ ("increment of read-only variable %qD"), - G_ ("decrement of read-only variable %qD"), - G_ ( - "read-only variable %qD used as %<asm%> output")), - arg); - else if (TREE_CODE (arg) == PARM_DECL) - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only parameter %qD"), - G_ ("increment of read-only parameter %qD"), - G_ ("decrement of read-only parameter %qD"), - G_ ( - "read-only parameter %qD use as %<asm%> output")), - arg); - else if (TREE_CODE (arg) == RESULT_DECL) + + // Check if the constant item is mutable. + if (maybe_item + && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant) { - error_at (loc, - READONLY_MSG (G_ ("assignment of " - "read-only named return value %qD"), - G_ ("increment of " - "read-only named return value %qD"), - G_ ("decrement of " - "read-only named return value %qD"), - G_ ("read-only named return value %qD " - "used as %<asm%>output")), - arg); + auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item); + rust_error_at (expr.get_locus (), "assignment of read-only location '%s'", + const_item->get_identifier ().as_string ().c_str ()); } - else if (TREE_CODE (arg) == FUNCTION_DECL) - error_at (loc, - READONLY_MSG (G_ ("assignment of function %qD"), - G_ ("increment of function %qD"), - G_ ("decrement of function %qD"), - G_ ("function %qD used as %<asm%> output")), - arg); - else - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only location %qE"), - G_ ("increment of read-only location %qE"), - G_ ("decrement of read-only location %qE"), - G_ ( - "read-only location %qE used as %<asm%> output")), - arg); } -static void -emit_error (tree *t, tree lhs, enum lvalue_use use) +void +ReadonlyChecker::check_variable (IdentifierPattern *pattern, + location_t assigned_loc) { - readonly_error (EXPR_LOCATION (*t), lhs, use); - TREE_OPERAND (*t, 0) = error_mark_node; + if (!mutable_context.is_in_context ()) + return; + + TyTy::BaseType *type; + if (context.lookup_type (pattern->get_mappings ().get_hirid (), &type) + && is_mutable_type (type)) + return; + if (pattern->is_mut ()) + return; + + auto hir_id = pattern->get_mappings ().get_hirid (); + if (already_assigned_variables.count (hir_id) > 0) + rust_error_at (assigned_loc, "assignment of read-only variable '%s'", + pattern->as_string ().c_str ()); + already_assigned_variables.insert (hir_id); } -static void -check_modify_expr (tree *t) +void +ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern, + bool has_init_expr) { - tree lhs = TREE_OPERAND (*t, 0); - if (TREE_CODE (lhs) == ARRAY_REF || TREE_CODE (lhs) == COMPONENT_REF) - lhs = TREE_OPERAND (lhs, 0); - - tree lhs_type = TREE_TYPE (lhs); - if (TYPE_READONLY (lhs_type) || TREE_READONLY (lhs) || TREE_CONSTANT (lhs)) + if (has_init_expr) { - if (TREE_CODE (lhs) != VAR_DECL) - emit_error (t, lhs, lv_assign); - else if (!DECL_ARTIFICIAL (lhs)) - { - if (DECL_INITIAL (lhs) != NULL) - emit_error (t, lhs, lv_assign); - else - { - if (assignment_map.find (lhs) == assignment_map.end ()) - { - assignment_map.insert ({lhs, 0}); - } - assignment_map[lhs]++; - - if (assignment_map[lhs] > 1) - emit_error (t, lhs, lv_assign); - } - } + HirId pattern_id = pattern.get_mappings ().get_hirid (); + already_assigned_variables.insert (pattern_id); } } -static void -check_decl (tree *t) +void +ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern, + bool has_init_expr) { - switch (TREE_CODE (*t)) + switch (tuple_pattern.get_items ().get_item_type ()) { - case MODIFY_EXPR: - check_modify_expr (t); + case HIR::TuplePatternItems::ItemType::NO_REST: + { + auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> ( + tuple_pattern.get_items ()); + for (auto &sub : items_no_rest.get_patterns ()) + { + collect_assignment (*sub, has_init_expr); + } + } + break; + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> ( + tuple_pattern.get_items ()); + for (auto &sub : items_has_rest.get_lower_patterns ()) + collect_assignment (*sub, has_init_expr); + for (auto &sub : items_has_rest.get_upper_patterns ()) + collect_assignment (*sub, has_init_expr); + } + break; + default: break; + } +} +void +ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr) +{ + switch (pattern.get_pattern_type ()) + { + case HIR::Pattern::PatternType::IDENTIFIER: + { + collect_assignment_identifier (static_cast<IdentifierPattern &> ( + pattern), + has_init_expr); + } + break; + case HIR::Pattern::PatternType::TUPLE: + { + auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern); + collect_assignment_tuple (tuple_pattern, has_init_expr); + } + break; default: break; } } -static tree -readonly_walk_fn (tree *t, int *, void *) +void +ReadonlyChecker::visit (LetStmt &stmt) +{ + HIR::Pattern &pattern = stmt.get_pattern (); + collect_assignment (pattern, stmt.has_init_expr ()); +} + +void +ReadonlyChecker::visit (FieldAccessExpr &expr) { - check_decl (t); - return NULL_TREE; + if (mutable_context.is_in_context ()) + { + expr.get_receiver_expr ().accept_vis (*this); + } } void -ReadonlyCheck::Lint (Compile::Context &ctx) +ReadonlyChecker::visit (TupleIndexExpr &expr) { - assignment_map.clear (); - for (auto &fndecl : ctx.get_func_decls ()) + if (mutable_context.is_in_context ()) { - for (tree p = DECL_ARGUMENTS (fndecl); p != NULL_TREE; p = DECL_CHAIN (p)) - { - check_decl (&p); - } + expr.get_tuple_expr ().accept_vis (*this); + } +} - walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl), - &readonly_walk_fn, &ctx); +void +ReadonlyChecker::visit (ArrayIndexExpr &expr) +{ + if (mutable_context.is_in_context ()) + { + expr.get_array_expr ().accept_vis (*this); } +} - assignment_map.clear (); - for (auto &var : ctx.get_var_decls ()) +void +ReadonlyChecker::visit (TupleExpr &expr) +{ + if (mutable_context.is_in_context ()) { - tree decl = var->get_decl (); - check_decl (&decl); + // TODO: Add check for tuple expression } +} - assignment_map.clear (); - for (auto &const_decl : ctx.get_const_decls ()) +void +ReadonlyChecker::visit (LiteralExpr &expr) +{ + if (mutable_context.is_in_context ()) { - check_decl (&const_decl); + rust_error_at (expr.get_locus (), "assignment of read-only location"); } } -} // namespace Analysis +void +ReadonlyChecker::visit (DereferenceExpr &expr) +{ + if (!mutable_context.is_in_context ()) + return; + TyTy::BaseType *to_deref_type; + auto to_deref = expr.get_expr ().get_mappings ().get_hirid (); + if (!context.lookup_type (to_deref, &to_deref_type)) + return; + if (!is_mutable_type (to_deref_type)) + rust_error_at (expr.get_locus (), "assignment of read-only location"); +} + +bool +ReadonlyChecker::is_mutable_type (TyTy::BaseType *type) +{ + if (type->get_kind () == TyTy::TypeKind::REF) + return static_cast<TyTy::ReferenceType *> (type)->is_mutable (); + if (type->get_kind () == TyTy::TypeKind::POINTER) + return static_cast<TyTy::PointerType *> (type)->is_mutable (); + return false; +} +} // namespace HIR } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-readonly-check.h b/gcc/rust/checks/errors/rust-readonly-check.h index b39eee3..3525620 100644 --- a/gcc/rust/checks/errors/rust-readonly-check.h +++ b/gcc/rust/checks/errors/rust-readonly-check.h @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -16,21 +16,54 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#ifndef RUST_READONLY_CHECK -#define RUST_READONLY_CHECK - -#include "rust-compile-context.h" +#include "rust-hir-visitor.h" +#include "rust-name-resolver.h" +#include "rust-stacked-contexts.h" +#include "rust-hir-type-check.h" namespace Rust { -namespace Analysis { - -class ReadonlyCheck +namespace HIR { +class ReadonlyChecker : public DefaultHIRVisitor { public: - static void Lint (Compile::Context &ctx); -}; + ReadonlyChecker (); + + void go (HIR::Crate &crate); + +private: + enum class lvalue_use + { + assign, + increment, + decrement, + }; + + Resolver::Resolver &resolver; + Analysis::Mappings &mappings; + Resolver::TypeCheckContext &context; + StackedContexts<HirId> mutable_context; -} // namespace Analysis -} // namespace Rust + using DefaultHIRVisitor::visit; + + virtual void visit (AssignmentExpr &expr) override; + virtual void visit (PathInExpression &expr) override; + virtual void visit (FieldAccessExpr &expr) override; + virtual void visit (ArrayIndexExpr &expr) override; + virtual void visit (TupleExpr &expr) override; + virtual void visit (TupleIndexExpr &expr) override; + virtual void visit (LetStmt &stmt) override; + virtual void visit (LiteralExpr &expr) override; + virtual void visit (DereferenceExpr &expr) override; + + void collect_assignment (Pattern &pattern, bool has_init_expr); + void collect_assignment_identifier (IdentifierPattern &pattern, + bool has_init_expr); + void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr); + + void check_variable (IdentifierPattern *pattern, location_t assigned_loc); + + bool is_mutable_type (TyTy::BaseType *type); +}; -#endif // RUST_READONLY_CHECK +} // namespace HIR +} // namespace Rust
\ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-readonly-check2.cc b/gcc/rust/checks/errors/rust-readonly-check2.cc deleted file mode 100644 index 2fa92ae..0000000 --- a/gcc/rust/checks/errors/rust-readonly-check2.cc +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (C) 2025 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 -// <http://www.gnu.org/licenses/>. - -#include "rust-readonly-check2.h" -#include "rust-hir-expr.h" -#include "rust-hir-node.h" -#include "rust-hir-path.h" -#include "rust-hir-map.h" -#include "rust-hir-pattern.h" -#include "rust-mapping-common.h" -#include "rust-system.h" -#include "rust-immutable-name-resolution-context.h" -#include "rust-tyty.h" - -namespace Rust { -namespace HIR { - -static std::set<HirId> already_assigned_variables = {}; - -ReadonlyChecker::ReadonlyChecker () - : resolver (*Resolver::Resolver::get ()), - mappings (Analysis::Mappings::get ()), - context (*Resolver::TypeCheckContext::get ()) -{} - -void -ReadonlyChecker::go (Crate &crate) -{ - for (auto &item : crate.get_items ()) - item->accept_vis (*this); -} - -void -ReadonlyChecker::visit (AssignmentExpr &expr) -{ - Expr &lhs = expr.get_lhs (); - mutable_context.enter (expr.get_mappings ().get_hirid ()); - lhs.accept_vis (*this); - mutable_context.exit (); -} - -void -ReadonlyChecker::visit (PathInExpression &expr) -{ - if (!mutable_context.is_in_context ()) - return; - - NodeId ast_node_id = expr.get_mappings ().get_nodeid (); - NodeId def_id; - - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id = nr_ctx.lookup (ast_node_id)) - def_id = *id; - else - return; - - auto hir_id = mappings.lookup_node_to_hir (def_id); - if (!hir_id) - return; - - // Check if the local variable is mutable. - auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id); - if (maybe_pattern - && maybe_pattern.value ()->get_pattern_type () - == HIR::Pattern::PatternType::IDENTIFIER) - check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()), - expr.get_locus ()); - - // Check if the static item is mutable. - auto maybe_item = mappings.lookup_hir_item (*hir_id); - if (maybe_item - && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static) - { - auto static_item = static_cast<HIR::StaticItem *> (*maybe_item); - if (!static_item->is_mut ()) - rust_error_at (expr.get_locus (), - "assignment of read-only location '%s'", - static_item->get_identifier ().as_string ().c_str ()); - } - - // Check if the constant item is mutable. - if (maybe_item - && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant) - { - auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item); - rust_error_at (expr.get_locus (), "assignment of read-only location '%s'", - const_item->get_identifier ().as_string ().c_str ()); - } -} - -void -ReadonlyChecker::check_variable (IdentifierPattern *pattern, - location_t assigned_loc) -{ - if (!mutable_context.is_in_context ()) - return; - if (pattern->is_mut ()) - return; - - auto hir_id = pattern->get_mappings ().get_hirid (); - if (already_assigned_variables.count (hir_id) > 0) - rust_error_at (assigned_loc, "assignment of read-only variable '%s'", - pattern->as_string ().c_str ()); - already_assigned_variables.insert (hir_id); -} - -void -ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern, - bool has_init_expr) -{ - if (has_init_expr) - { - HirId pattern_id = pattern.get_mappings ().get_hirid (); - already_assigned_variables.insert (pattern_id); - } -} - -void -ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern, - bool has_init_expr) -{ - switch (tuple_pattern.get_items ().get_item_type ()) - { - case HIR::TuplePatternItems::ItemType::MULTIPLE: - { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - tuple_pattern.get_items ()); - for (auto &sub : items.get_patterns ()) - { - collect_assignment (*sub, has_init_expr); - } - } - break; - default: - break; - } -} - -void -ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr) -{ - switch (pattern.get_pattern_type ()) - { - case HIR::Pattern::PatternType::IDENTIFIER: - { - collect_assignment_identifier (static_cast<IdentifierPattern &> ( - pattern), - has_init_expr); - } - break; - case HIR::Pattern::PatternType::TUPLE: - { - auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern); - collect_assignment_tuple (tuple_pattern, has_init_expr); - } - break; - default: - break; - } -} - -void -ReadonlyChecker::visit (LetStmt &stmt) -{ - HIR::Pattern &pattern = stmt.get_pattern (); - collect_assignment (pattern, stmt.has_init_expr ()); -} - -void -ReadonlyChecker::visit (FieldAccessExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_receiver_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (TupleIndexExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_tuple_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (ArrayIndexExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_array_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (TupleExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - // TODO: Add check for tuple expression - } -} - -void -ReadonlyChecker::visit (LiteralExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } -} - -void -ReadonlyChecker::visit (DereferenceExpr &expr) -{ - if (!mutable_context.is_in_context ()) - return; - TyTy::BaseType *to_deref_type; - auto to_deref = expr.get_expr ().get_mappings ().get_hirid (); - if (!context.lookup_type (to_deref, &to_deref_type)) - return; - if (to_deref_type->get_kind () == TyTy::TypeKind::REF) - { - auto ref_type = static_cast<TyTy::ReferenceType *> (to_deref_type); - if (!ref_type->is_mutable ()) - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } - if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER) - { - auto ptr_type = static_cast<TyTy::PointerType *> (to_deref_type); - if (!ptr_type->is_mutable ()) - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } -} -} // namespace HIR -} // namespace Rust diff --git a/gcc/rust/checks/errors/rust-readonly-check2.h b/gcc/rust/checks/errors/rust-readonly-check2.h deleted file mode 100644 index 06af9db..0000000 --- a/gcc/rust/checks/errors/rust-readonly-check2.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2025 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 -// <http://www.gnu.org/licenses/>. - -#include "rust-hir-visitor.h" -#include "rust-name-resolver.h" -#include "rust-stacked-contexts.h" -#include "rust-hir-type-check.h" - -namespace Rust { -namespace HIR { -class ReadonlyChecker : public DefaultHIRVisitor -{ -public: - ReadonlyChecker (); - - void go (HIR::Crate &crate); - -private: - enum class lvalue_use - { - assign, - increment, - decrement, - }; - - Resolver::Resolver &resolver; - Analysis::Mappings &mappings; - Resolver::TypeCheckContext &context; - StackedContexts<HirId> mutable_context; - - using DefaultHIRVisitor::visit; - - virtual void visit (AssignmentExpr &expr) override; - virtual void visit (PathInExpression &expr) override; - virtual void visit (FieldAccessExpr &expr) override; - virtual void visit (ArrayIndexExpr &expr) override; - virtual void visit (TupleExpr &expr) override; - virtual void visit (TupleIndexExpr &expr) override; - virtual void visit (LetStmt &stmt) override; - virtual void visit (LiteralExpr &expr) override; - virtual void visit (DereferenceExpr &expr) override; - - void collect_assignment (Pattern &pattern, bool has_init_expr); - void collect_assignment_identifier (IdentifierPattern &pattern, - bool has_init_expr); - void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr); - - void check_variable (IdentifierPattern *pattern, location_t assigned_loc); -}; - -} // namespace HIR -} // namespace Rust
\ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index 405c59b..607d20f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -926,11 +926,11 @@ UnsafeChecker::visit (StructPattern &) {} void -UnsafeChecker::visit (TupleStructItemsNoRange &) +UnsafeChecker::visit (TupleStructItemsNoRest &) {} void -UnsafeChecker::visit (TupleStructItemsRange &) +UnsafeChecker::visit (TupleStructItemsHasRest &) {} void @@ -938,11 +938,11 @@ UnsafeChecker::visit (TupleStructPattern &) {} void -UnsafeChecker::visit (TuplePatternItemsMultiple &) +UnsafeChecker::visit (TuplePatternItemsNoRest &) {} void -UnsafeChecker::visit (TuplePatternItemsRanged &) +UnsafeChecker::visit (TuplePatternItemsHasRest &) {} void @@ -950,6 +950,14 @@ UnsafeChecker::visit (TuplePattern &) {} void +UnsafeChecker::visit (SlicePatternItemsNoRest &) +{} + +void +UnsafeChecker::visit (SlicePatternItemsHasRest &) +{} + +void UnsafeChecker::visit (SlicePattern &) {} diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h index dc3b482..420668f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.h +++ b/gcc/rust/checks/errors/rust-unsafe-checker.h @@ -161,12 +161,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/lints/rust-lint-marklive-base.h b/gcc/rust/checks/lints/rust-lint-marklive-base.h index 2a97577..dec9396 100644 --- a/gcc/rust/checks/lints/rust-lint-marklive-base.h +++ b/gcc/rust/checks/lints/rust-lint-marklive-base.h @@ -19,9 +19,6 @@ #ifndef RUST_HIR_LIVENESS_BASE #define RUST_HIR_LIVENESS_BASE -#include "rust-diagnostics.h" -#include "rust-lint-marklive.h" -#include "rust-lint-marklive-base.h" #include "rust-hir-visitor.h" #include "rust-hir-map.h" |
