diff options
Diffstat (limited to 'gcc/rust')
65 files changed, 2228 insertions, 520 deletions
diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog index 556ce28..ec156ac 100644 --- a/gcc/rust/ChangeLog +++ b/gcc/rust/ChangeLog @@ -1,3 +1,300 @@ +2025-12-03 Marc Poulhiès <dkm@kataplop.net> + + * lex/rust-lex.cc (rust_input_source_test): Reindent. + +2025-12-03 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-macro.h (MetaNameValueStr::get_name): New function. + (MetaNameValueStr::get_value): Likewise. + * checks/errors/feature/rust-feature-gate.cc + (FeatureGate::visit): Tweak unknown feature detection. + (FeatureGate::gate): Handle field rename. + (FeatureGate::note_stability_attribute): New function + definition. + * checks/errors/feature/rust-feature-gate.h + (FeatureGate::note_stability_attribute): New function + declaration. + (FeatureGate::Stability): New enum class. + (FeatureGate::valid_features): Rename field to... + (FeatureGate::valid_lang_features): ...here. + (FeatureGate::valid_lib_features): New field. + (FeatureGate::defined_lib_features): Likewise. + * checks/errors/feature/rust-feature.cc (Feature::as_name): + Improve implementation. + +2025-12-03 Raiki Tamura <tamaron1203@gmail.com> + + * checks/errors/feature/rust-feature-gate.cc (FeatureGate::visit): Add check for lang_items. + * checks/errors/feature/rust-feature-gate.h: Likewise. + +2025-12-03 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse-impl.h (Parser::parse_function): Return a nullptr on + error instead of a valid function. + (Parser::parse_let_stmt): Remove non leaf error. + (Parser::parse_if_expr): Likewise. + (Parser::parse_loop_expr): Likewise. + (Parser::parse_expr): Return error on null denotation error. + +2025-12-03 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse-impl.h (Parser::parse_delim_token_tree): + Remove error message. + (Parser::parse_token_tree): Split error message. + +2025-12-03 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * backend/rust-constexpr.cc (eval_binary_expression): Set initial value + equality value to false. + +2025-12-03 Jonathan Wakely <jwakely@redhat.com> + + * expand/rust-macro-expand.h: Fix typos in comment. + +2025-12-03 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse-impl.h (Parser::parse_items): Remove item parsing + error. + +2025-12-03 Ryutaro Okada <1015ryu88@gmail.com> + + * expand/rust-expand-visitor.cc (builtin_derive_item): Collect derived nodes. + (derive_item): Collect derived nodes. + * util/rust-hir-map.cc (Mappings::add_derived_nodes): Add derived set to collect derived + nodes. + (Mappings::is_derived_node): Add derived set to collect derived nodes. + * util/rust-hir-map.h: Add derived set to collect derived nodes. + +2025-11-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + * lang.opt.urls: Regenerate. + +2025-11-27 Jakub Jelinek <jakub@redhat.com> + + * lex/rust-lex.cc (rust_input_source_test): Cast char8_t string + literals to (const char *) to make it compilable with C++20. Use + char16_t or char32_t character literals instead of ordinary + character literals or wide character literals in expected + initializers. + +2025-11-27 Arthur Cohen <arthur.cohen@embecosm.com> + + * typecheck/rust-tyty-subst.h: Remove now useless inclusion. + * typecheck/rust-tyty.h (class TypeBoundPredicate): New, moved from rust-tyty-bounds.h + (class TypeBoundsMappings): Likewise. + * typecheck/rust-tyty-bounds.h: Removed. + +2025-11-25 Lúcio Boari Fleury <lucboari@gmail.com> + + * parse/rust-parse-impl.h: Add early exit condition to parsing loop. + +2025-11-25 Philip Herron <herron.philip@googlemail.com> + + * ast/rust-ast.cc (TraitItemType::as_string): add generic params + * ast/rust-ast.h: remove old comment + * ast/rust-item.h: add generic params to associated type + * ast/rust-type.h: remove old comment + * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): hir lowering for gat's + * hir/tree/rust-hir-item.cc (TraitItemType::TraitItemType): gat's on TraitItemType + (TraitItemType::operator=): preserve generic params + * hir/tree/rust-hir-item.h: likewise + * hir/tree/rust-hir.cc (TraitItemType::as_string): likewise + * parse/rust-parse-impl.h (Parser::parse_trait_type): hit the < and parse params + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItemWithTrait::visit): typecheck + * typecheck/rust-tyty.cc (BaseType::has_substitutions_defined): dont destructure + +2025-11-25 Lucas Ly Ba <lucas.ly-ba@outlook.com> + + * expand/rust-derive.cc (DeriveVisitor::derive): + Add check and error. + +2025-11-25 Lucas Ly Ba <lucas.ly-ba@outlook.com> + + * hir/rust-ast-lower-base.cc (ASTLoweringBase::handle_doc_item_attribute): Make error. + +2025-11-25 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-expr.cc (compile_float_literal): Add is_negative + check to compile negative float literals properly. + * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(RangePattern)): + Minor optimization to E0579 checks to reduce memory copy. + +2025-11-25 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/feature/rust-feature-gate.cc + (FeatureGate::gate): Handle removal of Feature::create. + (FeatureGate::visit): Refer to AUTO_TRAITS as + OPTIN_BUILTIN_TRAITS. + * checks/errors/feature/rust-feature.cc (Feature::create): + Remove. + (Feature::feature_list): New static member variable. + (Feature::name_hash_map): Use "rust-feature-defs.h" to define. + (Feature::lookup): New member function definition. + * checks/errors/feature/rust-feature.h (Feature::State): Add + comments. + (Feature::Name): Use "rust-feature-defs.h" to define. + (Feature::as_string): Make const. + (Feature::name): Likewise. + (Feature::state): Likewise. + (Feature::issue): Likewise. + (Feature::description): Remove member function declaration. + (Feature::create): Remove static member function declaration. + (Feature::lookup): New member function declarations. + (Feature::Feature): Adjust arguments. + (Feature::m_rustc_since): Rename to... + (Feature::m_rust_since): ...here. + (Feature::m_description): Remove. + (Feature::m_reason): New member variable. + (Feature::feature_list): New static member variable. + * checks/errors/feature/rust-feature-defs.h: New file. + * checks/errors/feature/contrib/parse.y: New file. + * checks/errors/feature/contrib/scan.l: New file. + * checks/errors/feature/contrib/.gitignore: New file. + * checks/errors/feature/contrib/Makefile: New file. + * checks/errors/feature/contrib/fetch: New file. + * checks/errors/feature/contrib/regen: New file. + * checks/errors/feature/contrib/copyright-stub.h: New file. + * checks/errors/feature/contrib/README: New file. + +2025-11-25 Lucas Ly Ba <lucas.ly-ba@outlook.com> + + * ast/rust-ast.cc (Attribute::check_cfg_predicate): Make error when attribute has no input. + +2025-11-25 Owen Avery <powerboat9.gamer@gmail.com> + + * backend/rust-compile-expr.cc (CompileExpr::visit): Implicitly + convert LocalVariable to pointer to Bvariable. + * rust-backend.h (local_variable): Return LocalVariable. + (parameter_variable): Likewise. + (static_chain_variable): Likewise. + (temporary_variable): Likewise. + * rust-gcc.cc (local_variable): Likewise. + (parameter_variable): Likewise. + (static_chain_variable): Likewise. + (temporary_variable): Likewise. + (LocalVariable::get_tree): New function. + (LocalVariable::error_variable): Likewise. + * rust-gcc.h (class LocalVariable): New class. + +2025-11-25 lenny.chiadmi-delage <lenny.chiadmi-delage@epita.fr> + + * expand/rust-macro-expand.cc (transcribe_expression): Check if + parser didn't fail. + (transcribe_type): Likewise. + (transcribe_pattern): Likewise. + +2025-11-17 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItemWithTrait::visit): null guard + * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): default to anon + +2025-11-17 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-item.cc (CompileItem::visit): support the synthetic function consts + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::Resolve): likewise + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): create the synth + * typecheck/rust-tyty.h: new flag for synthetic constant + +2025-11-17 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): fix mappings + +2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com> + + * ast/rust-ast.cc (Attribute::is_derive): + Change is_derive method with its valid path. + * util/rust-attribute-values.h: + Delete redudant derive attribute. + * util/rust-attributes.cc (AttributeChecker::check_inner_attribute): + Helper method for check_inner_attributes + (AttributeChecker::check_inner_attributes): + Implement method for errors check. + * util/rust-attributes.h: + Add methods above in header. + +2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com> + + * parse/rust-parse-impl.h(Parser<ManagedTokenSource>::parse_while_let_loop_expr): + Add check for missing pattern. + +2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com> + + * ast/rust-ast.cc (MetaItemLitExpr::check_cfg_predicate): Make error. + +2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com> + + * ast/rust-ast.cc (Attribute::check_cfg_predicate): add cfg path in condition + +2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com> + + * ast/rust-ast.cc (Attribute::check_cfg_predicate): + Make error. + +2025-11-17 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-resolve-path.cc: handle const param values + * typecheck/rust-hir-type-check-item.cc: generate const infer vars when required + * typecheck/rust-type-util.cc (unify_site_and): handle a null param cleanup + * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): helper interface + * typecheck/rust-tyty-util.h: update header prototypes + * typecheck/rust-tyty.cc (BaseType::is_concrete): correctly handle const types + (ConstParamType::get_name): emit the specified type + (ConstParamType::is_equal): fix recursion loop + * typecheck/rust-unify.cc (UnifyRules::go): const infer vars need cleanup too + * typecheck/rust-unify.h: support base generics + +2025-11-17 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc(compilePatternCheckExpr::visit(RangePattern)): + Add E0579 check to ensure that lower bound is always below upper bound. + +2025-11-17 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc (compile_range_pattern_bound): Set litexpr + to negative if has_minus is present in the RangePatternBoundLiteral param. + +2025-11-17 vishruth-thimmaiah <vishruththimmaiah@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_generic_params): Emit + an error when const generics with a default value is not + trailing. + +2025-11-17 Yap Zhi Heng <yapzhhg@gmail.com> + + * parse/rust-parse-impl.h (parse_literal_or_range_pattern): Parse minus sign + properly for LiteralPattern. + * ast/rust-pattern.h (LiteralPattern): Add has_minus boolean for LiteralPattern. + * hir/tree/rust-hir-pattern.h (LiteralPattern): Ditto. + * ast/rust-pattern.cc (LiteralPattern::as_string): Update to include minus sign + if present. + * hir/tree/rust-hir.cc (LiteralPattern::as_string): Ditto. + * hir/rust-ast-lower-pattern.cc (visit(LiteralPattern)): Pass has_minus boolean + from AST to HIR. + * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(LiteralPattern)): + Compile litexpr as negative if minus sign is present. + +2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.fr> + + * metadata/rust-export-metadata.cc (ExportContext::emit_macro): + Change method argument NodeId to AST::MacroRulesDefinition. + * metadata/rust-export-metadata.h: + Likewise. + * util/rust-hir-map.cc (Mappings::insert_exported_macro): + Insert AST::MacroRulesDefinition instead of NodeId. + * util/rust-hir-map.h: + Change methods declarations of exported macros. + +2025-11-12 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-fmt.h: Simplify diagnostic avoidance. + +2025-11-12 Arthur Cohen <arthur.cohen@embecosm.com> + Thomas Schwinge <tschwinge@gcc.gnu.org> + + PR rust/122498 + * ast/rust-fmt.h: Add -Warray-bounds pragma to avoid the issue during + bootstraps + 2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> * ast/rust-ast-pointer-visitor.cc (PointerVisitor::visit): diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 337a338..851f7ea 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -248,7 +248,7 @@ Attribute::as_string () const bool Attribute::is_derive () const { - return has_attr_input () && get_path () == Values::Attributes::DERIVE; + return has_attr_input () && get_path () == Values::Attributes::DERIVE_ATTR; } /** @@ -3050,6 +3050,18 @@ TraitItemType::as_string () const str += "\ntype " + name.as_string (); + if (has_generics ()) + { + str += "<"; + for (size_t i = 0; i < generic_params.size (); i++) + { + if (i > 0) + str += ", "; + str += generic_params[i]->as_string (); + } + str += ">"; + } + str += "\n Type param bounds: "; if (!has_type_param_bounds ()) { @@ -3834,6 +3846,9 @@ MetaItemLitExpr::check_cfg_predicate (const Session &) const { /* as far as I can tell, a literal expr can never be a valid cfg body, so * false */ + rust_error_at (this->get_locus (), "'%s' predicate key cannot be a literal", + this->as_string ().c_str ()); + return false; } @@ -4160,16 +4175,10 @@ Attribute::check_cfg_predicate (const Session &session) const auto string_path = path.as_string (); /* assume that cfg predicate actually can exist, i.e. attribute has cfg or * cfg_attr path */ - if (!has_attr_input () - || (string_path != Values::Attributes::CFG - && string_path != Values::Attributes::CFG_ATTR)) + if (!has_attr_input ()) { - // DEBUG message - rust_debug ( - "tried to check cfg predicate on attr that either has no input " - "or invalid path. attr: '%s'", - as_string ().c_str ()); - + rust_error_at (path.get_locus (), "%qs is not followed by parentheses", + string_path.c_str ()); return false; } @@ -4178,11 +4187,18 @@ Attribute::check_cfg_predicate (const Session &session) const return false; auto &meta_item = static_cast<AttrInputMetaItemContainer &> (*attr_input); - if (meta_item.get_items ().empty () - && string_path == Values::Attributes::CFG_ATTR) + if (meta_item.get_items ().empty ()) + { + rust_error_at (path.get_locus (), "malformed %<%s%> attribute input", + string_path.c_str ()); + return false; + } + + if (string_path == Values::Attributes::CFG + && meta_item.get_items ().size () != 1) { - rust_error_at (path.get_locus (), - "malformed %<cfg_attr%> attribute input"); + rust_error_at (path.get_locus (), "multiple %qs predicates are specified", + path.as_string ().c_str ()); return false; } return meta_item.get_items ().front ()->check_cfg_predicate (session); diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 8a7e618..8610ade 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1891,7 +1891,6 @@ public: { parsed_items = std::move (new_items); } - // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items () { return parsed_items; diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h index e59bed3..13dc7be 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -22,6 +22,9 @@ #include "rust-system.h" #include "optional.h" +// PR122498 "rust-enabled bootstrap is broken after r16-4897" +#pragma GCC diagnostic warning "-Warray-bounds" + namespace Rust { namespace Fmt { diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 7aea763..3e3735c 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -2726,21 +2726,28 @@ class TraitItemType : public TraitItem Identifier name; + // Generic parameters for GATs (Generic Associated Types) + std::vector<std::unique_ptr<GenericParam>> generic_params; + // bool has_type_param_bounds; // TypeParamBounds type_param_bounds; std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; // inlined form public: + bool has_generics () const { return !generic_params.empty (); } + // Returns whether trait item type has type param bounds. bool has_type_param_bounds () const { return !type_param_bounds.empty (); } TraitItemType (Identifier name, + std::vector<std::unique_ptr<GenericParam>> generic_params, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds, std::vector<Attribute> outer_attrs, Visibility vis, location_t locus) : TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)), - name (std::move (name)), type_param_bounds (std::move (type_param_bounds)) + name (std::move (name)), generic_params (std::move (generic_params)), + type_param_bounds (std::move (type_param_bounds)) {} // Copy constructor with vector clone @@ -2749,6 +2756,9 @@ public: name (other.name) { node_id = other.node_id; + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -2763,6 +2773,9 @@ public: locus = other.locus; node_id = other.node_id; + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -2786,7 +2799,15 @@ public: std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } - // TODO: mutable getter seems kinda dodgy + std::vector<std::unique_ptr<GenericParam>> &get_generic_params () + { + return generic_params; + } + const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const + { + return generic_params; + } + std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds () { return type_param_bounds; diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 4165075..71de8f0 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -993,6 +993,10 @@ public: return ident.as_string () + " = \"" + str + "\""; } + const Identifier &get_name () const { return ident; } + + const std::string &get_value () const { return str; } + void accept_vis (ASTVisitor &vis) override; // HACK: used to simplify parsing - creates a copy of this diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index a2fe5d5..80189d3 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -48,7 +48,7 @@ tokenid_to_rangekind (TokenId id) std::string LiteralPattern::as_string () const { - return lit.as_string (); + return (has_minus ? "-" : "") + lit.as_string (); } std::string diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 0da1981..3b1bd1c 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -30,6 +30,7 @@ class LiteralPattern : public Pattern Literal lit; location_t locus; NodeId node_id; + bool has_minus; public: std::string as_string () const override; @@ -37,17 +38,34 @@ public: // Constructor for a literal pattern LiteralPattern (Literal lit, location_t locus) : lit (std::move (lit)), locus (locus), - node_id (Analysis::Mappings::get ().get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()), + has_minus (false) + {} + + LiteralPattern (Literal lit, location_t locus, bool has_minus) + : lit (std::move (lit)), locus (locus), + node_id (Analysis::Mappings::get ().get_next_node_id ()), + has_minus (has_minus) {} LiteralPattern (std::string val, Literal::LitType type, location_t locus, PrimitiveCoreType type_hint) : lit (Literal (std::move (val), type, type_hint)), locus (locus), - node_id (Analysis::Mappings::get ().get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()), + has_minus (false) + {} + + LiteralPattern (std::string val, Literal::LitType type, location_t locus, + PrimitiveCoreType type_hint, bool has_minus) + : lit (Literal (std::move (val), type, type_hint)), locus (locus), + node_id (Analysis::Mappings::get ().get_next_node_id ()), + has_minus (has_minus) {} location_t get_locus () const override final { return locus; } + bool get_has_minus () const { return has_minus; } + void accept_vis (ASTVisitor &vis) override; NodeId get_node_id () const override { return node_id; } diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 014963f..38a3474 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -177,7 +177,6 @@ public: void accept_vis (ASTVisitor &vis) override; - // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { return type_param_bounds; @@ -250,7 +249,6 @@ public: bool is_dyn () const { return has_dyn; } - // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { return type_param_bounds; @@ -463,7 +461,6 @@ public: void accept_vis (ASTVisitor &vis) override; - // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<Type> > &get_elems () { return elems; } const std::vector<std::unique_ptr<Type> > &get_elems () const { diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 0a627f3..9a9c315 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -175,7 +175,7 @@ CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) } auto receiver_tmp = NULL_TREE; - auto receiver + Bvariable *receiver = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, TREE_TYPE (lhs), lhs, true, expr.get_locus (), &receiver_tmp); @@ -214,7 +214,7 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr) if (ctx->in_fn () && !ctx->const_context_p ()) { auto tmp = NULL_TREE; - auto receiver + Bvariable *receiver = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, TREE_TYPE (lhs), lhs, true, expr.get_locus (), &tmp); @@ -1712,6 +1712,8 @@ CompileExpr::compile_float_literal (const HIR::LiteralExpr &expr, rust_error_at (expr.get_locus (), "bad number in literal"); return error_mark_node; } + if (expr.is_negative ()) + mpfr_neg (fval, fval, MPFR_RNDN); // taken from: // see go/gofrontend/expressions.cc:check_float_type diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index b72e70d..d908710 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -109,6 +109,17 @@ CompileItem::visit (HIR::ConstantItem &constant) // canonical path Resolver::CanonicalPath canonical_path = nr_ctx.to_canonical_path (mappings.get_nodeid ()); + if (constant_type->is<const TyTy::FnType> ()) + { + if (concrete == nullptr) + return; + + rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *concrete_fnty = static_cast<TyTy::FnType *> (concrete); + + concrete_fnty->override_context (); + constant_type = expr_type = concrete_fnty->get_return_type (); + } ctx->push_const_context (); tree const_expr diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 82333dc..af5f453 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -87,6 +87,8 @@ CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern) auto litexpr = std::make_unique<HIR::LiteralExpr> ( HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (), pattern.get_locus (), std::vector<AST::Attribute> ())); + if (pattern.get_has_minus ()) + litexpr->set_negative (); // Note: Floating point literals are currently accepted but will likely be // forbidden in LiteralPatterns in a future version of Rust. @@ -119,6 +121,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, HIR::LiteralExpr litexpr (mappings, ref.get_literal (), locus, std::vector<AST::Attribute> ()); + if (ref.get_has_minus ()) + litexpr.set_negative (); result = CompileExpr::Compile (litexpr, ctx); } @@ -159,6 +163,30 @@ CompilePatternCheckExpr::visit (HIR::RangePattern &pattern) pattern.get_mappings (), pattern.get_locus (), ctx); + rust_assert ( + (TREE_CODE (upper) == REAL_CST && TREE_CODE (lower) == REAL_CST) + || (TREE_CODE (upper) == INTEGER_CST && TREE_CODE (lower) == INTEGER_CST)); + + bool error_E0579 = false; + if (TREE_CODE (upper) == REAL_CST) + { + const REAL_VALUE_TYPE *upper_r = TREE_REAL_CST_PTR (upper); + const REAL_VALUE_TYPE *lower_r = TREE_REAL_CST_PTR (lower); + if (real_compare (GE_EXPR, lower_r, upper_r)) + error_E0579 = true; + } + else if (TREE_CODE (upper) == INTEGER_CST) + { + auto upper_wi = wi::to_wide (upper).to_shwi (); + auto lower_wi = wi::to_wide (lower).to_shwi (); + if (lower_wi >= upper_wi) + error_E0579 = true; + } + + if (error_E0579) + rust_error_at (pattern.get_locus (), ErrorCode::E0579, + "lower range bound must be less than upper"); + ComparisonOperator upper_cmp = pattern.is_inclusive_range () ? ComparisonOperator::LESS_OR_EQUAL : ComparisonOperator::LESS_THAN; diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index c33d0b0..5f30662 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -132,10 +132,8 @@ ResolvePathRef::resolve_with_node_id ( tl::optional<HirId> hid = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id); if (!hid.has_value ()) - { - rust_error_at (expr_locus, "reverse call path lookup failure"); - return error_mark_node; - } + return error_mark_node; + auto ref = hid.value (); // might be a constant @@ -189,6 +187,17 @@ ResolvePathRef::resolve_with_node_id ( } } + // possibly a const expr value + if (lookup->get_kind () == TyTy::TypeKind::CONST) + { + auto d = lookup->destructure (); + rust_assert (d->get_kind () == TyTy::TypeKind::CONST); + auto c = d->as_const_type (); + rust_assert (c->const_kind () == TyTy::BaseConstType::ConstKind::Value); + auto val = static_cast<TyTy::ConstValueType *> (c); + return val->get_value (); + } + // Handle unit struct tree resolved_item = error_mark_node; if (lookup->get_kind () == TyTy::TypeKind::ADT) @@ -203,9 +212,7 @@ ResolvePathRef::resolve_with_node_id ( resolved_item = query_compile (ref, lookup, final_segment, mappings, expr_locus, is_qualified_path); if (resolved_item != error_mark_node) - { - TREE_USED (resolved_item) = 1; - } + TREE_USED (resolved_item) = 1; return resolved_item; } diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index d04f864..e32ba3a 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -3137,7 +3137,7 @@ eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval, { tree lmem = PTRMEM_CST_MEMBER (lhs); tree rmem = PTRMEM_CST_MEMBER (rhs); - bool eq; + bool eq = false; if (TREE_CODE (lmem) == TREE_CODE (rmem) && TREE_CODE (lmem) == FIELD_DECL && TREE_CODE (DECL_CONTEXT (lmem)) == UNION_TYPE 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/feature/rust-feature-gate.cc b/gcc/rust/checks/errors/feature/rust-feature-gate.cc index 44007f9..9df822b 100644 --- a/gcc/rust/checks/errors/feature/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/feature/rust-feature-gate.h b/gcc/rust/checks/errors/feature/rust-feature-gate.h index f1011e5..8ff491c 100644 --- a/gcc/rust/checks/errors/feature/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 index 071d3f8..1a967aa 100644 --- a/gcc/rust/checks/errors/feature/rust-feature.cc +++ b/gcc/rust/checks/errors/feature/rust-feature.cc @@ -20,79 +20,81 @@ 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 (); - } -} +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 = { - {"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}, +#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) { - if (Feature::name_hash_map.count (name)) - return Feature::name_hash_map.at (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)); }); +} - return tl::nullopt; +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 index e7cb0af..8686cf4 100644 --- a/gcc/rust/checks/errors/feature/rust-feature.h +++ b/gcc/rust/checks/errors/feature/rust-feature.h @@ -29,59 +29,55 @@ class Feature public: enum class State { - ACCEPTED, - ACTIVE, - REMOVED, - STABILIZED, + ACCEPTED, // stabilized + ACTIVE, // unstable + REMOVED, // removed + STABILIZED, // removed after stabilization }; 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, +#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 () { 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; } + 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 Feature create (Name 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 *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) + 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) {} - State m_state; Name m_name; + State m_state; std::string m_name_str; - std::string m_rustc_since; + std::string m_rust_since; tl::optional<unsigned> m_issue; tl::optional<Edition> edition; - std::string m_description; // TODO: Switch to optional? + tl::optional<const char *> m_reason; + static Feature feature_list[]; static const std::map<std::string, Name> name_hash_map; }; diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index 55147df..2777f07 100644 --- a/gcc/rust/expand/rust-derive.cc +++ b/gcc/rust/expand/rust-derive.cc @@ -25,6 +25,7 @@ #include "rust-derive-ord.h" #include "rust-derive-partial-eq.h" #include "rust-derive-hash.h" +#include "rust-system.h" namespace Rust { namespace AST { @@ -39,6 +40,16 @@ DeriveVisitor::derive (Item &item, const Attribute &attr, { auto loc = attr.get_locus (); + using Kind = AST::Item::Kind; + auto item_kind = item.get_item_kind (); + if (item_kind != Kind::Enum && item_kind != Kind::Struct + && item_kind != Kind::Union) + { + rust_error_at (loc, + "derive may only be applied to structs, enums and unions"); + return {}; + } + switch (to_derive) { case BuiltinMacro::Clone: diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 4593cc3..6e98a5c 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -18,6 +18,7 @@ #include "rust-expand-visitor.h" #include "rust-ast-fragment.h" +#include "rust-hir-map.h" #include "rust-item.h" #include "rust-proc-macro.h" #include "rust-attributes.h" @@ -48,7 +49,10 @@ static std::vector<std::unique_ptr<AST::Item>> builtin_derive_item (AST::Item &item, const AST::Attribute &derive, BuiltinMacro to_derive) { - return AST::DeriveVisitor::derive (item, derive, to_derive); + auto items = AST::DeriveVisitor::derive (item, derive, to_derive); + for (auto &item : items) + Analysis::Mappings::get ().add_derived_node (item->get_node_id ()); + return items; } static std::vector<std::unique_ptr<AST::Item>> @@ -64,6 +68,8 @@ derive_item (AST::Item &item, AST::SimplePath &to_derive, switch (node.get_kind ()) { case AST::SingleASTNode::Kind::Item: + Analysis::Mappings::get ().add_derived_node ( + node.get_item ()->get_node_id ()); result.push_back (node.take_item ()); break; default: diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 52f8e2b..b47e43a 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -962,12 +962,10 @@ transcribe_expression (Parser<MacroInvocLexer> &parser) auto attrs = parser.parse_outer_attributes (); auto expr = parser.parse_expr (std::move (attrs)); - if (expr == nullptr) - { - for (auto error : parser.get_errors ()) - error.emit (); - return AST::Fragment::create_error (); - } + for (auto error : parser.get_errors ()) + error.emit (); + if (!expr) + return AST::Fragment::create_error (); // FIXME: make this an error for some edititons if (parser.peek_current_token ()->get_id () == SEMICOLON) @@ -997,6 +995,8 @@ transcribe_type (Parser<MacroInvocLexer> &parser) auto type = parser.parse_type (true); for (auto err : parser.get_errors ()) err.emit (); + if (!type) + return AST::Fragment::create_error (); auto end = lexer.get_offs (); @@ -1018,6 +1018,9 @@ transcribe_pattern (Parser<MacroInvocLexer> &parser) for (auto err : parser.get_errors ()) err.emit (); + if (!pattern) + return AST::Fragment::create_error (); + auto end = lexer.get_offs (); return AST::Fragment ({std::move (pattern)}, diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index c3d5e7d..0e79466 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -358,7 +358,7 @@ struct MacroExpander * * @param parser Parser to use for matching * @param rep Repetition to try and match - * @param match_amount Reference in which to store the ammount of succesful + * @param match_amount Reference in which to store the amount of successful * and valid matches * * @param lo_bound Lower bound of the matcher. When specified, the matcher diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 1c8e5b6..8984c98 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -820,9 +820,17 @@ void ASTLoweringBase::handle_doc_item_attribute (const ItemWrapper &, const AST::Attribute &attr) { - auto simple_doc_comment = attr.has_attr_input () - && attr.get_attr_input ().get_attr_input_type () - == AST::AttrInput::AttrInputType::LITERAL; + if (!attr.has_attr_input ()) + { + rust_error_at (attr.get_locus (), + "attribute must be of the form %qs or %qs", + "#[doc(hidden|inline|...)]", "#[doc = string]"); + return; + } + + auto simple_doc_comment = attr.get_attr_input ().get_attr_input_type () + == AST::AttrInput::AttrInputType::LITERAL; + if (simple_doc_comment) return; diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc index 8fd9d16..87f1e01 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.cc +++ b/gcc/rust/hir/rust-ast-lower-implitem.cc @@ -55,11 +55,11 @@ ASTLowerImplItem::translate (AST::AssociatedItem &item, HirId parent_impl_id) void ASTLowerImplItem::visit (AST::TypeAlias &alias) { - std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; + std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (alias.get_visibility ()); - std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + std::vector<std::unique_ptr<HIR::GenericParam>> generic_params; if (alias.has_generics ()) generic_params = lower_generic_params (alias.get_generic_params ()); @@ -110,7 +110,7 @@ void ASTLowerImplItem::visit (AST::Function &function) { // ignore for now and leave empty - std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; + std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; for (auto &item : function.get_where_clause ().get_items ()) { HIR::WhereClauseItem *i @@ -124,7 +124,7 @@ ASTLowerImplItem::visit (AST::Function &function) HIR::Visibility vis = translate_visibility (function.get_visibility ()); // need - std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + std::vector<std::unique_ptr<HIR::GenericParam>> generic_params; if (function.has_generics ()) { generic_params = lower_generic_params (function.get_generic_params ()); @@ -233,12 +233,12 @@ ASTLowerTraitItem::translate (AST::AssociatedItem &item) void ASTLowerTraitItem::visit (AST::Function &func) { - std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; + std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::FunctionQualifiers qualifiers = lower_qualifiers (func.get_qualifiers ()); - std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + std::vector<std::unique_ptr<HIR::GenericParam>> generic_params; if (func.has_generics ()) generic_params = lower_generic_params (func.get_generic_params ()); @@ -342,7 +342,24 @@ ASTLowerTraitItem::visit (AST::ConstantItem &constant) void ASTLowerTraitItem::visit (AST::TraitItemType &type) { - std::vector<std::unique_ptr<HIR::TypeParamBound> > type_param_bounds; + // Lower generic parameters (for GATs) + std::vector<std::unique_ptr<HIR::GenericParam>> generic_params; + for (auto ¶m : type.get_generic_params ()) + { + auto lowered_param = ASTLowerGenericParam::translate (*param.get ()); + generic_params.push_back ( + std::unique_ptr<HIR::GenericParam> (lowered_param)); + } + + // Lower type parameter bounds + std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds; + for (auto &bound : type.get_type_param_bounds ()) + { + auto lowered_bound = lower_bound (*bound.get ()); + type_param_bounds.push_back ( + std::unique_ptr<HIR::TypeParamBound> (lowered_bound)); + } + auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), mappings.get_next_hir_id (crate_num), @@ -350,6 +367,7 @@ ASTLowerTraitItem::visit (AST::TraitItemType &type) HIR::TraitItemType *trait_item = new HIR::TraitItemType (mapping, type.get_identifier (), + std::move (generic_params), std::move (type_param_bounds), type.get_outer_attrs (), type.get_locus ()); translated = trait_item; diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index 4250adb..c941a5c 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -280,7 +280,8 @@ ASTLoweringPattern::visit (AST::LiteralPattern &pattern) HIR::Literal l = lower_literal (pattern.get_literal ()); translated - = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus ()); + = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus (), + pattern.get_has_minus ()); } void diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc index 1406e7a..268b09b 100644 --- a/gcc/rust/hir/tree/rust-hir-item.cc +++ b/gcc/rust/hir/tree/rust-hir-item.cc @@ -716,17 +716,21 @@ TraitItemConst::operator= (TraitItemConst const &other) TraitItemType::TraitItemType ( Analysis::NodeMapping mappings, Identifier name, + std::vector<std::unique_ptr<GenericParam>> generic_params, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds, AST::AttrVec outer_attrs, location_t locus) : TraitItem (mappings), outer_attrs (std::move (outer_attrs)), - name (std::move (name)), type_param_bounds (std::move (type_param_bounds)), - locus (locus) + name (std::move (name)), generic_params (std::move (generic_params)), + type_param_bounds (std::move (type_param_bounds)), locus (locus) {} TraitItemType::TraitItemType (TraitItemType const &other) : TraitItem (other.mappings), outer_attrs (other.outer_attrs), name (other.name), locus (other.locus) { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -741,6 +745,9 @@ TraitItemType::operator= (TraitItemType const &other) locus = other.locus; mappings = other.mappings; + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index eb9cec7..7629406 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -2121,15 +2121,20 @@ class TraitItemType : public TraitItem AST::AttrVec outer_attrs; Identifier name; + // Generic parameters for GATs (Generic Associated Types) + std::vector<std::unique_ptr<GenericParam>> generic_params; std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; // inlined form location_t locus; public: + bool has_generics () const { return !generic_params.empty (); } + // Returns whether trait item type has type param bounds. bool has_type_param_bounds () const { return !type_param_bounds.empty (); } TraitItemType (Analysis::NodeMapping mappings, Identifier name, + std::vector<std::unique_ptr<GenericParam>> generic_params, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds, AST::AttrVec outer_attrs, location_t locus); @@ -2152,6 +2157,15 @@ public: Identifier get_name () const { return name; } + std::vector<std::unique_ptr<GenericParam>> &get_generic_params () + { + return generic_params; + } + const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const + { + return generic_params; + } + std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds () { return type_param_bounds; diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 89b9cc6..a2c408f 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -32,19 +32,27 @@ class LiteralPattern : public Pattern Literal lit; location_t locus; Analysis::NodeMapping mappings; + bool has_minus; public: std::string as_string () const override; // Constructor for a literal pattern LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t locus) - : lit (std::move (lit)), locus (locus), mappings (mappings) + : lit (std::move (lit)), locus (locus), mappings (mappings), + has_minus (false) + {} + + LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t locus, + bool has_minus) + : lit (std::move (lit)), locus (locus), mappings (mappings), + has_minus (has_minus) {} LiteralPattern (Analysis::NodeMapping mappings, std::string val, Literal::LitType type, location_t locus) : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)), - locus (locus), mappings (mappings) + locus (locus), mappings (mappings), has_minus (false) {} location_t get_locus () const override { return locus; } @@ -65,6 +73,8 @@ public: Literal &get_literal () { return lit; } const Literal &get_literal () const { return lit; } + bool get_has_minus () const { return has_minus; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index ce10b02..614fec7 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -2634,7 +2634,7 @@ StructPattern::as_string () const std::string LiteralPattern::as_string () const { - return lit.as_string (); + return (has_minus ? "-" : "") + lit.as_string (); } std::string @@ -3582,6 +3582,18 @@ TraitItemType::as_string () const str += "\ntype " + name.as_string (); + if (has_generics ()) + { + str += "<"; + for (size_t i = 0; i < generic_params.size (); i++) + { + if (i > 0) + str += ", "; + str += generic_params[i]->as_string (); + } + str += ">"; + } + str += "\n Type param bounds: "; if (!has_type_param_bounds ()) { diff --git a/gcc/rust/lang.opt.urls b/gcc/rust/lang.opt.urls index 33a54b4..09cfede 100644 --- a/gcc/rust/lang.opt.urls +++ b/gcc/rust/lang.opt.urls @@ -1,7 +1,7 @@ ; Autogenerated by regenerate-opt-urls.py from gcc/rust/lang.opt and generated HTML I -UrlSuffix(gcc/Directory-Options.html#index-I) LangUrlSuffix_D(gdc/Directory-Options.html#index-I) +UrlSuffix(gcc/Directory-Options.html#index-I) LangUrlSuffix_D(gdc/Directory-Options.html#index-I) LangUrlSuffix_Algol68(ga68/Directory-options.html#index-I) L UrlSuffix(gcc/Directory-Options.html#index-L) LangUrlSuffix_D(gdc/Directory-Options.html#index-L) diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 214161f..a99b5ed 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -2639,37 +2639,37 @@ void rust_input_source_test () { // ASCII - std::string src = u8"_abcde\tXYZ\v\f"; - std::vector<uint32_t> expected - = {'_', 'a', 'b', 'c', 'd', 'e', '\t', 'X', 'Y', 'Z', '\v', '\f'}; + std::string src = (const char *) u8"_abcde\tXYZ\v\f"; + std::vector<uint32_t> expected = {u'_', u'a', u'b', u'c', u'd', u'e', + u'\t', u'X', u'Y', u'Z', u'\v', u'\f'}; test_buffer_input_source (src, expected); // BOM - src = u8"\xef\xbb\xbfOK"; - expected = {'O', 'K'}; + src = (const char *) u8"\xef\xbb\xbfOK"; + expected = {u'O', u'K'}; test_buffer_input_source (src, expected); // Russian - src = u8"приве́т"; - expected = {L'п', - L'р', - L'и', - L'в', + src = (const char *) u8"приве́т"; + expected = {u'п', + u'р', + u'и', + u'в', 0x0435 /* CYRILLIC SMALL LETTER IE е */, 0x301 /* COMBINING ACUTE ACCENT ́ */, - L'т'}; + u'т'}; test_buffer_input_source (src, expected); - src = u8"❤️🦀"; + src = (const char *) u8"❤️🦀"; expected = {0x2764 /* HEAVY BLACK HEART */, - 0xfe0f /* VARIATION SELECTOR-16 */, L'🦀'}; + 0xfe0f /* VARIATION SELECTOR-16 */, U'🦀'}; test_buffer_input_source (src, expected); - src = u8"こんにちは"; - expected = {L'こ', L'ん', L'に', L'ち', L'は'}; + src = (const char *) u8"こんにちは"; + expected = {u'こ', u'ん', u'に', u'ち', u'は'}; test_file_input_source (src, expected); - src = u8"👮♂👩⚕"; + src = (const char *) u8"👮♂👩⚕"; expected = {0x1f46e /* POLICE OFFICER */, 0x200d /* ZERO WIDTH JOINER */, 0x2642 /* MALE SIGN */, 0x1f469 /* WOMAN */, diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc index 4dfc280..a8d4af1 100644 --- a/gcc/rust/metadata/rust-export-metadata.cc +++ b/gcc/rust/metadata/rust-export-metadata.cc @@ -23,6 +23,7 @@ #include "rust-ast-dump.h" #include "rust-abi.h" #include "rust-item.h" +#include "rust-macro.h" #include "rust-object-export.h" #include "md5.h" @@ -111,14 +112,12 @@ ExportContext::emit_function (const HIR::Function &fn) } void -ExportContext::emit_macro (NodeId macro) +ExportContext::emit_macro (AST::MacroRulesDefinition ¯o) { std::stringstream oss; AST::Dump dumper (oss); - AST::Item *item = mappings.lookup_ast_item (macro).value (); - - dumper.go (*item); + dumper.go (macro); public_interface_buffer += oss.str (); } @@ -195,7 +194,7 @@ PublicInterface::gather_export_data () vis_item.accept_vis (visitor); } - for (const auto ¯o : mappings.get_exported_macros ()) + for (auto ¯o : mappings.get_exported_macros ()) context.emit_macro (macro); } diff --git a/gcc/rust/metadata/rust-export-metadata.h b/gcc/rust/metadata/rust-export-metadata.h index ee006cd..7747d95 100644 --- a/gcc/rust/metadata/rust-export-metadata.h +++ b/gcc/rust/metadata/rust-export-metadata.h @@ -48,7 +48,7 @@ public: * directly refer to them using their NodeId. There's no need to keep an HIR * node for them. */ - void emit_macro (NodeId macro); + void emit_macro (AST::MacroRulesDefinition ¯o); const std::string &get_interface_buffer () const; diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index ec4c1c1..6cb8f0e 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -431,10 +431,6 @@ Parser<ManagedTokenSource>::parse_items () std::unique_ptr<AST::Item> item = parse_item (false); if (item == nullptr) { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse item in crate"); - add_error (std::move (error)); - // TODO: should all items be cleared? items = std::vector<std::unique_ptr<AST::Item>> (); break; @@ -982,16 +978,7 @@ Parser<ManagedTokenSource>::parse_delim_token_tree () std::unique_ptr<AST::TokenTree> tok_tree = parse_token_tree (); if (tok_tree == nullptr) - { - // TODO: is this error handling appropriate? - Error error ( - t->get_locus (), - "failed to parse token tree in delimited token tree - found %qs", - t->get_token_description ()); - add_error (std::move (error)); - - return AST::DelimTokenTree::create_empty (); - } + return AST::DelimTokenTree::create_empty (); token_trees_in_tree.push_back (std::move (tok_tree)); @@ -1079,11 +1066,12 @@ Parser<ManagedTokenSource>::parse_token_tree () case RIGHT_SQUARE: case RIGHT_CURLY: // error - should not be called when this a token - add_error ( - Error (t->get_locus (), - "unexpected closing delimiter %qs - token tree requires " - "either paired delimiters or non-delimiter tokens", - t->get_token_description ())); + add_error (Error (t->get_locus (), "unexpected closing delimiter %qs", + t->get_token_description ())); + + add_error (Error (Error::Kind::Hint, t->get_locus (), + "token tree requires either paired delimiters or " + "non-delimiter tokens")); lexer.skip_token (); return nullptr; @@ -1861,20 +1849,13 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi ( t = lexer.peek_token (); // parse token trees until the initial delimiter token is found again - while (!token_id_matches_delims (t->get_id (), delim_type)) + while (!token_id_matches_delims (t->get_id (), delim_type) + && t->get_id () != END_OF_FILE) { std::unique_ptr<AST::TokenTree> tree = parse_token_tree (); if (tree == nullptr) - { - Error error (t->get_locus (), - "failed to parse token tree for macro invocation semi " - "- found %qs", - t->get_token_description ()); - add_error (std::move (error)); - - return nullptr; - } + return nullptr; token_trees.push_back (std::move (tree)); @@ -3010,8 +2991,9 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis, else { std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr (); - if (block_expr != nullptr) - body = std::move (block_expr); + if (block_expr == nullptr) + return nullptr; + body = std::move (block_expr); } return std::unique_ptr<AST::Function> ( @@ -3262,8 +3244,12 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token) // Did we parse a generic type param yet auto type_seen = false; + // Did we parse a const param with a default value yet + auto const_with_default_seen = false; // Did the user write a lifetime parameter after a type one auto order_error = false; + // Did the user write a const param with a default value after a type one + auto const_with_default_order_error = false; // parse lifetime params while (!is_end_token (lexer.peek_token ()->get_id ())) @@ -3271,12 +3257,29 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token) auto param = parse_generic_param (is_end_token); if (param) { - // TODO: Handle `Const` here as well if necessary if (param->get_kind () == AST::GenericParam::Kind::Type) - type_seen = true; + { + type_seen = true; + if (const_with_default_seen) + const_with_default_order_error = true; + } else if (param->get_kind () == AST::GenericParam::Kind::Lifetime && type_seen) - order_error = true; + { + order_error = true; + if (const_with_default_seen) + const_with_default_order_error = true; + } + else if (param->get_kind () == AST::GenericParam::Kind::Const) + { + type_seen = true; + AST::ConstGenericParam *const_param + = static_cast<AST::ConstGenericParam *> (param.get ()); + if (const_param->has_default_value ()) + const_with_default_seen = true; + else if (const_with_default_seen) + const_with_default_order_error = true; + } generic_params.emplace_back (std::move (param)); maybe_skip_token (COMMA); @@ -3293,6 +3296,13 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token) "must be declared prior to type and const parameters"); add_error (std::move (error)); } + if (const_with_default_order_error) + { + Error error (generic_params.front ()->get_locus (), + "invalid order for generic parameters: generic parameters " + "with a default must be trailing"); + add_error (std::move (error)); + } generic_params.shrink_to_fit (); return generic_params; @@ -5193,6 +5203,13 @@ Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs, Identifier ident{ident_tok}; + // Parse optional generic parameters for GATs (Generic Associated Types) + std::vector<std::unique_ptr<AST::GenericParam>> generic_params; + if (lexer.peek_token ()->get_id () == LEFT_ANGLE) + { + generic_params = parse_generic_params_in_angles (); + } + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; // parse optional colon @@ -5213,8 +5230,9 @@ Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs, } return std::unique_ptr<AST::TraitItemType> ( - new AST::TraitItemType (std::move (ident), std::move (bounds), - std::move (outer_attrs), vis, locus)); + new AST::TraitItemType (std::move (ident), std::move (generic_params), + std::move (bounds), std::move (outer_attrs), vis, + locus)); } // Parses a constant trait item. @@ -6201,10 +6219,6 @@ Parser<ManagedTokenSource>::parse_let_stmt (AST::AttrVec outer_attrs, expr = parse_expr (); if (expr == nullptr) { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse expression in let statement"); - add_error (std::move (error)); - skip_after_semicolon (); return nullptr; } @@ -7231,11 +7245,7 @@ Parser<ManagedTokenSource>::parse_block_expr ( ExprOrStmt expr_or_stmt = parse_stmt_or_expr (); if (expr_or_stmt.is_error ()) { - Error error ( - t->get_locus (), - "failed to parse statement or expression in block expression"); - add_error (std::move (error)); - + skip_after_end_block (); return nullptr; } @@ -7758,14 +7768,7 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs, // parse required block expr std::unique_ptr<AST::BlockExpr> if_body = parse_block_expr (); if (if_body == nullptr) - { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse if body block expression in if expression"); - add_error (std::move (error)); - - // skip somewhere? - return nullptr; - } + return nullptr; // branch to parse end or else (and then else, else if, or else if let) if (lexer.peek_token ()->get_id () != ELSE) @@ -8088,13 +8091,7 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs, // parse loop body, which is required std::unique_ptr<AST::BlockExpr> loop_body = parse_block_expr (); if (loop_body == nullptr) - { - Error error (lexer.peek_token ()->get_locus (), - "could not parse loop body in (infinite) loop expression"); - add_error (std::move (error)); - - return nullptr; - } + return nullptr; return std::unique_ptr<AST::LoopExpr> ( new AST::LoopExpr (std::move (loop_body), locus, std::move (label), @@ -8206,7 +8203,14 @@ Parser<ManagedTokenSource>::parse_while_let_loop_expr ( // parse predicate patterns std::vector<std::unique_ptr<AST::Pattern>> predicate_patterns = parse_match_arm_patterns (EQUAL); - // TODO: have to ensure that there is at least 1 pattern? + // ensure that there is at least 1 pattern + if (predicate_patterns.empty ()) + { + Error error (lexer.peek_token ()->get_locus (), + "should be at least 1 pattern"); + add_error (std::move (error)); + return nullptr; + } if (!skip_token (EQUAL)) { @@ -10345,7 +10349,7 @@ Parser<ManagedTokenSource>::parse_literal_or_range_pattern () return std::unique_ptr<AST::LiteralPattern> ( new AST::LiteralPattern (range_lower->get_str (), type, range_lower->get_locus (), - range_lower->get_type_hint ())); + range_lower->get_type_hint (), has_minus)); } } @@ -12166,6 +12170,8 @@ Parser<ManagedTokenSource>::parse_expr (int right_binding_power, // parse null denotation (unary part of expression) std::unique_ptr<AST::Expr> expr = null_denotation ({}, null_denotation_restrictions); + if (expr == nullptr) + return nullptr; return left_denotations (std::move (expr), right_binding_power, std::move (outer_attrs), restrictions); diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 95ca7a9..99496e6 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -349,18 +349,18 @@ void global_variable_set_init (Bvariable *, tree); // the function, as otherwise the variable would be on the heap). // LOCATION is where the variable is defined. For each local variable // the frontend will call init_statement to set the initial value. -Bvariable *local_variable (tree function, GGC::Ident name, tree type, - Bvariable *decl_var, location_t location); +LocalVariable local_variable (tree function, GGC::Ident name, tree type, + Bvariable *decl_var, location_t location); // Create a function parameter. This is an incoming parameter, not // a result parameter (result parameters are treated as local // variables). The arguments are as for local_variable. -Bvariable *parameter_variable (tree function, GGC::Ident name, tree type, - location_t location); +LocalVariable parameter_variable (tree function, GGC::Ident name, tree type, + location_t location); // Create a static chain parameter. This is the closure parameter. -Bvariable *static_chain_variable (tree function, GGC::Ident name, tree type, - location_t location); +LocalVariable static_chain_variable (tree function, GGC::Ident name, tree type, + location_t location); // Create a temporary variable. A temporary variable has no name, // just a type. We pass in FUNCTION and BLOCK in case they are @@ -373,9 +373,9 @@ Bvariable *static_chain_variable (tree function, GGC::Ident name, tree type, // variable, and may not be very useful. This function should // return a variable which can be referenced later and should set // *PSTATEMENT to a statement which initializes the variable. -Bvariable *temporary_variable (tree fndecl, tree bind_tree, tree type, - tree init, bool address_is_taken, - location_t location, tree *pstatement); +LocalVariable temporary_variable (tree fndecl, tree bind_tree, tree type, + tree init, bool address_is_taken, + location_t location, tree *pstatement); // Labels. diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 8f950d17..750c392 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -83,6 +83,23 @@ Bvariable::error_variable () return new Bvariable (error_mark_node); } +// Get the tree of a variable for use as an expression +tree +LocalVariable::get_tree (location_t location) const +{ + if (error_operand_p (t)) + return error_mark_node; + + TREE_USED (t) = 1; + return t; +} + +LocalVariable +LocalVariable::error_variable () +{ + return LocalVariable (error_mark_node); +} + // This file implements the interface between the Rust frontend proper // and the gcc IR. This implements specific instantiations of // abstract classes defined by the Rust frontend proper. The Rust @@ -2014,12 +2031,12 @@ global_variable_set_init (Bvariable *var, tree expr_tree) // Make a local variable. -Bvariable * +LocalVariable local_variable (tree function, GGC::Ident name, tree type_tree, Bvariable *decl_var, location_t location) { if (error_operand_p (type_tree)) - return Bvariable::error_variable (); + return LocalVariable::error_variable (); tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree); DECL_CONTEXT (decl) = function; @@ -2029,33 +2046,33 @@ local_variable (tree function, GGC::Ident name, tree type_tree, SET_DECL_VALUE_EXPR (decl, decl_var->get_decl ()); } rust_preserve_from_gc (decl); - return new Bvariable (decl); + return LocalVariable (decl); } // Make a function parameter variable. -Bvariable * +LocalVariable parameter_variable (tree function, GGC::Ident name, tree type_tree, location_t location) { if (error_operand_p (type_tree)) - return Bvariable::error_variable (); + return LocalVariable::error_variable (); tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree); DECL_CONTEXT (decl) = function; DECL_ARG_TYPE (decl) = type_tree; rust_preserve_from_gc (decl); - return new Bvariable (decl); + return LocalVariable (decl); } // Make a static chain variable. -Bvariable * +LocalVariable static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree, location_t location) { if (error_operand_p (type_tree)) - return Bvariable::error_variable (); + return LocalVariable::error_variable (); tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree); DECL_CONTEXT (decl) = fndecl; DECL_ARG_TYPE (decl) = type_tree; @@ -2076,12 +2093,12 @@ static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree, DECL_STATIC_CHAIN (fndecl) = 1; rust_preserve_from_gc (decl); - return new Bvariable (decl); + return LocalVariable (decl); } // Make a temporary variable. -Bvariable * +LocalVariable temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree, bool is_address_taken, location_t location, tree *pstatement) @@ -2091,7 +2108,7 @@ temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree, || error_operand_p (fndecl)) { *pstatement = error_mark_node; - return Bvariable::error_variable (); + return LocalVariable::error_variable (); } tree var; @@ -2141,7 +2158,7 @@ temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree, || TREE_TYPE (init_tree) == void_type_node)) *pstatement = compound_statement (init_tree, *pstatement); - return new Bvariable (var); + return LocalVariable (var); } // Make a label. diff --git a/gcc/rust/rust-gcc.h b/gcc/rust/rust-gcc.h index b3f0325..1ff7c5b 100644 --- a/gcc/rust/rust-gcc.h +++ b/gcc/rust/rust-gcc.h @@ -59,4 +59,28 @@ private: tree orig_type_; }; +// like Bvariable, but orig_type_ == nullptr always holds +// could be any variable which isn't a zero-sized global +class LocalVariable +{ +public: + LocalVariable (tree t) : t (t) {} + + // Get the tree for use as an expression. + tree get_tree (location_t) const; + + // Get the actual decl; + tree get_decl () const { return t; } + + // Create an error variable. This is used for cases which should + // not occur in a correct program, in order to keep the compilation + // going without crashing. + static LocalVariable error_variable (); + + operator Bvariable * () const { return new Bvariable (t); } + +private: + tree t; +}; + #endif // RUST_GCC diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 7885dfc..1c00fd96 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -53,10 +53,19 @@ TypeCheckExpr::Resolve (HIR::Expr &expr) if (resolver.infered == nullptr) return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); - auto ref = expr.get_mappings ().get_hirid (); - resolver.infered->set_ref (ref); + if (resolver.infered->get_kind () != TyTy::TypeKind::CONST) + { + auto ref = expr.get_mappings ().get_hirid (); + resolver.infered->set_ref (ref); + } resolver.context->insert_type (expr.get_mappings (), resolver.infered); + if (auto fn = resolver.infered->try_as<const TyTy::FnType> ()) + { + if (fn->is_syn_constant ()) + resolver.infered = fn->get_return_type (); + } + return resolver.infered; } @@ -2358,7 +2367,12 @@ bool TypeCheckExpr::validate_arithmetic_type ( const TyTy::BaseType *tyty, HIR::ArithmeticOrLogicalExpr::ExprType expr_type) { - const TyTy::BaseType *type = tyty->destructure (); + auto type = tyty->destructure (); + if (type->get_kind () == TyTy::TypeKind::CONST) + { + auto base_const = type->as_const_type (); + type = base_const->get_specified_type (); + } // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators // this will change later when traits are added diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index e7f6632..8df8a18 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -391,8 +391,32 @@ TypeCheckImplItem::visit (HIR::ConstantItem &constant) TyTy::TyWithLocation (type, constant.get_type ().get_locus ()), TyTy::TyWithLocation (expr_type, constant.get_expr ().get_locus ()), constant.get_locus ()); - context->insert_type (constant.get_mappings (), unified); - result = unified; + + if (substitutions.empty ()) + { + context->insert_type (constant.get_mappings (), unified); + result = unified; + return; + } + + // special case when this is a generic constant + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ()); + RustIdent ident{canonical_path, constant.get_locus ()}; + auto fnType = new TyTy::FnType ( + constant.get_mappings ().get_hirid (), + constant.get_mappings ().get_defid (), + constant.get_identifier ().as_string (), ident, + TyTy::FnType::FNTYPE_IS_SYN_CONST_FLAG, ABI::RUST, {}, unified, + std::move (substitutions), + TyTy::SubstitutionArgumentMappings::empty ( + context->get_lifetime_resolver ().get_num_bound_regions ()), + {}); + + context->insert_type (constant.get_mappings (), fnType); + result = fnType; } void @@ -495,6 +519,12 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant) void TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) { + auto binder_pin = context->push_lifetime_binder (); + + if (type.has_generics ()) + resolve_generic_params (HIR::Item::ItemKind::TypeAlias, type.get_locus (), + type.get_generic_params (), substitutions); + // normal resolution of the item TyTy::BaseType *lookup = TypeCheckImplItem::Resolve (parent, type, self, substitutions); @@ -558,6 +588,8 @@ TypeCheckImplItemWithTrait::visit (HIR::Function &function) // normal resolution of the item TyTy::BaseType *lookup = TypeCheckImplItem::Resolve (parent, function, self, substitutions); + if (lookup == nullptr) + return; // map the impl item to the associated trait item const auto tref = trait_reference.get (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 4987c88a..ee5c4e9 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -112,17 +112,27 @@ TypeCheckItem::ResolveImplBlockSelfWithInference ( std::vector<TyTy::SubstitutionArg> args; for (auto &p : substitutions) { - if (p.needs_substitution ()) + auto param = p.get_param_ty (); + if (!p.needs_substitution ()) { - TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus); - args.emplace_back (&p, infer_var.get_tyty ()); + auto resolved = param->destructure (); + args.emplace_back (&p, resolved); + + continue; + } + + TyTy::BaseType *argument = nullptr; + if (param->get_kind () == TyTy::TypeKind::CONST) + { + auto i = TyTy::TyVar::get_implicit_const_infer_var (locus); + argument = i.get_tyty (); } else { - auto param = p.get_param_ty (); - auto resolved = param->destructure (); - args.emplace_back (&p, resolved); + auto i = TyTy::TyVar::get_implicit_infer_var (locus); + argument = i.get_tyty (); } + args.emplace_back (&p, argument); } // create argument mappings diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 799efc8..ca7ef47 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -704,7 +704,6 @@ TypeCheckType::visit (HIR::ArrayType &type) TyTy::BaseType *expected_ty = nullptr; bool ok = context->lookup_builtin ("usize", &expected_ty); rust_assert (ok); - context->insert_type (type.get_size_expr ().get_mappings (), expected_ty); TyTy::BaseConstType *const_type = nullptr; if (capacity_type->get_kind () == TyTy::TypeKind::CONST) @@ -745,7 +744,7 @@ TypeCheckType::visit (HIR::ArrayType &type) translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (), TyTy::TyVar ( - const_type->as_base_type ()->get_ty_ref ()), + const_type->as_base_type ()->get_ref ()), TyTy::TyVar (element_type->get_ref ())); } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 64f4314..3215f434 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -237,19 +237,20 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const : Mutability::Mut; rust_assert (self_param.has_lifetime ()); + auto region = TyTy::Region::make_anonymous (); auto maybe_region = context->lookup_and_resolve_lifetime ( self_param.get_lifetime ()); - - if (!maybe_region.has_value ()) + if (maybe_region.has_value ()) + region = maybe_region.value (); + else { rust_error_at (self_param.get_locus (), "failed to resolve lifetime"); - return get_error (); } + self_type = new TyTy::ReferenceType ( self_param.get_mappings ().get_hirid (), - TyTy::TyVar (self->get_ref ()), mutability, - maybe_region.value ()); + TyTy::TyVar (self->get_ref ()), mutability, region); } break; diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index 6f30ebf..a6b9966 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -221,13 +221,13 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, } else if (cleanup) { - // FIXME - // reset the get_next_hir_id - for (auto &i : infers) { - i.param->set_ref (i.pref); - i.param->set_ty_ref (i.ptyref); + if (i.param != nullptr) + { + i.param->set_ref (i.pref); + i.param->set_ty_ref (i.ptyref); + } // remove the inference variable context.clear_type (i.infer); diff --git a/gcc/rust/typecheck/rust-tyty-bounds.h b/gcc/rust/typecheck/rust-tyty-bounds.h deleted file mode 100644 index 6392af1..0000000 --- a/gcc/rust/typecheck/rust-tyty-bounds.h +++ /dev/null @@ -1,66 +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_TYTY_BOUNDS_H -#define RUST_TYTY_BOUNDS_H - -#include "rust-location.h" -#include "rust-mapping-common.h" - -namespace Rust { - -namespace Resolver { -class TraitReference; -class TraitItemReference; -class AssociatedImplTrait; -} // namespace Resolver - -namespace TyTy { - -class BaseType; -class TypeBoundPredicate; -class TypeBoundsMappings -{ -protected: - TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds); - -public: - std::vector<TypeBoundPredicate> &get_specified_bounds (); - - const std::vector<TypeBoundPredicate> &get_specified_bounds () const; - - TypeBoundPredicate lookup_predicate (DefId id); - - size_t num_specified_bounds () const; - - std::string raw_bounds_as_string () const; - - std::string bounds_as_string () const; - - std::string raw_bounds_as_name () const; - -protected: - void add_bound (TypeBoundPredicate predicate); - - std::vector<TypeBoundPredicate> specified_bounds; -}; - -} // namespace TyTy -} // namespace Rust - -#endif // RUST_TYTY_BOUNDS_H diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h index c1bc96a..d09e180 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.h +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -22,7 +22,6 @@ #include "rust-system.h" #include "rust-location.h" #include "rust-hir-full-decls.h" -#include "rust-tyty-bounds.h" #include "rust-tyty-region.h" #include "rust-ast.h" #include "optional.h" diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc index 72761d9..b780eaa 100644 --- a/gcc/rust/typecheck/rust-tyty-util.cc +++ b/gcc/rust/typecheck/rust-tyty-util.cc @@ -62,14 +62,15 @@ TyVar::get_implicit_infer_var (location_t locus) } TyVar -TyVar::get_implicit_const_infer_var (location_t locus) +TyVar::get_implicit_const_infer_var (location_t locus, TyVar *implicit_type) { auto &mappings = Analysis::Mappings::get (); auto context = Resolver::TypeCheckContext::get (); - TyVar ty_infer = get_implicit_infer_var (locus); + TyVar it = (implicit_type != nullptr) ? *implicit_type + : get_implicit_infer_var (locus); HirId next = mappings.get_next_hir_id (); - auto infer = new ConstInferType (ty_infer.get_tyty (), next, next, {}); + auto infer = new ConstInferType (it.get_tyty (), next, next, {}); context->insert_implicit_type (infer->get_ref (), infer); mappings.insert_location (infer->get_ref (), locus); diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h index 26101fd..b132487 100644 --- a/gcc/rust/typecheck/rust-tyty-util.h +++ b/gcc/rust/typecheck/rust-tyty-util.h @@ -43,7 +43,8 @@ public: static TyVar get_implicit_infer_var (location_t locus); - static TyVar get_implicit_const_infer_var (location_t locus); + static TyVar get_implicit_const_infer_var (location_t locus, + TyVar *implicit_type = nullptr); static TyVar subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst); diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index da5c350..5386b72 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -785,11 +785,18 @@ BaseType::is_concrete () const { const TyTy::BaseType *x = destructure (); - if (x->is<ParamType> () || x->is<ProjectionType> () - || x->is<ConstParamType> ()) + if (x->is<ParamType> () || x->is<ProjectionType> ()) { return false; } + else if (x->get_kind () == TyTy::TypeKind::CONST) + { + auto p = x->as_const_type (); + if (p->const_kind () == BaseConstType::ConstKind::Decl) + return false; + + return true; + } // placeholder is a special case for this case when it is not resolvable // it means we its just an empty placeholder associated type which is // concrete @@ -883,7 +890,7 @@ BaseType::is_concrete () const bool BaseType::has_substitutions_defined () const { - const TyTy::BaseType *x = destructure (); + const auto x = this; switch (x->get_kind ()) { case INFER: @@ -3633,9 +3640,8 @@ ConstParamType::get_name () const return get_symbol (); BaseType *lookup = resolve (); - // Avoid infinite recursion if resolve() returns this same type if (lookup == this->as_base_type ()) - return get_symbol (); + return get_symbol () + ":" + get_specified_type ()->get_name (); return lookup->get_name (); } @@ -3660,9 +3666,25 @@ ConstParamType::is_equal (const BaseType &other) const return false; if (can_resolve ()) - return Resolver::types_compatable (TyTy::TyWithLocation (resolve ()), - TyTy::TyWithLocation (other2.resolve ()), - ident.locus, false); + { + // Compare the resolved ty_ref values to avoid infinite recursion + // through types_compatable/unification + BaseType *lhs = resolve (); + BaseType *rhs = other2.resolve (); + + // If they resolve to the same type (same ty_ref), they're equal + if (lhs->get_ty_ref () == rhs->get_ty_ref ()) + return true; + + // Otherwise check if the resolved types are equal + // Avoid recursion by checking if we'd be comparing ConstParamTypes again + if (lhs->get_kind () == TypeKind::CONST + && lhs->as_const_type ()->const_kind () + == BaseConstType::ConstKind::Decl) + return false; // Would cause recursion, so not equal + + return lhs->is_equal (*rhs); + } return get_symbol ().compare (other2.get_symbol ()) == 0; } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 3236bf3..50f6347 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -24,7 +24,6 @@ #include "rust-common.h" #include "rust-identifier.h" #include "rust-abi.h" -#include "rust-tyty-bounds.h" #include "rust-tyty-util.h" #include "rust-tyty-subst.h" #include "rust-tyty-region.h" @@ -92,6 +91,127 @@ public: class TyVisitor; class TyConstVisitor; class BaseConstType; + +class TypeBoundPredicate : public SubstitutionRef +{ +public: + TypeBoundPredicate (const Resolver::TraitReference &trait_reference, + BoundPolarity polarity, location_t locus); + + TypeBoundPredicate (DefId reference, + std::vector<SubstitutionParamMapping> substitutions, + BoundPolarity polarity, location_t locus); + + TypeBoundPredicate (const TypeBoundPredicate &other); + + virtual ~TypeBoundPredicate () {} + + TypeBoundPredicate &operator= (const TypeBoundPredicate &other); + + static TypeBoundPredicate error (); + + std::string as_string () const; + + std::string as_name () const; + + const Resolver::TraitReference *get () const; + + location_t get_locus () const { return locus; } + + std::string get_name () const; + + // check that this is object-safe see: + // https://doc.rust-lang.org/reference/items/traits.html#object-safety + bool is_object_safe (bool emit_error, location_t locus) const; + + void apply_generic_arguments (HIR::GenericArgs *generic_args, + bool has_associated_self, bool is_super_trait); + + void apply_argument_mappings (SubstitutionArgumentMappings &arguments, + bool is_super_trait); + + bool contains_item (const std::string &search) const; + + tl::optional<TypeBoundPredicateItem> + lookup_associated_item (const std::string &search) const; + + tl::optional<TypeBoundPredicateItem> + lookup_associated_item (const Resolver::TraitItemReference *ref) const; + + // WARNING THIS WILL ALWAYS RETURN NULLPTR + BaseType * + handle_substitions (SubstitutionArgumentMappings &mappings) override final; + + bool is_error () const; + + bool requires_generic_args () const; + + bool contains_associated_types () const; + + DefId get_id () const { return reference; } + + BoundPolarity get_polarity () const { return polarity; } + + std::vector<TypeBoundPredicateItem> get_associated_type_items (); + + size_t get_num_associated_bindings () const override final; + + TypeBoundPredicateItem + lookup_associated_type (const std::string &search) override final; + + bool is_equal (const TypeBoundPredicate &other) const; + + bool validate_type_implements_super_traits (TyTy::BaseType &self, + HIR::Type &impl_type, + HIR::Type &trait) const; + + bool validate_type_implements_this (TyTy::BaseType &self, + HIR::Type &impl_type, + HIR::Type &trait) const; + +private: + struct mark_is_error + { + }; + + TypeBoundPredicate (mark_is_error); + + void get_trait_hierachy ( + std::function<void (const Resolver::TraitReference &)> callback) const; + + DefId reference; + location_t locus; + bool error_flag; + BoundPolarity polarity; + std::vector<TyTy::TypeBoundPredicate> super_traits; +}; + +class TypeBoundsMappings +{ +protected: + TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds); + +public: + std::vector<TypeBoundPredicate> &get_specified_bounds (); + + const std::vector<TypeBoundPredicate> &get_specified_bounds () const; + + TypeBoundPredicate lookup_predicate (DefId id); + + size_t num_specified_bounds () const; + + std::string raw_bounds_as_string () const; + + std::string bounds_as_string () const; + + std::string raw_bounds_as_name () const; + +protected: + void add_bound (TypeBoundPredicate predicate); + + std::vector<TypeBoundPredicate> specified_bounds; +}; + class BaseType : public TypeBoundsMappings { public: @@ -671,100 +791,6 @@ private: std::vector<TyVar> fields; }; -class TypeBoundPredicate : public SubstitutionRef -{ -public: - TypeBoundPredicate (const Resolver::TraitReference &trait_reference, - BoundPolarity polarity, location_t locus); - - TypeBoundPredicate (DefId reference, - std::vector<SubstitutionParamMapping> substitutions, - BoundPolarity polarity, location_t locus); - - TypeBoundPredicate (const TypeBoundPredicate &other); - - virtual ~TypeBoundPredicate () {} - - TypeBoundPredicate &operator= (const TypeBoundPredicate &other); - - static TypeBoundPredicate error (); - - std::string as_string () const; - - std::string as_name () const; - - const Resolver::TraitReference *get () const; - - location_t get_locus () const { return locus; } - - std::string get_name () const; - - // check that this is object-safe see: - // https://doc.rust-lang.org/reference/items/traits.html#object-safety - bool is_object_safe (bool emit_error, location_t locus) const; - - void apply_generic_arguments (HIR::GenericArgs *generic_args, - bool has_associated_self, bool is_super_trait); - - void apply_argument_mappings (SubstitutionArgumentMappings &arguments, - bool is_super_trait); - - bool contains_item (const std::string &search) const; - - tl::optional<TypeBoundPredicateItem> - lookup_associated_item (const std::string &search) const; - - tl::optional<TypeBoundPredicateItem> - lookup_associated_item (const Resolver::TraitItemReference *ref) const; - - // WARNING THIS WILL ALWAYS RETURN NULLPTR - BaseType * - handle_substitions (SubstitutionArgumentMappings &mappings) override final; - - bool is_error () const; - - bool requires_generic_args () const; - - bool contains_associated_types () const; - - DefId get_id () const { return reference; } - - BoundPolarity get_polarity () const { return polarity; } - - std::vector<TypeBoundPredicateItem> get_associated_type_items (); - - size_t get_num_associated_bindings () const override final; - - TypeBoundPredicateItem - lookup_associated_type (const std::string &search) override final; - - bool is_equal (const TypeBoundPredicate &other) const; - - bool validate_type_implements_super_traits (TyTy::BaseType &self, - HIR::Type &impl_type, - HIR::Type &trait) const; - - bool validate_type_implements_this (TyTy::BaseType &self, - HIR::Type &impl_type, - HIR::Type &trait) const; - -private: - struct mark_is_error - { - }; - - TypeBoundPredicate (mark_is_error); - - void get_trait_hierachy ( - std::function<void (const Resolver::TraitReference &)> callback) const; - - DefId reference; - location_t locus; - bool error_flag; - BoundPolarity polarity; - std::vector<TyTy::TypeBoundPredicate> super_traits; -}; - class TypeBoundPredicateItem { public: @@ -1050,6 +1076,7 @@ public: static const uint8_t FNTYPE_IS_METHOD_FLAG = 0x01; static const uint8_t FNTYPE_IS_EXTERN_FLAG = 0x02; static const uint8_t FNTYPE_IS_VARADIC_FLAG = 0X04; + static const uint8_t FNTYPE_IS_SYN_CONST_FLAG = 0X08; FnType (HirId ref, DefId id, std::string identifier, RustIdent ident, uint8_t flags, ABI abi, std::vector<FnParam> params, BaseType *type, @@ -1111,6 +1138,11 @@ public: bool is_variadic () const { return (flags & FNTYPE_IS_VARADIC_FLAG) != 0; } + bool is_syn_constant () const + { + return (flags & FNTYPE_IS_SYN_CONST_FLAG) != 0; + } + DefId get_id () const { return id; } // get the Self type for the method diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 43dd6dc..36dbc0e 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -18,8 +18,8 @@ #include "rust-unify.h" #include "fold-const.h" +#include "rust-tyty-util.h" #include "rust-tyty.h" -#include "tree.h" namespace Rust { namespace Resolver { @@ -302,35 +302,67 @@ UnifyRules::go () else if (ltype->get_kind () == TyTy::TypeKind::CONST && rtype->get_kind () == TyTy::TypeKind::CONST) { - const auto &lhs = *ltype->as_const_type (); - const auto &rhs = *rtype->as_const_type (); + auto lhs = ltype->as_const_type (); + auto rhs = rtype->as_const_type (); bool both_are_decls - = lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl - && rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl; + = lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl + && rhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl; bool have_decls - = lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl - || rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl; + = lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl + || rhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl; if (have_decls && !both_are_decls) { - if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) + if (lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl) { - TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var ( - lhs.as_base_type ()->get_locus ()); - ltype = iv.get_tyty (); + auto l = lhs->as_base_type ()->get_locus (); + auto p = static_cast<TyTy::ConstParamType *> (lhs); + auto it = TyTy::TyVar::get_implicit_infer_var (l); + auto iv = TyTy::TyVar::get_implicit_const_infer_var (l, &it); + auto ivt = iv.get_tyty (); + + infers.emplace_back (0, 0, nullptr, it.get_tyty ()); + infers.emplace_back (ltype->get_ref (), ltype->get_ty_ref (), + p, ivt); + + ltype = ivt; + p->set_ty_ref (ltype->get_ref ()); } - else if (rhs.const_kind () + else if (rhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl) { - TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var ( - rhs.as_base_type ()->get_locus ()); - rtype = iv.get_tyty (); + auto l = rhs->as_base_type ()->get_locus (); + auto p = static_cast<TyTy::ConstParamType *> (rhs); + auto it = TyTy::TyVar::get_implicit_infer_var (l); + auto iv = TyTy::TyVar::get_implicit_const_infer_var (l, &it); + auto ivt = iv.get_tyty (); + + infers.emplace_back (0, 0, nullptr, it.get_tyty ()); + infers.emplace_back (rtype->get_ref (), rtype->get_ty_ref (), + p, ivt); + + rtype = ivt; + p->set_ty_ref (rtype->get_ref ()); } } } } + if (ltype->get_kind () != TyTy::TypeKind::CONST + && rtype->get_kind () == TyTy::TypeKind::CONST) + { + auto *rc = rtype->as_const_type (); + rtype = rc->get_specified_type (); + } + + if (ltype->get_kind () == TyTy::TypeKind::CONST + && rtype->get_kind () != TyTy::TypeKind::CONST) + { + auto *lc = ltype->as_const_type (); + ltype = lc->get_specified_type (); + } + switch (ltype->get_kind ()) { case TyTy::INFER: diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h index 4bed24c..2b772fe 100644 --- a/gcc/rust/typecheck/rust-unify.h +++ b/gcc/rust/typecheck/rust-unify.h @@ -30,15 +30,15 @@ class UnifyRules public: struct InferenceSite { - InferenceSite (HirId pref, HirId ptyref, TyTy::ParamType *param, - TyTy::InferType *infer) + InferenceSite (HirId pref, HirId ptyref, TyTy::BaseGeneric *param, + TyTy::BaseType *infer) : pref (pref), ptyref (ptyref), param (param), infer (infer) {} HirId pref; HirId ptyref; - TyTy::ParamType *param; - TyTy::InferType *infer; + TyTy::BaseGeneric *param; + TyTy::BaseType *infer; }; struct CommitSite { diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h index a22664a..0f35f56 100644 --- a/gcc/rust/util/rust-attribute-values.h +++ b/gcc/rust/util/rust-attribute-values.h @@ -49,8 +49,6 @@ public: static constexpr auto &PROC_MACRO_DERIVE = "proc_macro_derive"; static constexpr auto &PROC_MACRO_ATTRIBUTE = "proc_macro_attribute"; - static constexpr auto &DERIVE = "derive"; - static constexpr auto &TARGET_FEATURE = "target_feature"; // From now on, these are reserved by the compiler and gated through // #![feature(rustc_attrs)] diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index 9621100..70f26e7 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -90,8 +90,6 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::PROC_MACRO, EXPANSION}, {Attrs::PROC_MACRO_DERIVE, EXPANSION}, {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION}, - - {Attrs::DERIVE, EXPANSION}, // FIXME: This is not implemented yet, see // https://github.com/Rust-GCC/gccrs/issues/1475 {Attrs::TARGET_FEATURE, CODE_GENERATION}, @@ -101,7 +99,6 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION}, {Attrs::STABLE, STATIC_ANALYSIS}, {Attrs::UNSTABLE, STATIC_ANALYSIS}, - // assuming we keep these for static analysis {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION}, {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS}, @@ -114,23 +111,22 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK}, {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK}, {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK}, - {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION}, - // TODO: be careful about calling functions marked with this? {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION}, - {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}, - {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS}, {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS}, - {Attrs::FUNDAMENTAL, TYPE_CHECK}, {Attrs::NON_EXHAUSTIVE, TYPE_CHECK}, {Attrs::RUSTFMT, EXTERNAL}, - {Attrs::TEST, CODE_GENERATION}}; +static const std::set<std::string> __outer_attributes + = {Attrs::INLINE, Attrs::DERIVE_ATTR, Attrs::ALLOW_INTERNAL_UNSTABLE, + Attrs::LANG, Attrs::REPR, Attrs::PATH, + Attrs::TARGET_FEATURE, Attrs::TEST}; + BuiltinAttributeMappings * BuiltinAttributeMappings::get () { @@ -327,6 +323,26 @@ check_proc_macro_non_root (AST::AttrVec attributes, location_t loc) } void +AttributeChecker::check_inner_attribute (const AST::Attribute &attribute) +{ + BuiltinAttrDefinition result; + + if (!is_builtin (attribute, result)) + return; + + if (__outer_attributes.find (result.name) != __outer_attributes.end ()) + rust_error_at (attribute.get_locus (), + "attribute cannot be used at crate level"); +} + +void +AttributeChecker::check_inner_attributes (const AST::AttrVec &attributes) +{ + for (auto &attr : attributes) + check_inner_attribute (attr); +} + +void AttributeChecker::check_attribute (const AST::Attribute &attribute) { if (!attribute.empty_input ()) @@ -357,15 +373,6 @@ AttributeChecker::check_attribute (const AST::Attribute &attribute) } void -AttributeChecker::check_inner_attributes (const AST::AttrVec &attributes) -{ - for (auto &attr : attributes) - if (attr.is_derive ()) - rust_error_at (attr.get_locus (), - "derive attribute cannot be used at crate level"); -} - -void AttributeChecker::check_attributes (const AST::AttrVec &attributes) { for (auto &attr : attributes) diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h index b10a080..f4a2d38 100644 --- a/gcc/rust/util/rust-attributes.h +++ b/gcc/rust/util/rust-attributes.h @@ -102,12 +102,14 @@ public: private: using AST::DefaultASTVisitor::visit; + + /* Check the validity of an inner attribute */ + void check_inner_attribute (const AST::Attribute &attribute); + /* Check the validy of all inner attributes */ + void check_inner_attributes (const AST::AttrVec &attributes); /* Check the validity of a given attribute */ void check_attribute (const AST::Attribute &attribute); - /* Check the validity of all given attributes */ - - void check_inner_attributes (const AST::AttrVec &attributes); void check_attributes (const AST::AttrVec &attributes); // rust-ast.h diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 4629e6a..a6d323e 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -925,10 +925,10 @@ Mappings::lookup_macro_invocation (AST::MacroInvocation &invoc) void Mappings::insert_exported_macro (AST::MacroRulesDefinition &def) { - exportedMacros.emplace_back (def.get_node_id ()); + exportedMacros.emplace_back (def); } -std::vector<NodeId> & +std::vector<AST::MacroRulesDefinition> Mappings::get_exported_macros () { return exportedMacros; @@ -1358,5 +1358,17 @@ Mappings::lookup_captures (NodeId closure) return cap->second; } +void +Mappings::add_derived_node (NodeId node_id) +{ + derived_nodes.insert (node_id); +} + +bool +Mappings::is_derived_node (NodeId node_id) +{ + return derived_nodes.find (node_id) != derived_nodes.end (); +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index c8fafa4..60066d6 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -279,7 +279,7 @@ public: lookup_macro_invocation (AST::MacroInvocation &invoc); void insert_exported_macro (AST::MacroRulesDefinition &def); - std::vector<NodeId> &get_exported_macros (); + std::vector<AST::MacroRulesDefinition> get_exported_macros (); void insert_derive_proc_macros (CrateNum num, std::vector<CustomDeriveProcMacro> macros); @@ -350,6 +350,9 @@ public: void add_capture (NodeId closure, NodeId definition); tl::optional<std::vector<NodeId>> lookup_captures (NodeId closure); + void add_derived_node (NodeId node_id); + bool is_derived_node (NodeId node_id); + private: Mappings (); @@ -408,7 +411,7 @@ private: std::map<NodeId, std::pair<AST::MacroRulesDefinition *, CrateNum>> macroMappings; std::map<NodeId, AST::MacroRulesDefinition *> macroInvocations; - std::vector<NodeId> exportedMacros; + std::vector<AST::MacroRulesDefinition> exportedMacros; // Procedural macros std::map<CrateNum, std::vector<CustomDeriveProcMacro>> @@ -443,6 +446,8 @@ private: // Closure AST NodeId -> vector of Definition node ids std::unordered_map<NodeId, std::vector<NodeId>> captures; + + std::set<NodeId> derived_nodes; }; } // namespace Analysis |
