diff options
Diffstat (limited to 'gcc/rust')
341 files changed, 29025 insertions, 18025 deletions
diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog index 31c731b..ec156ac 100644 --- a/gcc/rust/ChangeLog +++ b/gcc/rust/ChangeLog @@ -1,3 +1,5001 @@ +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): + Handle the expression contained in an ErrorPropagationExpr. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (visit(TuplePattern)): Update HAS_REST + case to continue to attempt to resolve pattern items after emitting size error. + +2025-10-30 Ryo Yoshida <low.ryoshida@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Emit + an error when the path refers to an enum itself rather than its variant. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-base.cc (parse_repr_options): Changed TOKEN_TREE + assert into error, update malformed repr attribute error message to be inline + with other attribute error messages. + +2025-10-30 Lucas Ly Ba <lucas.ly-ba@outlook.fr> + + * ast/rust-ast.cc (Attribute::is_derive): + Change string derive to its definition. + * util/rust-attribute-values.h: + Add attribute definition derive. + * util/rust-attributes.cc (AttributeChecker::visit): + Add method check_inner_attributes. + (AttributeChecker::check_inner_attributes): + Check if there is a bad inner attribute. + * util/rust-attributes.h: + Add method check_inner_attributes in .h. + +2025-10-30 lishin <lishin1008@gmail.com> + + * typecheck/rust-tyty-util.cc (TyVar::TyVar): Add null check to avoid ICE. + (TyVar::get_tyty): Return nullptr when lookup fails. + (TyVar::clone): Handle null base type safely. + (TyVar::monomorphized_clone): Add fallback for error types. + +2025-10-30 Ryo Yoshida <low.ryoshida@gmail.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): check + and properly emit an error when the tuple index is on a non-tuple-struct. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::array_copied_expr): refactor to new classes + * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit): likewise + (CompilePatternBindings::visit): likewise + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): likewise + * backend/rust-compile-type.h: likewise + * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): likewise + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): likewise + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise + * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): likewise + * typecheck/rust-substitution-mapper.h: likewise + * typecheck/rust-type-util.cc (unify_site_and): remove bad delete (alpine32) + * typecheck/rust-tyty-call.h: refactor to new classes + * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::clone): likewise + (SubstitutionRef::infer_substitions): likewise + * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): likewise + * typecheck/rust-tyty-util.h: likewise + * typecheck/rust-tyty-variance-analysis-private.h: likewise + * typecheck/rust-tyty-visitor.h: likewise + * typecheck/rust-tyty.cc (BaseType::destructure): likewise + (BaseType::monomorphized_clone): likewise + (BaseType::is_concrete): likewise + (VariantDef::clone): likewise + (VariantDef::monomorphized_clone): likewise + (ArrayType::as_string): likewise + (ArrayType::get_capacity): likewise + (ArrayType::handle_substitions): likewise + (generate_tree_str): likewise + (ConstType::ConstType): likewise + (ConstParamType::ConstParamType): likewise + (ConstType::accept_vis): likewise + (ConstParamType::const_kind): likewise + (ConstParamType::get_symbol): likewise + (ConstParamType::can_resolve): likewise + (ConstParamType::resolve): likewise + (ConstParamType::accept_vis): likewise + (ConstType::set_value): likewise + (ConstType::as_string): likewise + (ConstParamType::as_string): likewise + (ConstType::clone): likewise + (ConstParamType::clone): likewise + (ConstType::get_symbol): likewise + (ConstParamType::get_name): likewise + (ConstType::can_resolve): likewise + (ConstParamType::is_equal): likewise + (ConstType::resolve): likewise + (ConstValueType::ConstValueType): likewise + (ConstValueType::const_kind): likewise + (ConstValueType::accept_vis): likewise + (ConstValueType::as_string): likewise + (ConstValueType::clone): likewise + (ConstValueType::get_name): likewise + (ConstValueType::is_equal): likewise + (ConstValueType::get_value): likewise + (ConstInferType::ConstInferType): likewise + (ConstInferType::const_kind): likewise + (ConstInferType::accept_vis): likewise + (ConstType::get_name): likewise + (ConstInferType::as_string): likewise + (ConstInferType::clone): likewise + (ConstInferType::get_name): likewise + (ConstType::is_equal): likewise + (ConstInferType::is_equal): likewise + (ConstErrorType::ConstErrorType): likewise + (ConstErrorType::const_kind): likewise + (ConstType::handle_substitions): likewise + (ConstErrorType::accept_vis): likewise + (ConstErrorType::as_string): likewise + (ConstErrorType::clone): likewise + (ConstErrorType::get_name): likewise + (ConstErrorType::is_equal): likewise + * typecheck/rust-tyty.h (class BaseConstType): likewise + (class ConstType): likewise + (class ConstParamType): likewise + (class ConstValueType): likewise + (class ConstInferType): likewise + (class ConstErrorType): likewise + * typecheck/rust-unify.cc (UnifyRules::commit): likewise + (UnifyRules::go): likewise + (UnifyRules::expect_array): likewise + (UnifyRules::expect_const): likewise + * typecheck/rust-unify.h: likewise + +2025-10-30 0xllx0 <github+elle@weathered-steel.dev> + + * ast/rust-ast.cc (Module::process_file_path): empty module early return + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/rust-attributes.cc (check_doc_attribute): Change message. + (AttributeChecker::visit): Add doc attribute checking on traits. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.cc (AttrInputMetaItemContainer::separate_cfg_attrs): + Avoid malformed attributes. + * util/rust-attributes.cc (AttributeChecker::visit): Change location. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h: Force crash when retrieving locus. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.h: Add missing override modifier. + * ast/rust-path.h: Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/rust-attributes.cc (AttributeChecker::check_attribute): Recurse + within attr input for additional attribute checking. + (AttributeChecker::visit): Remove empty definition in favor of default + ast visitor definition. + * util/rust-attributes.h: Remove now unused prototypes. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (visit(TupleStructPattern)): + Update error for mismatched number of fields to use rich_location. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc: Add compilation support for TupleStructItemsHasRest + in CompilePatternCheckExpr(TupleStructPattern) & CompilePatternBindings(TupleStructPattern) + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit(TupleStructPattern)): + Implement lowering of AST::TupleStructItemsHasRest to HIR. + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(TupleStructPattern)): + Add the respective type checking for AST::TupleStructItemsHasRest + * checks/errors/rust-hir-pattern-analysis.cc (lower_tuple_pattern): + Add respective pattern for HAS_REST case. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)): Add type check + support for StructPatterns matching against a TUPLE type ADT. + * backend/rust-compile-pattern.cc(CompilePatternBindings::visit(StructPattern)): + Update assert to allow TUPLE type ADTs. + * hir/tree/rust-hir.cc (StructPatternField::as_string()): Improve info dumped. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * ast/rust-pattern.h (StructPatternElements): Rename has_struct_pattern_etc + to has_rest_pattern, and has_etc to has_rest to signify presense of rest + patterns more clearly. + * ast/rust-pattern.cc (StructPatternElements::as_string): Rename variables + accordingly. + * ast/rust-ast-collector.cc: Rename variables accordingly. + * expand/rust-cfg-strip.cc: Rename variables accordingly. + * parse/rust-parse-impl.h: Rename variable accordingly. + * hir/tree/rust-hir-pattern.h (StructPatternElements): Add a boolean to track + presense of rest pattern. + * hir/rust-ast-lower-pattern.cc (visit(StructPattern)): Add support for + lowering rest pattern to HIR. + * typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)): Remove + size check when rest pattern is present. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * backend/rust-compile-extern.h: Add includes. + (CompileExternItem::visit): Use get_link_name. + (CompileExternItem::get_link_name): New static member function. + * util/rust-attribute-values.h (Attributes::LINK_NAME): New + static constexpr member variable. + * util/rust-attributes.cc (__definitions): New entry for + LINK_NAME. + * util/rust-ggc.cc: Include "rust-ast.h". + (Ident::Ident): Add overload for Rust::Identifier. + * util/rust-ggc.h (class Identifier): Forward declare. + (Ident::Ident): Add overload for Rust::Identifier. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-expand-visitor.cc: Remove old visitors. + * expand/rust-expand-visitor.h: Likewise, plus inherit from PointerVisitor. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-expand.cc: Forward invocation tree locus to + substitution context. + * expand/rust-macro-substitute-ctx.cc: Use origin location for expanded + tokens. + * expand/rust-macro-substitute-ctx.h (class SubstituteCtx): Save + invocation location. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-expand.cc (transcribe_expression): Emit error + early. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-substitute-ctx.cc (is_builtin_metavariable): Add + function to check builtin metavars knowledge. + (SubstituteCtx::check_repetition_amount): Do not process missing + fragment. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-resolve-path.cc: add error diag + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): add error diagnostic + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): check for error + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-expr.cc: remove old hack + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): handle fnptr + * typecheck/rust-tyty.cc (FnPtr::handle_substitions): new + * typecheck/rust-tyty.h: likewise + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-fmt.h (class FFIOpt): Adjust internal structure to + match a repr(C) rust enum. + +2025-10-30 Magnus-Mage <romescha123@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Implement + FormatArgs visitor to reconstruct format_args! macro syntax. + * ast/rust-builtin-ast-nodes.h (FormatArguments): Add get_args(), + size(), and empty() accessor methods. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): check for invalid capacity + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-constexpr.cc (eval_constant_expression): port over missing bits + (eval_store_expression): likewise + (eval_call_expression): likewise + (eval_binary_expression): likewise + (eval_bit_field_ref): likewise + (eval_check_shift_p): likewise + (fold_pointer_plus_expression): likewise + (maybe_fold_addr_pointer_plus): likewise + (fold_expr): likewise + (union_active_member): likewise + (fold_indirect_ref_1): likewise + (rs_fold_indirect_ref): likewise + (rs_eval_indirect_ref): likewise + (eval_logical_expression): likewise + (eval_vector_conditional_expression): likewise + (eval_bare_aggregate): likewise + (cxx_eval_trinary_expression): likewise + (eval_and_check_array_index): likewise + (eval_array_reference): likewise + (eval_component_reference): likewise + (rs_bind_parameters_in_call): likewise + (eval_builtin_function_call): likewise + (constexpr_fn_retval): likewise + (verify_constant): likewise + (get_array_or_vector_nelts): likewise + (eval_conditional_expression): likewise + (eval_switch_expr): likewise + (eval_unary_expression): likewise + (cxx_eval_outermost_constant_expr): likewise + (potential_constant_expression_1): likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::compile_integer_literal): cleanup + * backend/rust-constexpr.cc (struct constexpr_global_ctx): port over c++ helpers + (decl_really_constant_value): likewise + (eval_constant_expression): likewise + (non_const_var_error): likewise + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_pattern): Ignore + inner patterns which fail to parse. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Remove + overload for TraitItemConst. + * ast/rust-ast-collector.h (TokenCollector::visit): Likewise. + * ast/rust-ast-pointer-visitor.cc (PointerVisitor::visit): + Likewise. + * ast/rust-ast-pointer-visitor.h (PointerVisitor::visit): + Likewise. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * ast/rust-ast-visitor.h (ASTVisitor::visit): Likewise. + (DefaultASTVisitor::visit): Likewise. + * expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise. + * expand/rust-cfg-strip.h (CfgStrip::visit): Likewise. + * expand/rust-derive.h (DeriveVisitor::visit): Likewise. + * expand/rust-expand-visitor.cc (ExpandVisitor::visit): + Likewise. + * expand/rust-expand-visitor.h (ExpandVisitor::visit): Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. + * hir/rust-ast-lower-base.h (ASTLoweringBase::visit): Likewise. + * util/rust-attributes.cc (AttributeChecker::visit): Likewise. + * util/rust-attributes.h (AttributeChecker::visit): Likewise. + * ast/rust-ast.cc (ConstantItem::as_string): Handle missing + expression. + (TraitItemConst::as_string): Remove function definition. + (TraitItemConst::accept_vis): Remove function definition. + * ast/rust-item.h (ConstantItem::mark_for_strip): Adjust + comment. + (ConstantItem::has_expr): Make const. + (class TraitItemConst): Remove definition. + * ast/rust-ast-full-decls.h (class TraitItemConst): Remove + declaration. + * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): + Handle ConstantItem instead of TraitItemConst. + * hir/rust-ast-lower-implitem.h (ASTLowerTraitItem::visit): + Likewise. + * parse/rust-parse-impl.h (Parser::parse_trait_const): Return + pointer to ConstantItem instead of TraitItemConst. + * parse/rust-parse.h (Parser::parse_trait_const): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in: Handle source files in checks/errors/feature. + * checks/errors/rust-feature-gate.cc: Move to... + * checks/errors/feature/rust-feature-gate.cc: ...here. + * checks/errors/rust-feature-gate.h: Move to... + * checks/errors/feature/rust-feature-gate.h: ...here. + * checks/errors/rust-feature.cc: Move to... + * checks/errors/feature/rust-feature.cc: ...here. + * checks/errors/rust-feature.h: Move to... + * checks/errors/feature/rust-feature.h: ...here. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in (GRS_OBJS): Remove rust-early-name-resolver.o. + * expand/rust-macro-builtins-helpers.h: Remove inclusion of + rust-early-name-resolver.h. + * expand/rust-macro-builtins.cc: Likewise. + * expand/rust-macro-expand.cc: Likewise. + * expand/rust-macro-expand.h: Likewise. + * resolve/rust-early-name-resolver.cc: Removed. + * resolve/rust-early-name-resolver.h: Removed. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * hir/tree/rust-hir-item.h: add unsafe helper + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): pass in abi and unsafe + * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): likewise + (FnPtr::as_string): emit more info + (FnPtr::clone): update ctor call + * typecheck/rust-tyty.h: new ctor params + * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): check abi and unsafe + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::expect_reference): remove clone + (UnifyRules::expect_pointer): likewise + (UnifyRules::expect_slice): likewise + (UnifyRules::expect_tuple): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in (GRS_OBJS): Remove entries. + * rust-lang.cc: Remove inclusion of "rust-ast-resolve-item.h". + (run_rust_tests): Remove call to rust_simple_path_resolve_test. + * resolve/rust-ast-resolve-base.cc: Removed. + * resolve/rust-ast-resolve-base.h: Removed. + * resolve/rust-ast-resolve-expr.cc: Removed. + * resolve/rust-ast-resolve-expr.h: Removed. + * resolve/rust-ast-resolve-implitem.h: Removed. + * resolve/rust-ast-resolve-item.cc: Removed. + * resolve/rust-ast-resolve-item.h: Removed. + * resolve/rust-ast-resolve-path.cc: Removed. + * resolve/rust-ast-resolve-path.h: Removed. + * resolve/rust-ast-resolve-pattern.cc: Removed. + * resolve/rust-ast-resolve-pattern.h: Removed. + * resolve/rust-ast-resolve-stmt.cc: Removed. + * resolve/rust-ast-resolve-stmt.h: Removed. + * resolve/rust-ast-resolve-struct-expr-field.cc: Removed. + * resolve/rust-ast-resolve-struct-expr-field.h: Removed. + * resolve/rust-ast-resolve-toplevel.h: Removed. + * resolve/rust-ast-resolve-type.cc: Removed. + * resolve/rust-ast-resolve-type.h: Removed. + * resolve/rust-ast-resolve.cc: Removed. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use + resolve_type_path_like in overloads for TypePath, + StructExprStruct, StructExprStructBase, and + StructExprStructFields. + (resolve_type_path_like): New static function based off + Late::visit overload for TypePath. + * util/rust-unwrap-segment.h (unwrap_segment_error_string): New + inline static function definitions. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::visit): add guard + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-context.h: add assertions for context peeks + * backend/rust-compile-expr.cc (CompileExpr::visit): check for valid loop context + (CompileExpr::array_copied_expr): just reuse array tyty capacity value + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): catch error + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * checks/errors/rust-readonly-check.cc (collect_assignment_tuple): Implement + read-only checker for tuple patterns with rest pattern. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-var-decl.h (CompileVarDecl::visit(TuplePattern)): Implement + variable declaration bindings for tuple patterns with rest pattern (i.e. + TuplePatternItemsHasRest). + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * util/rust-attribute-values.h + (Attributes::RUSTC_ALLOW_CONST_FN_UNSTABLE): New static + constexpr member variable. + * util/rust-attributes.cc (__definitions): Add entry for + RUSTC_ALLOW_CONST_FN_UNSTABLE. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::commit): commit hook update + (UnifyRules::go): insert implicit infer const types + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::go): unwrap the const type + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-base.cc (walk_types_to_constrain): track the ref as well + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty-subst.cc: const generic arguments dont have a value yet + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (VariantDef::clone): fix formatting + (VariantDef::monomorphized_clone): likewise + * typecheck/rust-tyty.h: likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (InferType::can_eq): remove + (ErrorType::can_eq): likewise + (ADTType::can_eq): likewise + (TupleType::can_eq): likewise + (FnType::can_eq): likewise + (FnPtr::can_eq): likewise + (ClosureType::can_eq): likewise + (ArrayType::can_eq): likewise + (SliceType::can_eq): likewise + (BoolType::can_eq): likewise + (IntType::can_eq): likewise + (UintType::can_eq): likewise + (FloatType::can_eq): likewise + (USizeType::can_eq): likewise + (ISizeType::can_eq): likewise + (CharType::can_eq): likewise + (ReferenceType::can_eq): likewise + (PointerType::can_eq): likewise + (ParamType::can_eq): likewise + (ConstType::can_eq): likewise + (OpaqueType::can_eq): likewise + (StrType::can_eq): likewise + (NeverType::can_eq): likewise + (PlaceholderType::can_eq): likewise + (ProjectionType::can_eq): likewise + (DynamicObjectType::can_eq): likewise + * typecheck/rust-tyty.h: remove can_eq + * typecheck/rust-tyty-cmp.h: Removed. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (ParamType::is_equal): uses types_compatable + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (unify_error_type_node): new static node + (UnifyRules::go): likewise + (UnifyRules::expect_inference_variable): likewise + (UnifyRules::expect_adt): likewise + (UnifyRules::expect_str): likewise + (UnifyRules::expect_reference): likewise + (UnifyRules::expect_pointer): likewise + (UnifyRules::expect_param): likewise + (UnifyRules::expect_array): likewise + (UnifyRules::expect_slice): likewise + (UnifyRules::expect_fndef): likewise + (UnifyRules::expect_fnptr): likewise + (UnifyRules::expect_tuple): likewise + (UnifyRules::expect_bool): likewise + (UnifyRules::expect_char): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + (UnifyRules::expect_isize): likewise + (UnifyRules::expect_usize): likewise + (UnifyRules::expect_never): likewise + (UnifyRules::expect_placeholder): likewise + (UnifyRules::expect_projection): likewise + (UnifyRules::expect_dyn): likewise + (UnifyRules::expect_closure): likewise + (UnifyRules::expect_opaque): likewise + (UnifyRules::expect_const): likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::Resolve): check for success + (UnifyRules::expect_inference_variable): dont clone + (UnifyRules::expect_adt): likewise + (UnifyRules::expect_str): likewise + (UnifyRules::expect_reference): likewise + (UnifyRules::expect_pointer): likewise + (UnifyRules::expect_param): likewise + (UnifyRules::expect_array): likewise + (UnifyRules::expect_slice): likewise + (UnifyRules::expect_fndef): likewise + (UnifyRules::expect_fnptr): likewise + (UnifyRules::expect_tuple): likewise + (UnifyRules::expect_bool): likewise + (UnifyRules::expect_char): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + (UnifyRules::expect_isize): likewise + (UnifyRules::expect_usize): likewise + (UnifyRules::expect_never): likewise + (UnifyRules::expect_placeholder): likewise + (UnifyRules::expect_projection): likewise + (UnifyRules::expect_dyn): likewise + (UnifyRules::expect_closure): likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (BaseType::satisfies_bound): use types_compatable instead + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-type-util.cc (types_compatable): add check bounds flag + (unify_site_and): likewise + * typecheck/rust-type-util.h (types_compatable): likewise + (unify_site_and): likewise + * typecheck/rust-tyty-bounds.cc: likewise + * typecheck/rust-unify.cc (UnifyRules::UnifyRules): likewise + (UnifyRules::Resolve): likewise + (UnifyRules::resolve_subtype): likewise + (UnifyRules::go): likewise + * typecheck/rust-unify.h: likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-path-probe.cc (PathProbeType::process_impl_item_candidate): + refactor to types_compatable + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::expect_inference_variable): dont commit + (UnifyRules::expect_adt): likewise + (UnifyRules::expect_bool): likewise + (UnifyRules::expect_char): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + (UnifyRules::expect_isize): likewise + (UnifyRules::expect_usize): likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-base.h: remove const + * backend/rust-compile-expr.cc: likewise + * backend/rust-compile.cc (HIRCompileBase::coerce_to_dyn_object): likewise + * typecheck/rust-hir-type-bounds.h: likewise + * typecheck/rust-type-util.cc (lookup_associated_impl_block): likewise + * typecheck/rust-type-util.h (lookup_associated_impl_block): likewise + * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::TypeBoundsProbe): likewise + (TypeBoundsProbe::Probe): likewise + * typecheck/rust-tyty-cmp.h: likewise + * typecheck/rust-tyty-subst.cc (SubstitutionRef::monomorphize): likewise + * typecheck/rust-tyty.cc (BaseType::satisfies_bound): likewise + (BaseType::bounds_compatible): likewise + (VariantDef::clone): likewise + (VariantDef::monomorphized_clone): likewise + (OpaqueType::is_equal): likewise + (DynamicObjectType::is_equal): likewise + * typecheck/rust-tyty.h: likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::select): respect try flag + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import): + Replace assert with early break and remove early return. + (Early::visit): Check for unsuffixed lower self list. + * resolve/rust-early-name-resolver-2.0.h: Add visit function prototype. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Emit an error + on top level rebind self use declaration. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in (GRS_OBJS): Add "rust-resolve-builtins.o". + * resolve/rust-late-name-resolver-2.0.cc: Include + "rust-resolve-builtins.h". + (next_node_id): Remove function. + (next_hir_id): Likewise. + (Late::setup_builtin_types): Likewise. + (Late::go): Use Builtins::setup_type_ctx instead of + Late::setup_builtin_types. + * resolve/rust-late-name-resolver-2.0.h + (Late::setup_builtin_types): Remove function. + * rust-session-manager.cc: Include "rust-resolve-builtins.h". + (Session::expansion): Call Builtins::setup_lang_prelude. + * resolve/rust-resolve-builtins.cc: New file. + * resolve/rust-resolve-builtins.h: New file. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::left_denotation): Remove + usage of parse_tuple_index_expr_float. + (Parser::parse_closure_expr_pratt): Remove function. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust-session-manager.cc (Session::compile_crate): Move the AST dump + after parser error check. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch): Rename to... + (ExpressionYeast::reseat): ...this. + (ExpressionYeast::visit): Remove. + * ast/rust-expression-yeast.h: Inherit from PointerVisitor, override reseat instead + of declaring dispatch. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * Make-lang.in: Compile it. + * ast/rust-builtin-ast-nodes.h: Add missing methods for getting pointers. + * ast/rust-expr.h: Likewise. + * ast/rust-item.h: Likewise. + * ast/rust-path.h: Likewise. + * ast/rust-pattern.h: Likewise. + * ast/rust-type.h: Likewise. + * ast/rust-ast-pointer-visitor.cc: New file. + * ast/rust-ast-pointer-visitor.h: New file. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h (class TupleIndexExpr): Store strip information. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/borrowck/rust-bir-builder-internal.h: Remove + inclusion of "rust-name-resolver.h". + (BuilderContext::resolver): Change type to nr2.0 resolver. + (BuilderContext::BuilderContext): Change initialization of + resolver reference. + (AbstractBuilder::resolve_label): Assume name resolution 2.0 is + enabled. + (AbstractBuilder::resolve_variable): Likewise. + (AbstractBuilder::resolve_variable_or_fn): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/rust-hir-pattern-analysis.cc: Remove inclusion + of "options.h". + (PatternChecker::PatternChecker): Change initialization of + resolver reference. + (PatternChecker::visit): Assume name resolution 2.0 is enabled. + * checks/errors/rust-hir-pattern-analysis.h: Include nr2.0 + header instead of nr1.0 header. + (PatternChecker::resolver): Change type to nr2.0 resolver. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust-session-manager.cc: Remove inclusion of name resolution + 1.0 headers. + (Session::compile_crate): Assume name resolution 2.0 is enabled. + (Session::expansion): Likewise. + (Session::load_extern_crate): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/privacy/rust-privacy-check.cc: Adjust includes. + (Resolver::resolve): Pass 2.0 name resolution context to + VisibilityResolver and PrivacyReporter. + * checks/errors/privacy/rust-privacy-reporter.cc + (PrivacyReporter::PrivacyReporter): Change type of resolver + parameter. + (is_child_module): Remove static function. + (PrivacyReporter::check_for_privacy_violation): Assume nr2.0 is + enabled and handle removal of is_child_module. + * checks/errors/privacy/rust-privacy-reporter.h: Adjust + includes. + (PrivacyReporter::PrivacyReporter): Change type of resolver + parameter. + (PrivacyReporter::resolver): Change member variable type. + * checks/errors/privacy/rust-visibility-resolver.cc: Adjust + includes. + (VisibilityResolver::VisibilityResolver): Change type of + resolver parameter. + (VisibilityResolver::resolve_module_path): Assume nr2.0 is + enabled. + * checks/errors/privacy/rust-visibility-resolver.h: Adjust + includes. + (VisibilityResolver::VisibilityResolver): Change type of + resolver parameter. + (VisibilityResolver::resolver): Change member variable type. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * ast/rust-pattern.h: + - Add a new base abstract class `PatternItems` which are used by pattern items class + class derivatives for `TuplePattern`, `TupleStructPattern` & `SlicePattern`. + - Standardized the derived class names to have `HasRest` or `NoRest` as suffixes. + - Values for the common `ItemType` enum is updated to `HAS_REST` or `NO_REST`. + * ast/rust-pattern.cc: Renamed the classes accordingly. + * ast/rust-ast-collector.cc: Renamed the classes accordingly. + * ast/rust-ast-collector.h: Renamed the classes accordingly. + * ast/rust-ast-full-decls.h: Renamed the classes accordingly. + * ast/rust-ast-visitor.cc: Renamed the classes accordingly. + * ast/rust-ast-visitor.h: Renamed the classes accordingly. + * ast/rust-desugar-for-loops.cc: Renamed the classes accordingly. + * ast/rust-desugar-question-mark.cc: Renamed the classes accordingly. + * expand/rust-cfg-strip.cc: Renamed the classes accordingly. + * expand/rust-cfg-strip.h: Renamed the classes accordingly. + * expand/rust-derive-clone.cc: Renamed the classes accordingly. + * expand/rust-derive-cmp-common.cc: Renamed the classes accordingly. + * expand/rust-derive-hash.cc: Renamed the classes accordingly. + * expand/rust-derive-ord.cc: Renamed the classes accordingly. + * expand/rust-derive-partial-eq.cc: Renamed the classes accordingly. + * expand/rust-derive.h: Renamed the classes accordingly. + * expand/rust-expand-visitor.cc: Renamed the classes accordingly. + * expand/rust-expand-visitor.h: Renamed the classes accordingly. + * hir/rust-ast-lower-base.cc: Renamed the classes accordingly. + * hir/rust-ast-lower-base.h: Renamed the classes accordingly. + * hir/rust-ast-lower-pattern.cc: Renamed the classes accordingly. + * hir/tree/rust-hir-pattern.h: Renamed the classes accordingly. + * parse/rust-parse-impl.h: Renamed the classes accordingly. + * resolve/rust-ast-resolve-base.cc: Renamed the classes accordingly. + * resolve/rust-ast-resolve-base.h: Renamed the classes accordingly. + * resolve/rust-ast-resolve-pattern.cc: Renamed the classes accordingly. + * util/rust-attributes.cc: Renamed the classes accordingly. + * util/rust-attributes.h: Renamed the classes accordingly. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Use + should_have_str instead of has_str. + * ast/rust-ast.cc (Token::as_string): Likewise. + * expand/rust-macro-builtins-offset-of.cc + (MacroBuiltin::offset_of_handler): Likewise. + * lex/rust-lex.cc (Lexer::dump_and_skip): Likewise. + * ast/rust-ast.h (class Token): Remove dead code. + (Token::has_str): Remove function. + (Token::should_have_str): New function. + * lex/rust-token.cc (Token::get_str): Remove function + definition. + * lex/rust-token.h: Include "rust-diagnostics.h". + (Token::str): Change type from std::unique_ptr<std::string> to + std::string. + (Token::Token): Adjust initialization of str member variable and + the type of the parameter used to initialize it. + (Token::make_identifier): Accept std::string instead of rvalue + reference to std::string. + (Token::make_int): Likewise. + (Token::make_float): Likewise. + (Token::make_string): Likewise. + (Token::make_byte_string): Likewise. + (Token::make_raw_string): Likewise. + (Token::make_inner_doc_comment): Likewise. + (Token::make_outer_doc_comment): Likewise. + (Token::make_lifetime): Likewise. + (Token::get_str): Add definition to function declaration. + (Token::has_str): Remove member function. + (Token::should_have_str): Handle INNER_DOC_COMMENT and + OUTER_DOC_COMMENT. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-macro-builtins-format-args.cc + (format_args_parse_arguments): Split format expression parsing + into... + (format_args_parse_expr): ...a new function here, while handling + eager expansion. + (MacroBuiltin::format_args_handler): Use format_args_parse_expr. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_expr): Avoid skipping + or splitting tokens. + (Parser::null_denotation): Assume initial token was not skipped + and adjust function signature to match. Use + parse_path_in_expression instead of + parse_path_in_expression_pratt and handle SCOPE_RESOLUTION. + (Parser::parse_path_in_expression_pratt): Remove function. + * parse/rust-parse.h (null_denotation): Remove initial token + parameter. + (parse_path_in_expression_pratt): Remove function. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Use as + member function. + (TypeCoercionRules::coerce_borrowed_pointer): Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): + Move nevertype coercion from here... + (TypeCoercionRules::coerce_never): ... to here. + * typecheck/rust-coercion.h: Add function prototype. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Adapt + call to new return type. + (TypeCoercionRules::coerce_unsized): Change error handling. + * typecheck/rust-coercion.h: Update function prototype and add new + CoerceUnsizedError error type. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Refactor + common return statement. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Remove + unused assignment. + * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): + Likewise. + * typecheck/rust-tyty.cc (ParamType::handle_substitions): Likewise. + * typecheck/rust-unify.cc (UnifyRules::go): Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): + Construct value in place. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-ast-resolve-stmt.cc (ResolveStmt::visit): Remove + unused copy. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * backend/rust-compile-expr.cc (CompileExpr::generate_closure_fntype): + Unwrap the optional. + * backend/rust-compile.cc: Change return type container. Adapt code to + new return type. + * typecheck/rust-hir-dot-operator.cc: Likewise. + * typecheck/rust-hir-path-probe.cc: Likewise. + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItemWithTrait::visit): + Likewise. + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): + Likewise. + * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::contains_item): + Likewise. + (TypeBoundPredicate::lookup_associated_item): Likewise. + (TypeBoundPredicateItem::get_parent): Likewise. + (TypeBoundPredicate::lookup_associated_type): Likewise. + * typecheck/rust-tyty.cc (BaseType::satisfies_bound): Likewise. + * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit): Change + return type. + * typecheck/rust-tyty.h: Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-casts.cc (TypeCastRules::cast_rules): Authorize + cast from function pointer to integer like type. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-hir-type-check-base.cc (walk_type_to_constrain): Walk + through all kind of type to collect ty leaves. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-type.h: Prevent reconstruction on null pointers. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * util/rust-attribute-values.h (Attributes::SIMD_TEST): Remove + static constexpr member variable. + * util/rust-attributes.cc (__definitions): Remove entry for + SIMD_TEST. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_identifier_pattern): + Use parse_pattern_no_alt to parse identifier pattern + subpatterns. + (Parser::parse_ident_leading_pattern): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-fmt.cc (Pieces::collect): Handle changes to ffi + interface. + (Pieces::~Pieces): Remove function definition. + (Pieces::Pieces): Likewise. + (Pieces::operator=): Likewise. + * ast/rust-fmt.h: Include "optional.h". + (rust_ffi_alloc): New extern "C" function declaration. + (rust_ffi_dealloc): Likewise. + (class FFIVec): New class. + (class FFIOpt): Likewise. + (RustHamster::RustHamster): New constructor accepting const + std::string reference. + (struct FormatSpec): Use FFIOpt. + (struct PieceSlice): Remove struct. + (struct RustString): Likewise. + (struct FormatArgsHandle): Likewise. + (collect_pieces): Change function signature. + (clone_pieces): Likewise. + (destroy_pieces): Remove extern "C" function declaration. + (Pieces::~Pieces): Remove function declaration. + (Pieces::operator=): Likewise. + (Pieces::get_pieces): Handle changes to class fields. + (Pieces::Pieces): Remove copy and move constructor declarations, + adjust signature of remaining constructor declaration. + (Pieces::pieces_vector): Remove member variable. + (Pieces::handle): Likewise. + (Pieces::data): Add member variable. + * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): + Use references to avoid copying. + +2025-10-30 lishin <lishin1008@gmail.com> + + * backend/rust-compile-pattern.cc (CompilePatternLet::visit): + Handle tuple destructuring containing by-ref. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * hir/tree/rust-hir-pattern.h: Add SlicePatternItems base class and + SlicePatternItemsNoRest/SlicePatternItemsHasRest derived classes. + Update SlicePattern to hold patterns using the new classes. + * hir/tree/rust-hir-full-decls.h: Declare new classes. + * hir/tree/rust-hir.cc: Add visits for new classes. + * hir/tree/rust-hir-visitor.h: Add visits for new classes. + * hir/tree/rust-hir-visitor.cc: Implement visits for new classes. + * hir/rust-hir-dump.h: Add visits for new classes. + * hir/rust-hir-dump.cc: Implement Dump::visit for new classes. + * hir/rust-ast-lower-base.h: Declare new lower_slice_pattern_no_rest/has_rest + methods. + * hir/rust-ast-lower-base.cc: Implement lower_slice_pattern_no_rest/has_rest + to lower AST slice pattern items to HIR. + * hir/rust-ast-lower-pattern.cc: Update ASTLoweringPattern::visit for + SlicePattern to use new lowering methods. + * backend/rust-compile-pattern.cc: Update CompilePatternCheckExpr::visit + and CompilePatternBindings::visit for SlicePattern to handle + SlicePatternItemsNoRest/HasRest. + * checks/errors/borrowck/rust-bir-builder-pattern.cc: Update + PatternBindingBuilder::visit for SlicePattern to iterate members correctly. + * checks/errors/borrowck/rust-bir-builder-struct.h: Add visits for new + classes. + * checks/errors/borrowck/rust-function-collector.h: Add visits for new + classes. + * checks/errors/rust-const-checker.h: Add visits for new classes. + * checks/errors/rust-const-checker.cc: Implement empty visits for new classes. + * checks/errors/rust-hir-pattern-analysis.h: Add visits for new classes. + * checks/errors/rust-hir-pattern-analysis.cc: Implement empty visits for new + classes. + * checks/errors/rust-unsafe-checker.h: Add visits for new classes. + * checks/errors/rust-unsafe-checker.cc: Implement empty visits for new + classes. + * typecheck/rust-hir-type-check-pattern.cc: Update TypeCheckPattern::visit + for SlicePattern to handle SlicePatternItemsNoRest/HasRest. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust-session-manager.cc (Session::compile_crate): Collect lang + items after expansion. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * Make-lang.in: Replace old read-only checker with new implementation. + * checks/errors/rust-readonly-check.cc (ReadonlyChecker::ReadonlyChecker): + Replace old read-only checker with new implementation. + * checks/errors/rust-readonly-check.h: + Replace old read-only checker with new implementation. + * rust-session-manager.cc (Session::compile_crate): + Switch to new read-only checker. + * checks/errors/rust-readonly-check2.cc: Removed. + * checks/errors/rust-readonly-check2.h: Removed. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * checks/errors/rust-readonly-check2.cc (ReadonlyChecker::check_variable): + Read-only check if the variable is mutable type. + (ReadonlyChecker::is_mutable_type): Read-only check if the variable is mutable type. + * checks/errors/rust-readonly-check2.h: Read-only check if the variable is mutable type. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc(ClosureParamInfer(IdentifierPattern)): + Resolve subpattern types for IdentifierPattern. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc(CompilePatternLet::visit(IdentifierPattern)): + Add support for subpatterns. + * backend/rust-compile-var-decl.h(CompileVarDecl::visit(IdentifierPattern)): + Implement compilation for subpatterns. + +2025-10-30 lishin <lishin1008@gmail.com> + + * typecheck/rust-hir-dot-operator.cc (MethodResolver::Select): + Skip asserts by checking candidate type and using early-continue. + (MethodResolver::try_select_predicate_candidates): + Skip invalid candidates. + +2025-10-30 lishin <lishin1008@gmail.com> + + * rust-gcc.cc (constructor_expression): + Ensure vec_alloc reserves at least one element. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.cc (Attribute::check_cfg_predicate): Emit an error with + empty cfg_attr input. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-forever-stack.hxx + (ForeverStack::resolve_segments): Remove usage of optional + reference, allow non-final path segments to resolve to types + even outside the type namespace, and allow resolution to + progress past non-final path segments which resolve to modules. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse-impl.h (Parser::parse_stmt_or_expr): Add null check + on parse_macro_invocation_partial call. + * ast/rust-path.cc (Path::convert_to_simple_path): Do not exclude + capitalized "Self". + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-fragment.cc (Fragment::is_pattern_fragment): New function. + (Fragment::take_pattern_fragment): Likewise. + (Fragment::assert_single_fragment): Likewise. + * ast/rust-ast-fragment.h: Declare them. + * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Add new constructor for pattern + single AST nodes. + (SingleASTNode::operator=): Handle patterns. + (SingleASTNode::accept_vis): Likewise. + (SingleASTNode::is_error): Likewise. + (SingleASTNode::as_string): Likewise. + * ast/rust-ast.h: Add get_pattern_ptr() functions. + * ast/rust-expr.h: Likewise. + * ast/rust-item.h: Likewise. + * ast/rust-pattern.h: Likewise. + * ast/rust-stmt.h: Likewise. + * expand/rust-expand-visitor.cc (derive_item): Use new API enum values. + (expand_item_attribute): Likewise. + (expand_stmt_attribute): Likewise. + (ExpandVisitor::maybe_expand_pattern): New function. + (ExpandVisitor::expand_closure_params): Handle patterns. + (ExpandVisitor::visit): Add new visitors for patterns and missed exprs. + * expand/rust-expand-visitor.h: Declare them. + * expand/rust-macro-expand.cc (transcribe_pattern): New function. + (transcribe_context): Call it. + * expand/rust-macro-expand.h (struct MacroExpander): New Context type. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.h: Change NodeType to enum class Kind. + * ast/rust-ast-fragment.cc: Use new names. + * ast/rust-ast-fragment.h: Likewise. + * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h + (Parser::parse_identifier_or_keyword_token): Record error on + failure. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * resolve/rust-ast-resolve-stmt.h: + Add name resolution processing for discriminant values. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): fix error code + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-cfg-strip.cc: Include "rust-macro-expand.h". + (fails_cfg): Rename to... + (CfgStrip::fails_cfg): ...here and handle test attributes. + (fails_cfg_with_expand): Rename to... + (CfgStrip::fails_cfg_with_expand): ...here and handle test + attributes. + * expand/rust-cfg-strip.h (struct ExpansionCfg): Forward + declare. + (CfgStrip::fails_cfg): New member function. + (CfgStrip::fails_cfg_with_expand): Likewise. + (CfgStrip::CfgStrip): Accept reference to ExpansionCfg. + (CfgStrip::expansion_cfg): New member variable. + * rust-session-manager.cc (Session::expansion): Pass + ExpansionCfg instance to CfgStrip constructor. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import): + Do not abort on wildcard patterns. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h: Add const getters to llvm members. + * hir/rust-ast-lower-expr.cc (check_llvm_asm_support): Check llvm_asm + usage validity. + (ASTLoweringExpr::visit): Emit an error message instead of aborting. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-asm.cc (parse_llvm_clobbers): Expect a + comma between clobbers. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-asm.cc (parse_asm): Simplify expression. + (parse_llvm_asm): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast.h (Stmt::get_node_id): Make virtual. + (Type::get_node_id): Likewise. + (AssociatedItem::get_node_id): New virtual member function. + * ast/rust-expr.h (TypeCastExpr::get_casted_expr_ptr): New + member function. + (TypeCastExpr::get_type_to_cast_to_ptr): Likewise. + (ClosureExprInner::get_definition_expr_ptr): Likewise. + * ast/rust-item.h (TypeAlias::get_node_id): New member function + to override AssociatedItem::get_node_id. + (ConstantItem::get_node_id): Likewise. + * expand/rust-expand-visitor.cc + (ExpandVisitor::maybe_expand_expr): Adjust + macro_invoc_expect_id. + (ExpandVisitor::maybe_expand_type): Likewise and add an overload + for std::unique_ptr<TypeNoBounds>. + (ExpandVisitor::visit): Check macro_invoc_expect_id and + generally improve visitors so that the testsuite will still + pass. + * expand/rust-expand-visitor.h (ExpandVisitor::ExpandVisitor): + Initialize member variable macro_invoc_expect_id. + (ExpandVisitor::maybe_expand_type): Add an overload for + std::unique_ptr<TypeNoBounds>. + (ExpandVisitor::expand_macro_children): Adjust + macro_invoc_expect_id. + (ExpandVisitor::visit): Add an overload for TypeCastExpr. + (ExpandVisitor::macro_invoc_expect_id): New member variable. + +2025-10-30 lishin <lishin1008@gmail.com> + + * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit): + Check upper compare operator. + * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): + Handle lowering of exclusive range pattern. + * hir/tree/rust-hir-pattern.h (class RangePattern): + Add support for exclusive ranges in HIR representation. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-macro-expand.cc (transcribe_expression): Parse any + outer attributes before parsing an expression. + * parse/rust-parse.h (Parser::parse_outer_attributes): Make + public. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h (struct TupleClobber): Add constructor. + * backend/rust-compile-context.h (struct fncontext): Likewise. + * typecheck/rust-hir-dot-operator.h: Likewise. + * typecheck/rust-tyty-variance-analysis-private.h (struct Constraint): + Likewise. + * typecheck/rust-unify.h: Likewise. + * ast/rust-ast-builder.cc (Builder::new_lifetime_param): Add memory + reservation and construct in place. + (Builder::new_generic_args): Likewise. + * ast/rust-ast-collector.cc (TokenCollector::newline): Likewise. + (TokenCollector::indentation): Likewise. + (TokenCollector::comment): Likewise. + * ast/rust-desugar-apit.cc: Likewise. + * ast/rust-path.cc (Path::convert_to_simple_path): Likewise. + (TypePath::as_simple_path): Likewise. + * ast/rust-path.h: Likewise. + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): Likewise. + (TyTyResolveCompile::create_dyn_obj_record): Likewise. + * checks/errors/rust-hir-pattern-analysis.cc (Matrix::specialize): + Likewise. + (WitnessMatrix::apply_constructor): Likewise. + (check_match_usefulness): Likewise. + * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Likewise. + * expand/rust-macro-builtins-asm.cc (parse_clobber_abi): Likewise. + * expand/rust-macro-expand.cc (MacroExpander::parse_proc_macro_output): + Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_generic_args): + Likewise. + (ASTLoweringBase::lower_extern_block): Likewise. + * hir/rust-ast-lower-enumitem.h: Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + * hir/rust-ast-lower-extern.h: Likewise. + * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Likewise. + (ASTLowerTraitItem::visit): Likewise. + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise. + * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Likewise. + * hir/rust-ast-lower.cc (ASTLowering::go): Likewise. + (ASTLoweringBlock::visit): Likewise. + (ASTLoweringIfLetBlock::desugar_iflet): Likewise. + (ASTLoweringExprWithBlock::visit): Likewise. + (ASTLowerPathInExpression::visit): Likewise. + (ASTLowerQualPathInExpression::visit): Likewise. + * hir/tree/rust-hir.cc (PathPattern::convert_to_simple_path): Likewise. + (TypePath::as_simple_path): Likewise. + * metadata/rust-export-metadata.cc (ExportContext::emit_function): + Likewise. + * parse/rust-parse-impl.h (Parser::parse_decl_macro_def): Likewise. + (Parser::parse_lifetime_params): Likewise. + * resolve/rust-ast-resolve-item.cc (ResolveTraitItems::visit): + Likewise. + (ResolveItem::visit): Likewise. + (flatten_list): Likewise. + * resolve/rust-ast-resolve-pattern.cc (PatternDeclaration::visit): + Likewise. + * typecheck/rust-autoderef.cc (AutoderefCycle::try_autoderefed): + Likewise. + * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized): + Likewise. + * typecheck/rust-hir-dot-operator.cc: Likewise. + * typecheck/rust-hir-path-probe.cc: Likewise. + * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): + Likewise. + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): + Likewise. + (TypeCheckExpr::resolve_fn_trait_call): Likewise. + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit): + Likewise. + (TypeCheckImplItem::visit): Likewise. + * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): + Likewise. + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): + Likewise. + * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve): + Likewise. + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): + Likewise. + * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): + Likewise. + * typecheck/rust-typecheck-context.cc (TypeCheckContext::push_return_type): + Likewise. + (TypeCheckContext::insert_associated_impl_mapping): Likewise. + * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::scan): Likewise. + (TypeBoundsProbe::add_trait_bound): Likewise. + (TypeBoundPredicate::operator=): Likewise. + (TypeBoundPredicateItem::get_tyty_for_receiver): Likewise. + (TypeBoundPredicate::get_associated_type_items): Likewise. + * typecheck/rust-tyty-call.cc (TypeCheckMethodCallExpr::go): Likewise. + * typecheck/rust-tyty-subst.cc (SubstitutionRef::clone_substs): + Likewise. + (SubstitutionRef::infer_substitions): Likewise. + (SubstitutionRef::are_mappings_bound): Likewise. + * typecheck/rust-tyty-variance-analysis.cc (GenericTyPerCrateCtx::query_generic_variance): + Likewise. + (GenericTyVisitorCtx::add_constraint): Likewise. + * typecheck/rust-tyty.cc (FnPtr::clone): Likewise. + (DynamicObjectType::get_object_items): Likewise. + * typecheck/rust-unify.cc (UnifyRules::Resolve): Likewise. + (UnifyRules::go): Likewise. + (UnifyRules::expect_tuple): Likewise. + * util/rust-canonical-path.h: Likewise. + * util/rust-token-converter.cc (convert): Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/bi-map.h: Add include directive for required declarations. + * util/fnv-hash.h: Likewise. + * util/rust-dump.h: Likewise. + * util/rust-inline-visitor.h: Likewise. + * util/rust-unwrap-segment.h: Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/rust-lang-item.h (RUST_LANG_ITEM_H): Add header guards. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse.h: Change class to struct for friend qualification. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * checks/lints/rust-lint-marklive-base.h (RUST_HIR_LIVENESS_BASE): + Remove header includes. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-cond-compilation.h: Delete copy constructor for + ConfigurationAll and ConfigurationAny. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-type.h: Update member instead of parameter + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-cond-compilation.h: Move vector instead of passing it by + value. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-pattern.h: Include header directly. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-cond-compilation.h: Copy cfg_attrs + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-formatting.h (RUST_AST_FORMATTING_H): Include required + headers directly. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * util/rust-attributes.cc (Attributes::extract_string_literal): + New function definition. + * util/rust-attributes.h (Attributes::extract_string_literal): + New function declaration. + * ast/rust-collect-lang-items.cc (get_lang_item_attr): Use + extract_string_literal. + * backend/rust-compile-base.cc: Include "rust-attributes.h". + (HIRCompileBase::handle_link_section_attribute_on_fndecl): + Use extract_string_literal. + (HIRCompileBase::handle_must_use_attribute_on_fndecl): Likewise. + * hir/rust-ast-lower-base.cc + (ASTLoweringBase::handle_lang_item_attribute): Likewise. + * rust-session-manager.cc (Session::handle_crate_name): + Likewise. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * hir/tree/rust-hir-pattern.h: + - Rename TupleItems to PatternItems. + - Rename TuplePatternItemsMultiple/Ranged & TupleStructItemsRange/NoRange to + TuplePatternItemsNoRest/HasRest and TupleStructItemsNoRest/HasRest. + - Update enum values to NO_REST/HAS_REST. + - Rename clone_tuple_items_impl to clone_pattern_items_impl. + * hir/tree/rust-hir-full-decls.h: Renamed the classes accordingly. + * hir/tree/rust-hir-visitor.h: Renamed the classes accordingly. + * hir/tree/rust-hir-visitor.cc: Renamed the classes accordingly. + * hir/rust-hir-dump.h: Renamed the classes accordingly. + * hir/rust-hir-dump.cc: Renamed the classes accordingly. + * hir/tree/rust-hir.cc: Renamed the classes accordingly. + * hir/rust-ast-lower-base.cc: Renamed the classes accordingly. + * hir/rust-ast-lower-pattern.cc: Renamed the classes accordingly. + * backend/rust-compile-pattern.cc: Renamed the classes accordingly. + * backend/rust-compile-var-decl.h: Renamed the classes accordingly. + * checks/errors/borrowck/rust-bir-builder-pattern.cc: Renamed the classes accordingly. + * checks/errors/borrowck/rust-bir-builder-struct.h: Renamed the classes accordingly. + * checks/errors/borrowck/rust-function-collector.h: Renamed the classes accordingly. + * checks/errors/rust-const-checker.cc: Renamed the classes accordingly. + * checks/errors/rust-const-checker.h: Renamed the classes accordingly. + * checks/errors/rust-hir-pattern-analysis.cc: Renamed the classes accordingly. + * checks/errors/rust-hir-pattern-analysis.h: Renamed the classes accordingly. + * checks/errors/rust-unsafe-checker.cc: Renamed the classes accordingly. + * checks/errors/rust-unsafe-checker.h: Renamed the classes accordingly. + * checks/errors/rust-readonly-check2.cc: Renamed the classes accordingly. + * typecheck/rust-hir-type-check-pattern.cc: Update references to renamed classes and enum + values. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-derive-eq.cc: Use empty vector explicitly. + +2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> + + * Make-lang.in (rust-readonly-check2.cc): + Add read-only check on HIR + * checks/errors/rust-readonly-check2.cc (ReadonlyChecker): + Add read-only check on HIR + * checks/errors/rust-readonly-check2.h (ReadonlyChecker): + Add read-only check on HIR + +2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> + + * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): + Call base class's accept_vis method + +2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> + + * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): + Add check before calling `get_trait_ref()` + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-macro-builtins-helpers.cc + (try_extract_string_literal_from_fragment): Perform static_cast + to AST::LiteralExpr only after it's verified that an AST::Expr + is a literal. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * util/rust-attribute-values.h + (Attributes::RUSTC_ARGS_REQUIRED_CONST): New constexpr variable. + * util/rust-attributes.cc (__definitions): New entry for + RUSTC_ARGS_REQUIRED_CONST. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast.cc (AttributeParser::parse_meta_item_inner): + Handle removal of AttributeParser-specific functions. + (AttributeParser::parse_path_meta_item): Likewise. + (AttributeParser::parse_meta_item_seq): Likewise. + (AttributeParser::parse_meta_item_lit): Likewise. + (AttributeParser::parse_literal): Remove function. + (AttributeParser::parse_simple_path): Likewise. + (AttributeParser::parse_simple_path_segment): Likewise. + (AttributeParser::peek_token): Likewise. + (AttributeParser::skip_token): Likewise. + * ast/rust-macro.h (AttributeParser::parse_simple_path): + Likewise. + (AttributeParser::parse_simple_path_segment): Likewise. + (AttributeParser::parse_literal): Likewise. + (AttributeParser::peek_token): Likewise. + (AttributeParser::skip_token): Likewise. + * parse/rust-parse.h (Parser): Make AttributeParser a friend + class. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * backend/rust-compile-expr.cc (CompileExpr::visit): Add proper handling + of the node. + * rust-backend.h (lookup_field): Declare it. + * rust-gcc.cc (lookup_field): Add forked implementation from gcc/c/. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast.cc (AttributeParser::parse_path_meta_item): Catch + parse_expr returning nullptr and remove defunct comment. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in (GRS_OBJS): Add entries. + * parse/rust-parse-impl.h: Adjust header comment. + (Parser::parse_lifetime_params_objs): Fix bug and add comment. + (Parser::unexpected_token): Likewise. + * parse/rust-parse.h: Remove inclusion of "rust-parse-impl.h". + * parse/rust-parse-impl-lexer.cc: New file. + * parse/rust-parse-impl-macro.cc: New file. + * parse/rust-parse-impl-proc-macro.cc: New file. + +2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> + + * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): + Fix object copying issue causing pointer inconsistency + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.cc (AttributeParser::parse_path_meta_item): Parse + expression instead of literal. Update variant name. + (MetaItemPathLit::to_attribute): Remove function. + (AttributeParser::parse_path_meta_item): Update name. + (MetaItemPathLit::check_cfg_predicate): Likewise. + (MetaItemPathExpr::check_cfg_predicate): Likewise. + (MetaItemPathLit::accept_vis): Likewise. + (MetaItemPathExpr::accept_vis): Likewise. + * ast/rust-ast-collector.h: Update prototype and adapt code to new + expression. + * ast/rust-ast-collector.cc: Update code to expr. + * ast/rust-ast-full-decls.h (class MetaItemPathLit): Likewise. + (class MetaItemPathExpr): Likewise. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * ast/rust-ast-visitor.h: Likewise. + * ast/rust-ast.h (class MetaItemPathLit): Rename class from here... + (class MetaItemPathExpr): ... to here. + * ast/rust-expr.h (class MetaItemPathLit): Rename class from here... + (class MetaItemPathExpr): ...to here. + * expand/rust-derive.h: Update class name. + * expand/rust-expand-visitor.cc (ExpandVisitor::visit): Likewise. + * expand/rust-expand-visitor.h: Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. + * hir/rust-ast-lower-base.h: Likewise. + * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise. + * resolve/rust-ast-resolve-base.h: Likewise. + * resolve/rust-early-name-resolver.cc (EarlyNameResolver::visit): + Likewise. + * resolve/rust-early-name-resolver.h: Likewise. + * util/rust-attributes.cc (AttributeChecker::visit): Likewise. + * util/rust-attributes.h: Likewise. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty-subst.cc (SubstitutionRef::infer_substitions): remove debug + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-type-util.cc (unify_site_and): improve debug + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-autoderef.cc: remove useless assertion + * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsafe_ptr): refactor + (TypeCoercionRules::coerce_borrowed_pointer): remove FIXME this is fine + * typecheck/rust-hir-inherent-impl-overlap.h: use types_compatable + * typecheck/rust-hir-path-probe.cc (PathProbeType::PathProbeType): remove const + (PathProbeType::Probe): likewise + (PathProbeImplTrait::PathProbeImplTrait): likewise + (PathProbeImplTrait::Probe): likewise + * typecheck/rust-hir-path-probe.h: likewise + * typecheck/rust-hir-type-check-base.cc (walk_types_to_constrain): likewise + * typecheck/rust-hir-type-check-base.h: likewise + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): use types_compatable + * typecheck/rust-hir-type-check.h: remove const + * typecheck/rust-typecheck-context.cc (TypeCheckContext::insert_associated_impl_mapping): + likewise + (TypeCheckContext::lookup_associated_impl_mapping_for_self): remove can_Eq + * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::is_equal): likewise + * typecheck/rust-tyty-subst.cc (SubstitutionArg::get_tyty): remove const version + * typecheck/rust-tyty-subst.h: likewise + * typecheck/rust-tyty.cc (BaseType::get_root): likewise + * typecheck/rust-tyty.h: likewise + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty-subst.cc: track the const generic + * typecheck/rust-tyty.cc (ConstType::is_equal): finish the is_equal + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * hir/rust-hir-dump.cc (Dump::Dump): Initialize flag. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::ASTLoweringPattern): + flag was not initialized in the constructor. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): Remove + use after move. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-helpers.cc: Remove use after move. + +2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com> + + * ast/rust-ast-collector.cc: Add support for the 2 new classes. + * ast/rust-ast-collector.h: Header file update for above. + * ast/rust-ast-full-decls.h: Add forward decls for the 2 new classes. + * ast/rust-ast-visitor.cc: Add visit support for the 2 new classes. + * ast/rust-ast-visitor.h: Header file update for above. + * ast/rust-pattern.cc: Implementation of certain methods for the 2 new classes. + * ast/rust-pattern.h: Define the 2 new classes. Update SlicePattern to be able to hold + 2 kinds of items - SlicePatternItemsNoRest or SlicePatternItemsRest. + * expand/rust-cfg-strip.cc: Add support for the 2 new classes. + * expand/rust-cfg-strip.h: Header file update for above. + * expand/rust-derive.h: Add visits for the 2 new classes. + * hir/rust-ast-lower-base.cc: Add visits for the 2 new classes. + * hir/rust-ast-lower-base.h: Header file update for above. + * hir/rust-ast-lower-pattern.cc: Update lowering of SlicePattern to support + SlicePatternItemsNoRest. + * parse/rust-parse-impl.h (parse_slice_pattern()): Add support for parsing DOT_DOT into + respective SlicePatternItems. + * resolve/rust-ast-resolve-base.cc: Add visits for the 2 new classes. + * resolve/rust-ast-resolve-base.h: Header file update for above. + * resolve/rust-ast-resolve-pattern.cc: Update SlicePattern resolution to support new + classes. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty-subst.cc: fix check for total arguments + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): create infer variable + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * hir/rust-hir-dump.cc (Dump::visit): check for expression + * hir/tree/rust-hir.cc (AnonConst::as_string): likewise + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): check for value + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): formatting + * typecheck/rust-tyty-variance-analysis-private.h: likewise + * typecheck/rust-tyty.cc (VariantDef::clone): likewise + (VariantDef::monomorphized_clone): likewise + * typecheck/rust-tyty.h: likewise + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-base.cc: useful debug + * backend/rust-compile-stmt.cc (CompileStmt::visit): likewise + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): fold the capacity into ConstType + * hir/tree/rust-hir-generic-param.h: make const + * hir/tree/rust-hir-path.h: take into account const arguments now + * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): needs const + * typecheck/rust-hir-type-check-base.h: add error handling for const supported locations + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): const type the arrays + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit): update + (TypeCheckImplItem::visit): likewise + * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): likewise + (TypeCheckItem::resolve_impl_block_substitutions): likewise + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): wrap up const type + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise + (TypeResolveGenericParam::visit): likewise + (TypeResolveGenericParam::apply_trait_bounds): remove HIR::Generic from Param + * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): cleanup + * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping): + handle const generics + (SubstitutionParamMapping::get_type_representation): likewise + (SubstitutionParamMapping::param_has_default_ty): likewise + (SubstitutionParamMapping::get_default_ty): likewise + (SubstitutionRef::infer_substitions): likewise + * typecheck/rust-tyty-subst.h: likewise + * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): new helper + * typecheck/rust-tyty-util.h (class ConstType): likewise + * typecheck/rust-tyty.cc (BaseType::is_concrete): check for array const concrete + (ArrayType::as_string): update to const + (ArrayType::handle_substitions): likewise + (ParamType::ParamType): likewise + (ParamType::get_generic_param): likewise + (ParamType::clone): likewise + (ConstType::ConstType): likewise + (ConstType::set_value): likewise + (ConstType::clone): likewise + (ConstType::get_generic_param): likewise + (generate_tree_str): new helper to pretty print gimple + (ConstType::get_name): uses the generate_tree_str + (ConstType::handle_substitions): handle const infer's + * typecheck/rust-tyty.h (RUST_TYTY): likewise + * typecheck/rust-unify.cc (UnifyRules::expect_array): likewise + (UnifyRules::expect_const): likewise + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): error_mark_node for const types + * backend/rust-compile-type.h: boilerplate + * checks/errors/borrowck/rust-bir-fact-collector.h: likewise + * checks/errors/borrowck/rust-bir-place.h: likewise + * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::check_base_type_privacy): + likewise + * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): likewise + * typecheck/rust-substitution-mapper.h: likewise + * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::assemble_marker_builtins): likewise + * typecheck/rust-tyty-call.h: likewise + * typecheck/rust-tyty-cmp.h (class ConstCmp): likewise + * typecheck/rust-tyty-variance-analysis-private.h: likewise + * typecheck/rust-tyty-visitor.h: likewise + * typecheck/rust-tyty.cc (TypeKindFormat::to_string): likewise + (BaseType::is_unit): likewise + (BaseType::has_substitutions_defined): likewise + (BaseType::needs_generic_substitutions): likewise + (ConstType::ConstType): likewise + (ConstType::accept_vis): likewise + (ConstType::as_string): likewise + (ConstType::can_eq): likewise + (ConstType::clone): likewise + (ConstType::get_symbol): likewise + (ConstType::get_generic_param): likewise + (ConstType::can_resolve): likewise + (ConstType::resolve): likewise + (ConstType::get_name): likewise + (ConstType::is_equal): likewise + (ConstType::handle_substitions): likewise + * typecheck/rust-tyty.h (enum TypeKind): new tyty_kind + (class ConstType): new type + * typecheck/rust-unify.cc (UnifyRules::go): Handle a const type unify + (UnifyRules::expect_inference_variable): likewise + (UnifyRules::expect_adt): likewise + (UnifyRules::expect_str): likewise + (UnifyRules::expect_reference): likewise + (UnifyRules::expect_pointer): likewise + (UnifyRules::expect_param): likewise + (UnifyRules::expect_array): likewise + (UnifyRules::expect_slice): likewise + (UnifyRules::expect_fndef): likewise + (UnifyRules::expect_fnptr): likewise + (UnifyRules::expect_tuple): likewise + (UnifyRules::expect_bool): likewise + (UnifyRules::expect_char): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + (UnifyRules::expect_isize): likewise + (UnifyRules::expect_usize): likewise + (UnifyRules::expect_placeholder): likewise + (UnifyRules::expect_projection): likewise + (UnifyRules::expect_dyn): likewise + (UnifyRules::expect_closure): likewise + (UnifyRules::expect_const): likewise + * typecheck/rust-unify.h: new expect_const_type handler + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-intrinsic.cc (sizeof_handler): refactor types + (op_with_overflow_inner): likewise + (uninit_handler): likewise + (move_val_init_handler): likewise + * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): likewise + * typecheck/rust-hir-trait-resolve.cc: likewise + * typecheck/rust-hir-type-check-base.cc: likewise + * typecheck/rust-hir-type-check-item.cc: likewise + * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::is_equal): likewise + * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_param_ty): likewise + (SubstitutionArg::get_param_mapping): likewise + (SubstitutionRef::prepare_higher_ranked_bounds): likewise + (SubstitutionRef::monomorphize): likewise + * typecheck/rust-tyty-subst.h (class BaseGeneric): new generic base + * typecheck/rust-tyty.cc (VariantDef::clone): likewise + (VariantDef::monomorphized_clone): refactor + (ADTType::is_equal): likewise + (FnType::is_equal): likewise + (ParamType::ParamType): likewise + * typecheck/rust-tyty.h (class ParamType): likewise + (class BaseGeneric): new base class impl + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (ADTType::is_equal): let param::is_eq do this + (FnType::is_equal): remove whitespace + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-base.cc: check for type param + * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping): + return HIR::GenericParam base class + (SubstitutionParamMapping::get_generic_param): likewise + (SubstitutionParamMapping::get_type_representation): new helper + (SubstitutionParamMapping::param_has_default_ty): check for param type + (SubstitutionParamMapping::get_default_ty): likewise + * typecheck/rust-tyty-subst.h: get the locus from the subst HIR::GenericParam now + * typecheck/rust-tyty-variance-analysis.cc (GenericTyPerCrateCtx::debug_print_solutions): + likwise + (GenericTyVisitorCtx::process_type): likewise + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::visit): check for ADTType instead of assert + +2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> + + * checks/lints/rust-lint-unused-var.cc (check_decl): + Do not warn about unused `self` parameter. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * Make-lang.in: + * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch_loops): Call DesugarWhileLet. + * ast/rust-desugar-while-let.cc: New file. + * ast/rust-desugar-while-let.h: New file. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.cc (AttrInputMacro::operator=): Add return type. + * ast/rust-expr.h: Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-desugar-for-loops.cc: Remove functions implemented in AST::Builder. + * ast/rust-desugar-for-loops.h: Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * hir/rust-ast-lower-base.cc: Add rust_unreachable() when lowering desugared exprs. + * hir/rust-ast-lower-base.h: Mention this. + * hir/rust-ast-lower-block.h: Remove existing definitions. + * hir/rust-ast-lower-expr.cc: Likewise. + * hir/rust-ast-lower-expr.h: Likewise. + * hir/rust-ast-lower.cc: Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-desugar-question-mark.cc (DesugarQuestionMark::go): Add assertion for the + expr's type. + * ast/rust-desugar-try-block.cc (DesugarTryBlock::go): Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-desugar-for-loops.h: Adapt API and remove visitor. + * ast/rust-desugar-for-loops.cc: Likewise. + * ast/rust-expression-yeast.cc: Call DesugarForLoop. + * ast/rust-expression-yeast.h: Declare dispatch_loops function. + * rust-session-manager.cc (Session::expansion): Do not call for-loop desugar. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * hir/tree/rust-hir-expr.h (class OffsetOf): New. + * hir/tree/rust-hir-expr.cc: Define its methods. + * hir/tree/rust-hir-expr-abstract.h: Add ExprType::OffsetOf. + * hir/tree/rust-hir-full-decls.h (class OffsetOf): Declare it. + * backend/rust-compile-block.h: Add handling for OffsetOf. + * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise. + * backend/rust-compile-expr.h: Likewise. + * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise. + * checks/errors/borrowck/rust-bir-builder-expr-stmt.h (RUST_BIR_BUILDER_EXPR_H): Likewise. + * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise. + * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise. + * checks/errors/borrowck/rust-function-collector.h: Likewise. + * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit): Likewise. + * checks/errors/privacy/rust-privacy-reporter.h (RUST_PRIVACY_REPORTER_H): Likewise. + * checks/errors/rust-const-checker.cc (ConstChecker::visit): Likewise. + * checks/errors/rust-const-checker.h: Likewise. + * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Likewise. + * checks/errors/rust-hir-pattern-analysis.h: Likewise. + * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Likewise. + * checks/errors/rust-unsafe-checker.h: Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + * hir/rust-hir-dump.cc (Dump::visit): Likewise. + * hir/rust-hir-dump.h: Likewise. + * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Likewise. + * hir/tree/rust-hir-visitor.h: Likewise. + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. + * typecheck/rust-hir-type-check-expr.h (RUST_HIR_TYPE_CHECK_EXPR): Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * Make-lang.in: Compile the offset_of handler. + * lang.opt: Add -frust-assume-builtin-offset-of option. + * ast/rust-ast.h: Add has_str() for const_TokenPtr. + * expand/rust-macro-builtins.cc: Map offset_of as builtin. + * expand/rust-macro-builtins.h: Declare it. + * expand/rust-macro-expand.cc (MacroExpander::expand_invoc): Add hack for calling builtin + offset_of!(). + * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Likewise. + * expand/rust-macro-builtins-offset-of.cc: New file. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.h: Add OffsetOf expression kind. + * ast/rust-builtin-ast-nodes.h (class OffsetOf): Add node. + * ast/rust-ast.cc: Define it. + * ast/rust-ast-collector.cc: Add visitor for OffsetOf. + * ast/rust-ast-collector.h: Likewise. + * ast/rust-ast-visitor.cc: Likewise. + * ast/rust-ast-visitor.h: Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. + * hir/rust-ast-lower-base.h: Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + * hir/rust-ast-lower-expr.h: Likewise. + * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise. + * resolve/rust-ast-resolve-base.h: Likewise. + * resolve/rust-early-name-resolver-2.0.cc: Likewise. + * expand/rust-derive.h: + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust-diagnostics.h (struct Error): Add disambiguation. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-asm.cc (parse_format_strings): Emit an + error when expecting a comma. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * checks/errors/borrowck/rust-bir-fact-collector.h: Remove spurious + comment. + * checks/errors/rust-feature.cc: Likewise. + * util/optional.h: Likewise. + * expand/rust-token-tree-desugar.cc (TokenTreeDesugar::visit): Remove + semicolons on namespace. + * expand/rust-token-tree-desugar.h: Likewise. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * typecheck/rust-hir-type-check-base.cc + (TypeCheckBase::TypeCheckBase): Remove initialization of + resolver field. + * typecheck/rust-hir-type-check-base.h + (TypeCheckBase::resolver): Remove field. + * typecheck/rust-hir-trait-resolve.cc: Remove "options.h" + include. + (TraitResolver::resolve_path_to_trait): Assume name resolution + 2.0 is always enabled. + * typecheck/rust-hir-type-check-enumitem.cc: Remove "options.h" + include. + (TypeCheckEnumItem::visit): Assume name resolution 2.0 is always + enabled. + * typecheck/rust-hir-type-check-expr.cc: Remove "options.h" + include. + (TypeCheckExpr::visit): Assume name resolution 2.0 is always + enabled. + (TypeCheckExpr::resolve_operator_overload): Likewise. + (TypeCheckExpr::resolve_fn_trait_call): Likewise. + * typecheck/rust-hir-type-check-implitem.cc: Remove "options.h" + include. + (TypeCheckImplItem::visit): Assume name resolution 2.0 is always + enabled. + * typecheck/rust-hir-type-check-item.cc: Remove "options.h" + include. + (TypeCheckItem::visit): Assume name resolution 2.0 is always + enabled. + * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit): + Likewise. + (TypeCheckExpr::resolve_root_path): Likewise. + (TypeCheckExpr::resolve_segments): Likewise. + * typecheck/rust-hir-type-check-pattern.cc: Remove "options.h" + include. + (TypeCheckPattern::visit): Assume name resolution 2.0 is always + enabled. + * typecheck/rust-hir-type-check-type.cc + (TypeCheckType::resolve_root_path): Likewise. + (ResolveWhereClauseItem::visit): Likewise. + * typecheck/rust-hir-type-check.cc: Remove "options.h" include. + (TraitItemReference::get_type_from_fn): Assume name resolution + 2.0 is always enabled. + * typecheck/rust-type-util.cc (query_type): Likewise. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * backend/rust-compile-asm.cc (get_out_expr): Return valid output from + an operand. + (CompileAsm::asm_construct_outputs): Handle every output + (get_in_expr): Return valid input from an operand. + (CompileAsm::asm_construct_inputs): Handle every input + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-asm.cc (parse_reg_operand_inout): Parse + expressions and build split in out. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * hir/rust-hir-dump.cc (Dump::visit): Dump inline assembly fields + * hir/tree/rust-hir-expr.h: Add non const getter and avoid operand copy + from getters. + * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Use non const + reference. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): Handle + transformation for indexed positional arguments. + +2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust-backend.h: New slice_index_expression function. + * rust-gcc.cc: Implementation of slice_index_expression to generate tree node for + accessing slice elements. + * backend/rust-compile-pattern.cc: Implement SlicePattern check expression & binding + compilation against SliceType scrutinee. + +2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(SlicePattern)): + Add new type check case for SliceType wrapped in ReferenceType. + * backend/rust-compile-pattern.cc: Adjusted the asserts accordingly for + CompilePatternCheckExpr(SlicePattern) & CompilePatternBindings(SlicePattern). + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * Make-lang.in: Compile it. + * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch): Dispatch to try-block + desugar. + * ast/rust-desugar-try-block.cc: New file. + * ast/rust-desugar-try-block.h: New file. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.h: Add the new variant. + * ast/rust-expr.h: Use it for TryExpr class. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add + visitor for IfLetExprConseqElse. + * resolve/rust-default-resolver.h (DefaultResolver::visit): + Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit a block's loop label if it + exists. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * Make-lang.in: Compile it. + * rust-session-manager.cc: Call the expression desugar dispatcher. + * ast/rust-desugar-question-mark.cc: Rework class API. + * ast/rust-desugar-question-mark.h: Likewise. + * ast/rust-expression-yeast.cc: New file. + * ast/rust-expression-yeast.h: New file. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-expr.h: Fix formatting. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Handle defered consts. + * hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise. + (AnonConst::operator=): Likewise. + * hir/tree/rust-hir-expr.h: Likewise. + * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Likewise. + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-expr.h: Add handling for deferred consts. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * ast/rust-ast.cc (AnonConst::as_string): Likewise. + (ArrayType::as_string): Likewise. + * ast/rust-type.h (class ArrayType): Use AnonConst for sizes. + * parse/rust-parse-impl.h (Parser::parse_anon_const): New function. + (Parser::parse_slice_or_array_type): Call it. + * parse/rust-parse.h: Declare it. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * resolve/rust-early-name-resolver-2.0.cc (Early::resolve_glob_import): Adapt for enums. + (Early::finalize_glob_import): Likewise. + * resolve/rust-early-name-resolver-2.0.h: Likewise. + * resolve/rust-finalize-imports-2.0.cc (GlobbingVisitor::go): Likewise. + (GlobbingVisitor::visit_module_container): New function. + (GlobbingVisitor::visit_enum_container): New function. + * resolve/rust-finalize-imports-2.0.h: Declare them. + * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Insert enums as potential + containers. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * util/rust-hir-map.cc (Mappings::insert_ast_module): Rename to... + (Mappings::insert_glob_container): ...this. + (Mappings::lookup_ast_module): Rename to... + (Mappings::lookup_glob_container): ...this. + * util/rust-hir-map.h: Change declarations. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-cfg-strip.cc (CfgStrip::visit): Load unloaded + modules. + * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): + Assume modules have been loaded by CfgStrip. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-expand-visitor.cc + (ExpandVisitor::expand_inner_items): Adjust call to + expand_macro_children. + (ExpandVisitor::expand_inner_stmts): Likewise. + (ExpandVisitor::visit): Likewise. + * expand/rust-expand-visitor.h + (ExpandVisitor::expand_macro_children): Take a pointer to member + function instead of a std::function. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): do another lookup + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast.cc: Include "rust-macro-invoc-lexer.h". + (AttributeParser::~AttributeParser): Move function definition + here. + (AttributeParser::AttributeParser): Likewise and adjust member + initialization. + (AttributeParser::parse_meta_item_inner): Handle changes to + peek_token. + (AttributeParser::parse_literal): Likewise. + (AttributeParser::parse_simple_path_segment): Likewise. + (AttributeParser::parse_meta_item_seq): Handle changes to + AttributeParser fields. + (AttributeParser::peek_token): Move function definition here and + wrap MacroInvocLexer. + (AttributeParser::skip_token): Likewise. + * ast/rust-macro.h (class MacroInvocLexer): Forward declare. + (class Parser): Likewise. + (AttributeParser::token_stream): Remove field. + (AttributeParser::stream_pos): Likewise. + (AttributeParser::lexer): New field. + (AttributeParser::parser): Likewise. + (AttributeParser::AttributeParser): Move definition to + "rust-ast.cc". + (AttributeParser::~AttributeParser): Likewise. + (AttributeParser::peek_token): Likewise. + (AttributeParser::skip_token): Likewise. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-resolve-path.cc (ResolvePathRef::resolve): return error_mark_node + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * hir/tree/rust-hir-expr.cc (OperatorExprMeta::OperatorExprMeta): track the rhs + * hir/tree/rust-hir-expr.h: likewise + * hir/tree/rust-hir-path.h: get rid of old comments + * typecheck/rust-hir-trait-reference.cc (TraitReference::get_trait_substs): return + references instead of copy + * typecheck/rust-hir-trait-reference.h: update header + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::ResolveOpOverload): write ambigious + operator overloads to a table and try to resolve it at the end + * typecheck/rust-hir-type-check-expr.h: new static helper + * typecheck/rust-hir-type-check.h (struct DeferredOpOverload): new model to defer resolution + * typecheck/rust-typecheck-context.cc (TypeCheckContext::lookup_operator_overload): new + (TypeCheckContext::compute_ambigious_op_overload): likewise + (TypeCheckContext::compute_inference_variables): likewise + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-base.cc: check the canonical path + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_simple_path): Be more + careful about skipping SCOPE_RESOLUTION tokens. + (Parser::parse_simple_path_segment): Allow parsing from a + starting offset. + (Parser::parse_use_tree): Handle a non-skipped SCOPE_RESOLUTION + token. + * parse/rust-parse.h (Parser::parse_simple_path_segment): Add + parameter for parsing from a starting offset. + +2025-08-05 lishin <lishin1008@gmail.com> + + * backend/rust-compile-expr.cc (CompileExpr::visit): Add a catch for const/static. + +2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust-backend.h: New size_constant_expression function. + * rust-gcc.cc: Implementation of size_constant_expression function to generate tree node + for array access. + * backend/rust-compile-pattern.h: Remove empty visits for SlicePattern. + * backend/rust-compile-pattern.cc: Implement SlicePattern check expression & binding + compilation against ArrayType scrutinee. + +2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc(TypeCheckPattern::visit(SlicePattern)): + Implement size checking for SlicePattern when type checking against array parent + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * util/rust-attribute-values.h: Add declarations for them. + * util/rust-attributes.cc: Add definitions. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::visit): fix typo + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-casts.cc (TypeCastRules::resolve): optional emit_error flag + (TypeCastRules::check): try the simple cast rules then fallback to coercions + (TypeCastRules::check_ptr_ptr_cast): ensure the underlying's + (TypeCastRules::emit_cast_error): make this a static helper + * typecheck/rust-casts.h: new emit_error prototype + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Check for a label + before visiting it. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): track is super trait + * typecheck/rust-hir-type-bounds.h: refactor bounds scan + * typecheck/rust-hir-type-check-base.h: track from super trait + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise + * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::is_bound_satisfied_for_type): refactor + (TypeBoundsProbe::scan): likewise + (TypeBoundPredicate::apply_generic_arguments): likewise + * typecheck/rust-tyty-subst.cc: optional bounds checking on parm subst + * typecheck/rust-tyty-subst.h: likewise + * typecheck/rust-tyty.h: likewise + +2025-08-05 Marc Poulhiès <dkm@kataplop.net> + + * checks/errors/borrowck/rust-bir-place.h (LoanId::value): Make + it size_t to match Loan's base type. + +2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc(TypeCheckPattern::visit(LiteralPattern)): + Check LiteralPattern's type against its parent. + +2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(SlicePattern)): + Implement initial type checking for SlicePattern. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): check for missing borrow + * ast/rust-expr.h: add helper + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-base.cc (HIRCompileBase::query_compile_const_expr): new wrapper + * backend/rust-compile-base.h: add prototype + * backend/rust-compile-context.cc (Context::get): singleton helper + * backend/rust-compile-context.h: likewise + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): handle infer's that can default + * rust-session-manager.cc (Session::compile_crate): create the gcc context earlier for tychk + * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): const fold it + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise + * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): fix constructor call + (ArrayType::as_string): print capacity + (ArrayType::clone): fix constructor call + * typecheck/rust-tyty.h: track capacity + * typecheck/rust-unify.cc (UnifyRules::expect_array): check the capacities + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): New visitor. + * resolve/rust-late-name-resolver-2.0.h: Declare it. + * resolve/rust-name-resolution-context.h (enum class): New binding context. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Check that the WhileLet has a label + before visiting it. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Add visitor + for TryExpr. + * ast/rust-ast-collector.h (TokenCollector::visit): Likewise. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * ast/rust-ast-visitor.h (ASTVisitor::visit): Likewise. + (DefaultASTVisitor::visit): Likewise. + * expand/rust-derive.h (DeriveVisitor::visit): Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. + * hir/rust-ast-lower-base.h (ASTLoweringBase::visit): Likewise. + * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): + Likewise. + * resolve/rust-ast-resolve-base.h (ResolverBase::visit): + Likewise. + * ast/rust-ast-full-decls.h (class TryExpr): New forward class + declaration. + * ast/rust-ast.cc (TryExpr::as_string): New function. + (TryExpr::accept_vis): Likewise. + * ast/rust-expr.h (class TryExpr): New class. + * parse/rust-parse.h (Parser::parse_try_expr): New function. + * parse/rust-parse-impl.h (Parser::parse_try_expr): Likewise. + (Parser::null_denotation_not_path): Use parse_try_expr to parse + try expressions. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-macro-builtins-format-args.cc + (format_args_parse_arguments): Accept a RAW_STRING_LITERAL token + as the first argument. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse-impl.h: Add enum prefix. + * parse/rust-parse.h (enum ParseSelfError): Change from enum... + (enum class): To enum class. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Replace + usages of reinterpret_cast with static_cast. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove + override for StructStruct visitor. + * resolve/rust-late-name-resolver-2.0.h (Late::visit): Likewise. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * backend/rust-compile-context.cc (Context::Context): Remove + initialization of resolver field. + * backend/rust-compile-context.h (Context::get_resolver): Remove + function. + (Context::resolver): Remove field. + * backend/rust-compile-expr.cc (CompileExpr::visit): Assume name + resolution 2.0 is always enabled. + (CompileExpr::generate_closure_function): Likewise. + * backend/rust-compile-implitem.cc (CompileTraitItem::visit): + Likewise. + * backend/rust-compile-item.cc (CompileItem::visit): Likewise. + * backend/rust-compile-resolve-path.cc + (ResolvePathRef::resolve): Likewise. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * lang.opt (frust-name-resolution-2.0): Enable by default. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(TuplePattern)): + Implement check expression compilation for TuplePatternItems::RANGED. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (visit(TuplePattern)): Fix + incorrect logic for field size checking. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-builder.cc: Remove extra include, fix new formatting. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.h (reconstruct_vec): Pre-allocate size of vector. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * Make-lang.in: Remove object file for ASTTypeBuilder. + * ast/rust-ast-builder.h: Remove function. + * ast/rust-ast-builder.cc (Builder::new_type): Likewise. + (Builder::new_const_param): Use reconstruct_type() instead. + (Builder::new_generic_args): Likewise. + * expand/rust-derive-default.cc (DeriveDefault::visit_struct): Likewise. + (DeriveDefault::visit_tuple): Likewise. + * expand/rust-derive-eq.cc (DeriveEq::visit_tuple): Likewise. + (DeriveEq::visit_struct): Likewise. + (DeriveEq::visit_enum): Likewise. + (DeriveEq::visit_union): Likewise. + * ast/rust-ast-builder-type.cc: Removed. + * ast/rust-ast-builder-type.h: Removed. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.h: Add reconstruct() and reconstruct_impl() for Type nodes. + * ast/rust-type.h: Implement them. + * ast/rust-macro.h: Likewise. + * ast/rust-path.h: Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.h (reconstruct): New function for calling the `reconstruct_*_impl` method + and asserting that the new NodeId is different, and then wrap it in a unique_ptr<T>. + (reconstruct_vec): Likewise, but for vectors of unique_ptr<T> + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path): + Resolve final segments which point to modules. + * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): + Avoid inserting module names into ribs in the type namespace. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-late-name-resolver-2.0.cc + (visit_identifier_as_pattern): Handle is_ref and is_mut. + (Late::visit): Likewise. + * resolve/rust-name-resolution-context.cc + (BindingLayer::insert_ident): Likewise. + (BindingLayer::bind_test): Handle changes to BindingLayer + fields. + (BindingLayer::merge): Likewise and emit more error messages. + * resolve/rust-name-resolution-context.h + (struct IdentifierMode): New. + (Binding::has_expected_bindings): New field. + (Binding::set): Rename field to... + (Binding::idents): ...here and convert from a set to a map. + (Binding::Binding): Initialize has_expected_bindings. + (BindingLayer::insert_ident): Adjust parameters. + +2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h: Add getter to locus field. + * ast/rust-pattern.h (tokenid_to_rangekind): Likewise. + * hir/tree/rust-hir-item.h: Likewise. + * hir/tree/rust-hir-visibility.h: Likewise. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-default-resolver.cc + (DefaultResolver::visit_extern_crate): New function. + (DefaultResolver::visit): New visitor function for ExternCrate. + * resolve/rust-default-resolver.h + (DefaultResolver::visit_extern_crate): New function. + (DefaultResolver::visit): New visitor function for ExternCrate. + * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): + Adjust ExternCrate visitor and rename to... + (TopLevel::visit_extern_crate): ...here. + * resolve/rust-toplevel-name-resolver-2.0.h (TopLevel::visit): + Remove ExternCrate visitor override. + (TopLevel::visit_extern_crate): New function. + * rust-session-manager.cc (Session::load_extern_crate): Only run + name resolution 1.0 if name resolution 2.0 is disabled. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(TuplePattern)): + Implement type checking for ItemType::RANGED. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * rust-lang.cc: Move version check from C++11 to C++14. + +2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> + + * Make-lang.in: Scaffolding new rust-hir-visitor files + * hir/tree/rust-hir-visitor.h (DefaultHIRVisitor): Declare default HIR visitor + * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor): Define default HIR visitor + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in (GRS_OBJS): Add rust-ggc.o. + * backend/rust-compile-base.cc + (HIRCompileBase::compile_function): Adjust call to + Backend::function. + (HIRCompileBase::compile_constant_item): Likewise and adjust + initialization of Backend::typed_identifier. + * backend/rust-compile-expr.cc (CompileExpr::visit): Adjust call + to Backend::label. + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): + Adjust initialization of Backend::typed_identifier. + * rust-backend.h: Add includes. + (Backend::GGC::Ident): Use Rust::GGC::Ident. + (struct typed_identifier): Store name as a GGC::Ident rather + than a std::string and adjust constructors. + (named_type): Take GGC::Ident/tl::optional<GGC::Ident> rather + than std::string. + (global_variable): Likewise. + (local_variable): Likewise. + (parameter_variable): Likewise. + (static_chain_variable): Likewise. + (label): Likewise. + (function): Likewise. + * rust-gcc.cc (named_type): Likewise. + (global_variable): Likewise. + (local_variable): Likewise. + (parameter_variable): Likewise. + (static_chain_variable): Likewise. + (label): Likewise. + (function): Likewise. + (function_defer_statement): Adjust call to Backend::label. + (get_identifier_from_string): Remove function. + (fill_in_fields): Handle adjustments to typed_identifier. + * util/rust-ggc.cc: New file. + * util/rust-ggc.h: New file. + +2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> + + * hir/tree/rust-hir-item.h (SelfParam::get_lifetime): Add getter + for non const lifetime object + +2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> + + * hir/tree/rust-hir-expr.h (MatchArm::get_outer_attrs): Add getter for outer attributions + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-resolve-path.cc: if this fails fall back to query compile + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::visit): add const call check + * backend/rust-compile-item.cc (CompileItem::visit): ensure we upfront compile types where + possible + * backend/rust-compile-item.h: update header + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): make parent ctx optional + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc(CompilePatternCheckExpr::visit(TupleStructPattern)): + Fix error thrown when compiling non-enum TupleStructPattern. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-default-resolver.cc (DefaultResolver::visit): + Call DefaultASTVisitor::visit even on ConstantItem instances + without expressions. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): add unify rules + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-trait-reference.cc (TraitReference::on_resolved): ensure associated + types are done first + * typecheck/rust-hir-type-check-type.cc: Update call site. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty-bounds.cc: Check super traits for type bindings. + * typecheck/rust-tyty.h: Add helper methods for bound checking. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-bounds.h: Rename method. + * typecheck/rust-tyty-bounds.cc: Refactor marker trait assembly + and add proper Fn trait handling for function types. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-dot-operator.cc: Major refactoring and cleanup. + * typecheck/rust-hir-dot-operator.h: Add new helper methods. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-trait-resolve.cc: Add cyclical projection + protection. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-expr.cc: Look at bounds behind + references. + * typecheck/rust-hir-type-check-expr.h: Add helper method. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * rust-session-manager.cc (Session::compile_crate): Move + AST desugaring to... + (Session::expansion): ...here and add a final TopLevel pass + afterwards. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): check for has_expr + * hir/rust-hir-dump.cc (Dump::visit): likewise + * hir/tree/rust-hir-item.h: add has_expr helper + * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): check for has_expr + * resolve/rust-ast-resolve-stmt.h: likewise + * typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): likewise + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Add + visitor for ExternCrate. + * hir/rust-ast-lower-item.h (ASTLoweringItem::visit): Likewise. + * rust-session-manager.cc (Session::load_extern_crate): Avoid + lowering or type resolving external crates here. + * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): + Add visitor for ExternCrate. + * typecheck/rust-hir-type-check-item.h (TypeCheckItem::visit): + Replace empty definition with a declaration. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (ParamType::handle_substitions): make this consistent + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit(IdentifierPattern)): + Remove redundant subpattern check. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc: Add support for IdentifierPattern's + subpattern under CompilePatternBindings. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * resolve/rust-ast-resolve-pattern.cc: Implement name resolution for + IdentifierPattern's subpattern. + * resolve/rust-late-name-resolver-2.0.cc: Ditto, but for nr2. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * ast/rust-ast-collector.cc: Rename get_pattern_to_bind to get_subpattern + * ast/rust-ast-visitor.cc: Ditto. + * ast/rust-pattern.h: Ditto. + * expand/rust-cfg-strip.cc: Ditto. + * hir/rust-ast-lower-pattern.cc: Ditto. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-default-resolver.cc (DefaultResolver::visit): + Adjust scoping of trait definitions and their generic + parameters. + * resolve/rust-forever-stack.hxx (ForeverStack::get): Prevent + lookups inside TraitOrImpl ribs. + (ForeverStack::resolve_segments): Prevent lookups of the first + segment inside TraitOrImpl ribs. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * hir/rust-hir-dump.cc: Change pattern dumps to use visit_field. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive.cc: Fix formatting after fork update. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): Create two different + variant paths. + (EnumMatchBuilder::strukt): Likewise. + * expand/rust-derive-cmp-common.h: Change API. + * expand/rust-derive-ord.cc (DeriveOrd::visit_enum): Use new EnumMatchBuilder API. + * expand/rust-derive-partial-eq.cc (DerivePartialEq::visit_enum): Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): Use new make_equal function. + (DeriveOrd::make_equal): New function. + (DeriveOrd::recursive_match): Handle the unit struct/tuple case. + * expand/rust-derive-ord.h: Declare make_equal. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-ord.cc (DeriveOrd::cmp_call): Use references. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): Fix condition. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-ord.cc: Finish implementation for enums. + * expand/rust-derive-ord.h: Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-partial-eq.cc (DerivePartialEq::eq_fn): Change signature. + (DerivePartialEq::visit_tuple): Use new eq_fn API. + (DerivePartialEq::visit_struct): Likewise. + (DerivePartialEq::visit_enum): Implement proper discriminant comparison. + * expand/rust-derive-partial-eq.h: Change eq_fn signature. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-cmp-common.h (class EnumMatchBuilder): New helper class. + * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): New function. + (EnumMatchBuilder::strukt): New function. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-builder.h: Put `loc` member in public. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-ord.cc (DeriveOrd::cmp_call): New function. + (DeriveOrd::recursive_match): Use it. + (DeriveOrd::visit_enum): Likewise. + * expand/rust-derive-ord.h: Declare it. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-hash.cc (DeriveHash::visit_enum): Use new APIs. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-builder.cc (Builder::discriminant_value): New function. + * ast/rust-ast-builder.h: Declare it. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-ord.cc (is_last): Remove. + (DeriveOrd::visit_tuple): Fix implementation. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-cmp-common.cc (SelfOther::indexes): Fix formatting. + (SelfOther::fields): Make iterator const. + * expand/rust-derive-cmp-common.h (struct SelfOther): New declaration for indexes. + * expand/rust-derive-partial-eq.cc (DerivePartialEq::visit_tuple): Use the new API. + (DerivePartialEq::visit_struct): Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): New function. + (is_last): Likewise. + (recursive_match): Likewise. + (DeriveOrd::recursive_match): Likewise. + (DeriveOrd::visit_struct): Add proper implementation. + (DeriveOrd::visit_union): Likewise. + * expand/rust-derive-ord.h: Declare these new functions. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-partial-eq.cc (DerivePartialEq::tuple_indexes): Remove. + (DerivePartialEq::field_acccesses): Remove. + (DerivePartialEq::visit_tuple): Use new API. + (DerivePartialEq::visit_struct): Likewise. + * expand/rust-derive-partial-eq.h: Remove declarations. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-cmp-common.cc: New file. + * expand/rust-derive-cmp-common.h: New file. + * Make-lang.in: Compile them. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-builder.cc (Builder::block): New function. + (Builder::match_case): Likewise. + * ast/rust-ast-builder.h: Declare them. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-builder.cc (Builder::new_const_param): New function. + * ast/rust-ast-builder.h (vec): New function for creating 3 elts vector. + * expand/rust-derive.cc: Use the new_const_param builder. + * ast/rust-path.h: Add get_default_value() method. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * Make-lang.in: Compile it. + * expand/rust-derive.cc (DeriveVisitor::derive): Call them. + * expand/rust-derive-ord.cc: New file. + * expand/rust-derive-ord.h: New file. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-clone.h: Add missing override qualifiers to DeriveVisitor methods. + * expand/rust-derive-copy.h: Likewise. + * expand/rust-derive-eq.h: Likewise. + * expand/rust-derive-hash.h: Likewise. + * expand/rust-derive-partial-eq.h: Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * resolve/rust-rib.h: Add missing switch cases. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-type-util.cc (query_type): early return. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): reuse GCC's build_array_type + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-late-name-resolver-2.0.cc + (visit_identifier_as_pattern): Make sure to map identifiers + inside or-bindings to prior identifiers. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * ast/rust-ast-collector.cc: Rename to_bind to subpattern. + * ast/rust-ast-visitor.cc: Ditto. + * ast/rust-pattern.cc: Ditto. + * ast/rust-pattern.h: Ditto. + * backend/rust-compile-pattern.cc: Ditto. + * expand/rust-cfg-strip.cc: Ditto. + * hir/rust-ast-lower-pattern.cc: Ditto. + * hir/rust-hir-dump.cc: Ditto. + * hir/tree/rust-hir-pattern.h: Ditto. + * hir/tree/rust-hir.cc: Ditto. + * typecheck/rust-hir-type-check-pattern.cc: Ditto. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc: Add CheckExpr compilation for + IdentifierPattern with subpattern. + * backend/rust-compile-pattern.h: Modify IdentifierPattern's + visit func to support the above. + * typecheck/rust-hir-type-check-pattern.cc: Add typechecking + support for the changes above. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-default-resolver.cc + (DefaultResolver::visit_closure_params): New member function + definition. + (DefaultResolver::visit): New visiting function definition for + ClosureExpr called from visiting functions for ClosureExprInner + and ClosureExprInnerTyped. + * resolve/rust-default-resolver.h + (DefaultResolver::visit_closure_params): New member function + declaration. + (DefaultResolver::visit): New visiting function declaration for + ClosureExpr. + * resolve/rust-late-name-resolver-2.0.cc (add_captures): Remove + function. + (Late::visit): New visiting function definition for ClosureExpr, + remove visiting function definitions for ClosureExprInner and + ClosureExprInnerTyped. + (Late::visit_closure_params): New member function definition. + * resolve/rust-late-name-resolver-2.0.h (Late::visit): New + visiting function declaration for ClosureExpr, remove visiting + function declarations for ClosureExprInner and + ClosureExprInnerTyped. + (Late::visit_closure_params): New member function declaration. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path): + Handle single segment paths "crate", "self", and "super". + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use + visit_identifier_as_pattern to handle IdentifierPattern and + StructPatternFieldIdent. + (visit_identifier_as_pattern): New function. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-expr.h (ClosureExpr::get_definition_expr): New + virtual member function. + (ClosureExprInner::get_definition_expr): Add override specifier. + (ClosureExprInnerTyped::get_definition_block): Rename to... + (ClosureExprInnerTyped::get_definition_expr): ...here and add + override specifier. + * ast/rust-ast-collector.cc (TokenCollector::visit): Handle + rename of ClosureExprInnerTyped::get_definition_block to + ClosureExprInnerTyped::get_definition_expr. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise. + * expand/rust-expand-visitor.cc (ExpandVisitor::visit): + Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): + Likewise. + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): + Likewise. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * backend/rust-compile-base.cc + (HIRCompileBase::compile_function): Since canonical paths + returned from nr2.0 now include the crate name, avoid prepending + the crate name again. + * backend/rust-compile-implitem.cc (CompileTraitItem::visit): + Use NameResolutionContext::to_canonical_path instead of + ForeverStack::to_canonical_path. + * backend/rust-compile-item.cc (CompileItem::visit): Likewise. + * typecheck/rust-hir-type-check-enumitem.cc + (TypeCheckEnumItem::visit): Likewise. + * typecheck/rust-hir-type-check-implitem.cc + (TypeCheckImplItem::visit): Likewise. + * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): + Likewise. + * typecheck/rust-hir-type-check.cc + (TraitItemReference::get_type_from_fn): Likewise. + * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add + Crate and EnumItem instance visitors, handle canonical path + context scoping. + * resolve/rust-default-resolver.h (DefaultResolver::visit): Add + Crate and EnumItem instance visitors. + * resolve/rust-early-name-resolver-2.0.cc (Early::go): Visit + instances of Crate using the virtual member function visit. + * resolve/rust-forever-stack.h + (ForeverStack::to_canonical_path): Remove function declaration. + * resolve/rust-forever-stack.hxx + (ForeverStack::to_canonical_path): Remove function definition. + * resolve/rust-late-name-resolver-2.0.cc (Late::go): Visit + instances of Crate using the virtual member function visit. + * resolve/rust-name-resolution-context.cc + (CanonicalPathRecordCrateRoot::as_path): New function definition. + (CanonicalPathRecordNormal::as_path): Likewise. + (CanonicalPathRecordLookup::as_path): Likewise. + (CanonicalPathRecordImpl::as_path): Likewise. + (CanonicalPathRecordTraitImpl::as_path): Likewise. + (NameResolutionContext::NameResolutionContext): Initialize + member variable canonical_ctx. + * resolve/rust-name-resolution-context.h: Include "rust-item.h". + (class NameResolutionContext): Forward declare class. + (class CanonicalPathRecord): New class. + (class CanonicalPathRecordWithParent): Likewise. + (class CanonicalPathRecordCrateRoot): Likewise. + (class CanonicalPathRecordNormal): Likewise. + (class CanonicalPathRecordLookup): Likewise. + (class CanonicalPathRecordImpl): Likewise. + (class CanonicalPathRecordTraitImpl): Likewise. + (class CanonicalPathCtx): Likewise. + (NameResolutionContext::canonical_ctx): New member variable. + (NameResolutionContext::to_canonical_path): New member function. + * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::go): + Visit instances of Crate with the virtual member function visit. + (TopLevel::visit): Handle canonical path context scoping for + external crates, use DefaultResolver::visit when visiting + instances of StructStruct. + * util/rust-canonical-path.h (CanonicalPath::new_seg): Take path + parameter by-value, as a duplicate instance will be constructed + regardless. + +2025-08-05 Zhi Heng <yapzhhg@gmail.com> + + * hir/rust-ast-lower-pattern.cc: Lower of IdentifierPattern's to_bind to HIR. + * hir/rust-hir-dump.cc: Update IdentifierPattern's dump to properly show to_bind's full + full properties. + +2025-08-05 Vishruth-Thimmaiah <vishruththimmaiah@gmail.com> + + * lex/rust-lex.cc (Lexer::parse_raw_byte_string): + Fix infinite looping when a raw byte string is not terminated. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-default-resolver.cc (DefaultResolver::visit): Use + visit_impl_type to visit the self types of impl blocks. + * resolve/rust-default-resolver.h + (DefaultResolver::visit_impl_type): New member function + declaration. + * resolve/rust-late-name-resolver-2.0.cc (Late::Late): + Initialize member variable block_big_self. + (Late::visit_impl_type): New member function definition. + (Late::visit): Check for Self while inside impl block self + types. + * resolve/rust-late-name-resolver-2.0.h (Late::visit_impl_type): + New member function. + (Late::block_big_self): New member variable. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-forever-stack.h + (enum ResolutionMode): New. + (ForeverStack::get): Add a private overload that takes a + starting node as a parameter. + (ForeverStack::resolve_path): Replace boolean parameter + has_opening_scope_resolution with ResolutionMode parameter mode. + * resolve/rust-forever-stack.hxx + (ForeverStack::resolve_path): Likewise. + (ForeverStack::get): Add a private overload that takes a + starting node as a parameter. + * resolve/rust-late-name-resolver-2.0.cc + (Late::visit): Add Visibility visitor. + * resolve/rust-late-name-resolver-2.0.h + (Late::visit): Likewise. + * resolve/rust-name-resolution-context.h + (NameResolutionContext::resolve_path): Rework overloading a bit + and accept ResolutionMode parameter. + +2025-08-05 Vishruth-Thimmaiah <vishruththimmaiah@gmail.com> + + * parse/rust-parse.cc (Rust::extract_module_path): + Handle empty or whitespace-only path attributes. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Handle + changed type of ConstantItem::identifier. + * ast/rust-ast.cc (ConstantItem::as_string): Likewise. + * ast/rust-ast.h (operator const std::string &): New member + function. + * ast/rust-item.h (ConstantItem::identifier): Change type from + std::string to Identifier. + (ConstantItem::ConstantItem): Handle changed type of identifier + field. + (ConstantItem::is_unnamed): Likewise. + (ConstantItem::get_identifier): Likewise. + * hir/rust-ast-lower-extern.h (ASTLoweringExternItem::visit): + Avoid discarding location of wildcard patterns. + * lex/rust-token.cc: Include "rust-ast.h". + (Token::make_identifier): Add overload accepting an Identifier + instance. + * lex/rust-token.h (class Identifier): Add forward declaration + in order to... + (Token::make_identifier): ...declare an overload for this static + member function. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * hir/tree/rust-hir-expr.h: New classes. + * hir/tree/rust-hir-full-decls.h: Likewise. + * hir/tree/rust-hir.cc: Handle AnonConst and ConstBlock. + * backend/rust-compile-block.cc: Likewise. + * backend/rust-compile-block.h: Likewise. + * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise. + * backend/rust-compile-expr.h: Likewise. + * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise. + * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Likewise. + * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise. + * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise. + * checks/errors/borrowck/rust-function-collector.h: Likewise. + * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit): Likewise. + * checks/errors/privacy/rust-privacy-reporter.h: Likewise. + * checks/errors/rust-const-checker.cc (ConstChecker::visit): Likewise. + * checks/errors/rust-const-checker.h: Likewise. + * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Likewise. + * checks/errors/rust-hir-pattern-analysis.h: Likewise. + * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Likewise. + * checks/errors/rust-unsafe-checker.h: Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + (translate_operand_out): Likewise. + (translate_operand_inout): Likewise. + (translate_operand_const): Likewise. + * hir/rust-ast-lower-expr.h: Likewise. + * hir/rust-hir-dump.cc (Dump::visit): Likewise. + * hir/rust-hir-dump.h: Likewise. + * hir/tree/rust-hir-expr-abstract.h: Likewise. + * hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise. + (AnonConst::operator=): Likewise. + (ConstBlock::ConstBlock): Likewise. + (ConstBlock::operator=): Likewise. + * hir/tree/rust-hir-visitor.h: + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. + (typecheck_inline_asm_operand): Likewise. + * typecheck/rust-hir-type-check-expr.h: Likewise. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * parse/rust-parse-impl.h (Parser::parse_const_block_expr): New function. + * parse/rust-parse.h: Declare it. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-expr.h: Declare AnonConst and ConstBlock and use them. + * ast/rust-ast-full-decls.h: Likewise. + * ast/rust-ast.cc: Add implementation for AnonConst and ConstBlock. + * ast/rust-ast.h: Likewise. + * ast/rust-ast-collector.cc (TokenCollector::visit): Likewise. + * ast/rust-ast-collector.h: Likewise. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * ast/rust-ast-visitor.h: Likewise. + * expand/rust-derive.h: Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. + * hir/rust-ast-lower-base.h: Likewise. + * hir/rust-ast-lower-expr.cc (translate_operand_const): Likewise. + * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise. + * resolve/rust-ast-resolve-base.h: Likewise. + * resolve/rust-ast-resolve-expr.h: Likewise. + * resolve/rust-ast-resolve-expr.cc: Likewise. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized): dont emit error here + * typecheck/rust-unify.cc (UnifyRules::resolve_subtype): new helper to handle emit error + (UnifyRules::expect_adt): call resolve_subtype + (UnifyRules::expect_reference): likewise + (UnifyRules::expect_pointer): likewise + (UnifyRules::expect_array): likewise + (UnifyRules::expect_slice): likewise + (UnifyRules::expect_fndef): likewise + (UnifyRules::expect_fnptr): likewise + (UnifyRules::expect_tuple): likewise + (UnifyRules::expect_closure): likewise + (UnifyRules::expect_opaque): likeiwse + * typecheck/rust-unify.h: add new helper to header + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-default-resolver.cc + (DefaultResolver::visit_if_let_patterns): New function + definition. + (DefaultResolver::visit): New IfLetExpr visitor definition. + * resolve/rust-default-resolver.h + (DefaultResolver::visit_if_let_patterns): New function + declaration. + (DefaultResolver::visit): New IfLetExpr visitor declaration. + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove + IfLetExpr visitor definition. + (Late::visit_if_let_patterns): New function definition. + * resolve/rust-late-name-resolver-2.0.h (Late::visit): Remove + IfLetExpr visitor declaration. + (Late::visit_if_let_patterns): New function declaration. + * resolve/rust-name-resolution-context.h (BindingSource::IfLet): + New enumerator. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): we need to resolve the + underlying type + * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): just clone + * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): + ensure we monomphize to get the underlying + * typecheck/rust-tyty.cc (BaseType::destructure): handle opaque types + (OpaqueType::resolve): this is much simpler now + (OpaqueType::handle_substitions): no longer needed + * typecheck/rust-tyty.h: update header + * typecheck/rust-unify.cc (UnifyRules::expect_opaque): unify rules for opaque + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): use get_name + * typecheck/rust-tyty.cc (TupleType::get_name): likewise + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::check_base_type_privacy): + no need for unreachable here + * typecheck/rust-unify.cc (UnifyRules::commit): dont clone infer vars + (UnifyRules::expect_inference_variable): likewise + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check.h: new function + * typecheck/rust-typecheck-context.cc (TypeCheckContext::compute_inference_variables): + call the new helper + (TypeCheckContext::compute_infer_var): refactored code + +2025-08-05 Tom Schollenberger <tss2344@g.rit.edu> + + * resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): rust_assert to if + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_expr_stmt): Avoid + reference binding and remove std::move in return statements. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-visitor.cc + (DefaultASTVisitor::visit): Only visit the path of an instance + of Visibility if the instance has a path. + * ast/rust-ast.h + (SimplePath::SimplePath): Make sure constructors are explicit. + * resolve/rust-early-name-resolver-2.0.cc + (Early::visit_attributes): Pass entire paths to + NameResolutionContext::resolve_path. + (Early::visit): Likewise and avoid copying a path. + * resolve/rust-forever-stack.hxx + (ForeverStack::resolve_path): Assert that at least one path + segment has been passed in. + +2025-08-05 Marc Poulhiès <dkm@kataplop.net> + + * rust-attribs.cc (handle_hot_attribute): Remove clang-format comment. + +2025-08-05 Marc Poulhiès <dkm@kataplop.net> + + * ast/rust-ast-builder-type.cc (ASTTypeBuilder::visit): Reindent. + * ast/rust-ast-builder.cc (Builder::new_generic_args): Likewise. + * ast/rust-ast-collector.cc (TokenCollector::visit): Likewise. + * ast/rust-ast-dump.h (debug): Likewise. + * ast/rust-ast-formatting.h (indent_spaces): Likewise. + (get_string_in_delims): Likewise. + (get_mode_dump_desc): Likewise. + (append_attributes): Likewise. + (unquote_string): Likewise. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * ast/rust-ast.cc (Attribute::get_traits_to_derive): Likewise. + (UseTreeGlob::as_string): Likewise. + (UseTreeList::as_string): Likewise. + (AttributeParser::parse_path_meta_item): Likewise. + (FormatArgs::set_outer_attrs): Likewise. + * ast/rust-ast.h (operator<<): Likewise. + * ast/rust-cond-compilation.h: Likewise. + * ast/rust-desugar-apit.cc: Likewise. + * ast/rust-fmt.h (collect_pieces): Likewise. + (clone_pieces): Likewise. + * ast/rust-pattern.h (tokenid_to_rangekind): Likewise. + * backend/rust-compile-context.cc (Context::type_hasher): Likewise. + * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise. + * backend/rust-compile-intrinsic.cc (get_identifier): Likewise. + (offset_handler): Likewise. + (sizeof_handler): Likewise. + (transmute_handler): Likewise. + (rotate_handler): Likewise. + (wrapping_op_handler_inner): Likewise. + (op_with_overflow_inner): Likewise. + (uninit_handler): Likewise. + (move_val_init_handler): Likewise. + (assume_handler): Likewise. + (discriminant_value_handler): Likewise. + (variant_count_handler): Likewise. + (prefetch_data_handler): Likewise. + (atomic_store_handler_inner): Likewise. + (atomic_load_handler_inner): Likewise. + (unchecked_op_inner): Likewise. + (copy_handler_inner): Likewise. + (expect_handler_inner): Likewise. + (try_handler_inner): Likewise. + * backend/rust-compile-pattern.cc (compile_range_pattern_bound): Likewise. + (CompilePatternCheckExpr::visit): Likewise. + (CompilePatternBindings::visit): Likewise. + (CompilePatternLet::visit): Likewise. + * backend/rust-compile-var-decl.h: Likewise. + * backend/rust-constexpr.cc (verify_constant): Likewise. + (find_array_ctor_elt): Likewise. + (array_index_cmp): Likewise. + (potential_constant_expression_1): Likewise. + (unshare_constructor): Likewise. + (maybe_save_constexpr_fundef): Likewise. + (returns): Likewise. + (breaks): Likewise. + (continues): Likewise. + (switches): Likewise. + (constant_value_1): Likewise. + (decl_constant_value): Likewise. + (non_const_var_error): Likewise. + (eval_constant_expression): Likewise. + (constexpr_fn_retval): Likewise. + (eval_store_expression): Likewise. + (eval_call_expression): Likewise. + (eval_binary_expression): Likewise. + (get_function_named_in_call): Likewise. + (eval_statement_list): Likewise. + (extract_string_elt): Likewise. + (eval_conditional_expression): Likewise. + (eval_bit_field_ref): Likewise. + (eval_loop_expr): Likewise. + (eval_switch_expr): Likewise. + (eval_unary_expression): Likewise. + (get_or_insert_ctor_field): Likewise. + (eval_and_check_array_index): Likewise. + * backend/rust-constexpr.h (maybe_save_constexpr_fundef): Likewise. + * backend/rust-mangle-v0.cc (v0_path): Likewise. + (v0_complex_type_prefix): Likewise. + * backend/rust-mangle.h (legacy_mangle_item): Likewise. + (v0_mangle_item): Likewise. + * backend/rust-tree.cc (convert_to_void): Likewise. + (find_parameter_packs_r): Likewise. + (rs_tree_equal): Likewise. + (publicly_uniquely_derived_p): Likewise. + (instantiation_dependent_expression_p): Likewise. + (type_has_nontrivial_copy_init): Likewise. + (is_normal_capture_proxy): Likewise. + (is_bitfield_expr_with_lowered_type): Likewise. + (undeduced_auto_decl): Likewise. + (require_deduced_type): Likewise. + (gt_pch_nx): Likewise. + (lvalue_kind): Likewise. + * backend/rust-tree.h (LANG_DECL_MIN_CHECK): Likewise. + (LANG_DECL_FN_CHECK): Likewise. + (LANG_DECL_NS_CHECK): Likewise. + (LANG_DECL_PARM_CHECK): Likewise. + (LANG_DECL_DECOMP_CHECK): Likewise. + (resort_type_member_vec): Likewise. + (convert_to_void): Likewise. + (mark_discarded_use): Likewise. + (mark_exp_read): Likewise. + (mark_use): Likewise. + (mark_rvalue_use): Likewise. + (mark_lvalue_use): Likewise. + (mark_lvalue_use_nonread): Likewise. + (convert_from_reference): Likewise. + (maybe_warn_nodiscard): Likewise. + (expr_loc_or_loc): Likewise. + (expr_loc_or_input_loc): Likewise. + (get_fndecl_from_callee): Likewise. + (pointer_offset_expression): Likewise. + (is_empty_class): Likewise. + (is_really_empty_class): Likewise. + (rs_type_quals): Likewise. + (init_modules): Likewise. + (lookup_add): Likewise. + (ovl_make): Likewise. + (struct c_fileinfo): Likewise. + (get_fileinfo): Likewise. + (cxx_make_type): Likewise. + (build_cplus_array_type): Likewise. + (comptypes): Likewise. + (rs_build_qualified_type_real): Likewise. + (vector_targets_convertible_p): Likewise. + (get_class_binding_direct): Likewise. + (lang_check_failed): Likewise. + (check_for_uninitialized_const_var): Likewise. + (cp_fold_maybe_rvalue): Likewise. + (fold_offsetof): Likewise. + (fold_non_dependent_expr): Likewise. + (in_immediate_context): Likewise. + (cxx_mark_addressable): Likewise. + (decl_constant_value): Likewise. + (is_class_type): Likewise. + (fold_builtin_is_pointer_inverconvertible_with_class): Likewise. + (c_common_type_for_mode): Likewise. + (next_common_initial_seqence): Likewise. + (fold_builtin_is_corresponding_member): Likewise. + (maybe_constant_value): Likewise. + (rs_walk_subtrees): Likewise. + (make_tree_vector): Likewise. + (release_tree_vector): Likewise. + (location_of): Likewise. + (maybe_constant_init): Likewise. + (explain_invalid_constexpr_fn): Likewise. + (literal_type_p): Likewise. + (maybe_constexpr_fn): Likewise. + (fold_non_dependent_init): Likewise. + * checks/errors/borrowck/polonius/rust-polonius.h (polonius_run): Likewise. + (FFIVector__new): Likewise. + (FFIVector__new_vec_pair): Likewise. + (FFIVector__new_vec_triple): Likewise. + (FFIVector__push): Likewise. + (FFIVector__push_vec_triple): Likewise. + * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc + (ExprStmtBuilder::visit): Likewise. + * checks/errors/borrowck/rust-bir-builder-pattern.cc + (PatternBindingBuilder::visit): Likewise. + * checks/errors/borrowck/rust-bir-dump.cc (Dump::visit): Likewise. + * checks/errors/borrowck/rust-bir-fact-collector.h (points): Likewise. + * checks/errors/borrowck/rust-bir-place.h: Likewise. + * checks/errors/borrowck/rust-bir-visitor.h: Likewise. + * checks/errors/privacy/rust-privacy-check.cc (saw_errors): Likewise. + * checks/errors/privacy/rust-privacy-ctx.h (rust_privacy_ctx_test): Likewise. + * checks/errors/privacy/rust-privacy-reporter.cc + (PrivacyReporter::check_for_privacy_violation): Likewise. + (PrivacyReporter::check_base_type_privacy): Likewise. + (PrivacyReporter::visit): Likewise. + * checks/errors/privacy/rust-reachability.cc (ReachabilityVisitor::visit): Likewise. + * checks/errors/privacy/rust-visibility-resolver.cc + (VisibilityResolver::resolve_visibility): Likewise. + * checks/errors/rust-hir-pattern-analysis.cc (Constructor::is_covered_by): Likewise. + (PlaceInfo::specialize): Likewise. + (WitnessPat::to_string): Likewise. + (WitnessMatrix::apply_constructor): Likewise. + (lower_pattern): Likewise. + (lower_tuple_pattern): Likewise. + (lower_struct_pattern): Likewise. + * checks/errors/rust-hir-pattern-analysis.h (check_match_usefulness): Likewise. + * expand/rust-cfg-strip.cc (CfgStrip::maybe_strip_generic_args): Likewise. + * expand/rust-derive-eq.cc (DeriveEq::visit_enum): Likewise. + * expand/rust-derive.cc: Likewise. + * expand/rust-expand-format-args.cc (expand_format_args): Likewise. + * expand/rust-expand-visitor.h (is_derive): Likewise. + (is_builtin): Likewise. + * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): Likewise. + * expand/rust-macro-builtins-asm.h (parse_asm): Likewise. + (check_identifier): Likewise. + (check_and_set): Likewise. + (parse_label): Likewise. + (parse_llvm_outputs): Likewise. + (parse_llvm_inputs): Likewise. + (parse_llvm_clobbers): Likewise. + (parse_llvm_options): Likewise. + * expand/rust-macro-builtins-helpers.h (make_macro_path_str): Likewise. + (make_token): Likewise. + (make_string): Likewise. + (macro_end_token): Likewise. + (parse_single_string_literal): Likewise. + (source_relative_path): Likewise. + (load_file_bytes): Likewise. + * expand/rust-macro-expand.cc (MacroExpander::match_fragment): Likewise. + (MacroExpander::match_matcher): Likewise. + (MacroExpander::match_n_matches): Likewise. + * expand/rust-macro-substitute-ctx.cc (SubstituteCtx::substitute_token): Likewise. + * expand/rust-proc-macro.h (load_macros): Likewise. + (generate_proc_macro_decls_symbol): Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_generic_args): Likewise. + (ASTLoweringBase::lower_range_pattern_bound): Likewise. + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise. + * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Likewise. + * hir/rust-ast-lower.h (struct_field_name_exists): Likewise. + (translate_visibility): Likewise. + * hir/rust-hir-dump.cc (Dump::visit): Likewise. + * hir/rust-hir-dump.h (debug): Likewise. + * hir/tree/rust-hir.cc (UseTreeGlob::as_string): Likewise. + (UseTreeList::as_string): Likewise. + * lex/rust-lex.cc (Lexer::parse_escape): Likewise. + (Lexer::parse_utf8_escape): Likewise. + * lex/rust-lex.h (rust_input_source_test): Likewise. + * lex/rust-token.cc (RS_TOKEN_KEYWORD_2015): Likewise. + * lex/rust-token.h (get_token_description): Likewise. + (token_id_to_str): Likewise. + (token_id_is_keyword): Likewise. + (token_id_keyword_string): Likewise. + (get_type_hint_string): Likewise. + (nfc_normalize_token_string): Likewise. + * metadata/rust-export-metadata.cc (PublicInterface::write_to_path): Likewise. + * metadata/rust-import-archive.cc: Likewise. + * metadata/rust-imports.h (add_search_path): Likewise. + * parse/rust-cfg-parser.h (parse_cfg_option): Likewise. + (rust_cfg_parser_test): Likewise. + * parse/rust-parse-impl.h (Parser::skip_generics_right_angle): Likewise. + (Parser::parse_attr_input): Likewise. + (Parser::parse_macro_match): Likewise. + (Parser::parse_visibility): Likewise. + (Parser::parse_module): Likewise. + (Parser::parse_use_tree): Likewise. + (Parser::parse_generic_param): Likewise. + (Parser::parse_struct): Likewise. + (Parser::parse_enum_item): Likewise. + (Parser::parse_inherent_impl_item): Likewise. + (Parser::parse_external_item): Likewise. + (Parser::parse_generic_arg): Likewise. + (Parser::parse_type_path_segment): Likewise. + (Parser::parse_expr_stmt): Likewise. + (Parser::parse_if_expr): Likewise. + (Parser::parse_if_let_expr): Likewise. + (Parser::parse_type): Likewise. + (Parser::parse_for_prefixed_type): Likewise. + (Parser::parse_slice_or_array_type): Likewise. + (Parser::parse_type_no_bounds): Likewise. + (Parser::parse_range_pattern_bound): Likewise. + (Parser::parse_pattern_no_alt): Likewise. + (Parser::parse_grouped_or_tuple_pattern): Likewise. + (Parser::parse_ident_leading_pattern): Likewise. + (Parser::parse_tuple_struct_items): Likewise. + (Parser::parse_stmt_or_expr): Likewise. + (Parser::parse_struct_expr_field): Likewise. + (Parser::null_denotation): Likewise. + (Parser::left_denotation): Likewise. + (Parser::parse_closure_expr_pratt): Likewise. + * parse/rust-parse.cc (peculiar_fragment_match_compatible): Likewise. + (is_match_compatible): Likewise. + * parse/rust-parse.h (extract_module_path): Likewise. + (is_match_compatible): Likewise. + * resolve/rust-ast-resolve-expr.cc (translate_operand): Likewise. + * resolve/rust-ast-resolve-item.cc (flatten_glob): Likewise. + (flatten_rebind): Likewise. + (flatten_list): Likewise. + (flatten): Likewise. + * resolve/rust-ast-resolve-item.h (rust_simple_path_resolve_test): Likewise. + * resolve/rust-ast-resolve-pattern.cc (PatternDeclaration::visit): Likewise. + (resolve_range_pattern_bound): Likewise. + * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): Likewise. + (ResolveTypeToCanonicalPath::visit): Likewise. + * resolve/rust-ast-resolve.cc (saw_errors): Likewise. + * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import): Likewise. + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise. + * resolve/rust-toplevel-name-resolver-2.0.cc (flatten_glob): Likewise. + * rust-backend.h (init): Likewise. + (debug): Likewise. + (get_identifier_node): Likewise. + (wchar_type): Likewise. + (get_pointer_size): Likewise. + (raw_str_type): Likewise. + (integer_type): Likewise. + (float_type): Likewise. + (pointer_type): Likewise. + (reference_type): Likewise. + (immutable_type): Likewise. + (function_type): Likewise. + (function_type_variadic): Likewise. + (function_ptr_type): Likewise. + (struct_type): Likewise. + (union_type): Likewise. + (array_type): Likewise. + (named_type): Likewise. + (type_field_offset): Likewise. + (var_expression): Likewise. + (float_constant_expression): Likewise. + (string_constant_expression): Likewise. + (char_constant_expression): Likewise. + (wchar_constant_expression): Likewise. + (boolean_constant_expression): Likewise. + (convert_expression): Likewise. + (struct_field_expression): Likewise. + (compound_expression): Likewise. + (conditional_expression): Likewise. + (negation_expression): Likewise. + (arithmetic_or_logical_expression): Likewise. + (arithmetic_or_logical_expression_checked): Likewise. + (comparison_expression): Likewise. + (lazy_boolean_expression): Likewise. + (constructor_expression): Likewise. + (array_constructor_expression): Likewise. + (array_initializer): Likewise. + (array_index_expression): Likewise. + (call_expression): Likewise. + (init_statement): Likewise. + (assignment_statement): Likewise. + (return_statement): Likewise. + (if_statement): Likewise. + (loop_expression): Likewise. + (exit_expression): Likewise. + (statement_list): Likewise. + (exception_handler_statement): Likewise. + (block): Likewise. + (block_add_statements): Likewise. + (global_variable): Likewise. + (global_variable_set_init): Likewise. + (local_variable): Likewise. + (parameter_variable): Likewise. + (static_chain_variable): Likewise. + (temporary_variable): Likewise. + (label): Likewise. + (function): Likewise. + (function_defer_statement): Likewise. + (function_set_parameters): Likewise. + (write_global_definitions): Likewise. + (fill_in_fields): Likewise. + * rust-diagnostics.cc (expand_format): Likewise. + (expand_message): Likewise. + (va_constructor): Likewise. + * rust-diagnostics.h (RUST_ATTRIBUTE_GCC_DIAG): Likewise. + (rust_open_quote): Likewise. + (rust_close_quote): Likewise. + (rust_debug_loc): Likewise. + * rust-gcc.cc (non_zero_size_type): Likewise. + * rust-object-export.h (rust_field_alignment): Likewise. + (rust_read_export_data): Likewise. + (rust_write_export_data): Likewise. + * rust-session-manager.cc (saw_errors): Likewise. + (rust_get_linemap): Likewise. + (validate_crate_name): Likewise. + (Session::load_extern_crate): Likewise. + * rust-session-manager.h (rust_crate_name_validation_test): Likewise. + * rust-system.h (rust_preserve_from_gc): Likewise. + (rust_localize_identifier): Likewise. + * rust-target.h (rust_add_target_info): Likewise. + * typecheck/rust-autoderef.cc: + * typecheck/rust-casts.cc (TypeCastRules::cast_rules): Likewise. + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Likewise. + (TypeCoercionRules::coerce_unsafe_ptr): Likewise. + (TypeCoercionRules::coerce_borrowed_pointer): Likewise. + * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): Likewise. + (TraitItemReference::is_object_safe): Likewise. + * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): Likewise. + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. + (typecheck_inline_asm_operand): Likewise. + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): Likewise. + (TypeCheckImplItemWithTrait::visit): Likewise. + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Likewise. + * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::visit): Likewise. + * typecheck/rust-hir-type-check-type.cc + (TypeResolveGenericParam::apply_trait_bounds): Likewise. + (ResolveWhereClauseItem::visit): Likewise. + * typecheck/rust-hir-type-check.cc (saw_errors): Likewise. + (TraitItemReference::get_type_from_fn): Likewise. + * typecheck/rust-type-util.h (query_type): Likewise. + (types_compatable): Likewise. + (unify_site): Likewise. + (unify_site_and): Likewise. + (coercion_site): Likewise. + (try_coercion): Likewise. + (cast_site): Likewise. + * typecheck/rust-tyty-bounds.cc: + * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): Likewise. + * typecheck/rust-tyty-cmp.h: + * typecheck/rust-tyty-variance-analysis.h (query_field_regions): Likewise. + * typecheck/rust-tyty.cc (BaseType::is_unit): Likewise. + (BaseType::has_substitutions_defined): Likewise. + (BaseType::needs_generic_substitutions): Likewise. + (BaseType::get_subst_argument_mappings): Likewise. + (InferType::default_type): Likewise. + (InferType::apply_primitive_type_hint): Likewise. + * typecheck/rust-tyty.h (is_primitive_type_kind): Likewise. + * typecheck/rust-unify.cc (UnifyRules::expect_inference_variable): Likewise. + (UnifyRules::expect_adt): Likewise. + (UnifyRules::expect_str): Likewise. + (UnifyRules::expect_reference): Likewise. + (UnifyRules::expect_pointer): Likewise. + (UnifyRules::expect_param): Likewise. + (UnifyRules::expect_array): Likewise. + (UnifyRules::expect_slice): Likewise. + (UnifyRules::expect_fndef): Likewise. + (UnifyRules::expect_fnptr): Likewise. + (UnifyRules::expect_tuple): Likewise. + (UnifyRules::expect_bool): Likewise. + (UnifyRules::expect_char): Likewise. + (UnifyRules::expect_int): Likewise. + (UnifyRules::expect_uint): Likewise. + (UnifyRules::expect_float): Likewise. + (UnifyRules::expect_isize): Likewise. + (UnifyRules::expect_usize): Likewise. + (UnifyRules::expect_never): Likewise. + (UnifyRules::expect_placeholder): Likewise. + (UnifyRules::expect_projection): Likewise. + (UnifyRules::expect_dyn): Likewise. + (UnifyRules::expect_closure): Likewise. + (UnifyRules::expect_opaque): Likewise. + * util/rust-abi.h (get_abi_from_string): Likewise. + (get_string_from_abi): Likewise. + * util/rust-attributes.cc (check_doc_attribute): Likewise. + * util/rust-base62.h (base62_integer): Likewise. + * util/rust-dir-owner.h (get_file_subdir): Likewise. + * util/rust-edition.h (get_rust_edition): Likewise. + * util/rust-punycode.h (encode_punycode): Likewise. + (rust_punycode_encode_test): Likewise. + * util/rust-token-converter.cc (convert): Likewise. + (from_tokenstream): Likewise. + * util/rust-token-converter.h (convert): Likewise. + (convert_literal): Likewise. + * util/rust-unicode.h (is_alphabetic): Likewise. + (is_ascii_only): Likewise. + (is_numeric): Likewise. + (is_nfc_qc_no): Likewise. + (is_nfc_qc_maybe): Likewise. + (nfc_quick_check): Likewise. + (rust_nfc_qc_test): Likewise. + (rust_utf8_normalize_test): Likewise. + (rust_utf8_property_test): Likewise. + * util/rust-unwrap-segment.h (unwrap_segment_node_id): Likewise. + +2025-08-05 Marc Poulhiès <dkm@kataplop.net> + + * Make-lang.in (GRS_OBJS): Remove rust-macro.o. + * ast/rust-macro.cc: Removed. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h + (Parser::parse_attr_input): Handle more delimeter tokens and the + END_OF_FILE token. + (Parser::skip_after_end_attribute): Handle the END_OF_FILE + token. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * hir/rust-ast-lower-item.cc + (ASTLoweringItem::visit): Keep going after a duplicate field is + found. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/borrowck/rust-bir-builder-internal.h: Include + "rust-immutable-name-resolution-context.h" and "options.h". + (AbstractBuilder::resolve_label): Use the 2.0 name resolver when + it's enabled. + (AbstractBuilder::resolve_variable): Likewise. + (AbstractBuilder::resolve_variable_or_fn): Likewise. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * expand/rust-derive-default.cc (DeriveDefault::visit_struct): use builder + (DeriveDefault::visit_tuple): likewise + * expand/rust-derive-eq.cc (DeriveEq::visit_tuple): likewise + (DeriveEq::visit_struct): likewise + (DeriveEq::visit_enum): likewise + (DeriveEq::visit_union): likewise + +2025-08-05 Marc Poulhiès <dkm@kataplop.net> + + PR rust/120018 + * rust-attribs.cc (handle_noreturn_attribute): Reindent declaration. + (handle_leaf_attribute): Likewise. + (handle_const_attribute): Likewise. + (handle_malloc_attribute): Likewise. + (handle_pure_attribute): Likewise. + (handle_novops_attribute): Likewise. + (handle_nonnull_attribute): Likewise. + (handle_nothrow_attribute): Likewise. + (handle_type_generic_attribute): Likewise. + (handle_transaction_pure_attribute): Likewise. + (handle_returns_twice_attribute): Likewise. + (handle_fnspec_attribute): Likewise. + (handle_omp_declare_simd_attribute): Likewise. + (handle_cold_attribute): New. + (handle_hot_attribute): New. + (attribute_spec::exclusions attr_cold_hot_exclusions): New. + (grs_langhook_common_attributes): Make it static. + (grs_langhook_common_attribute_table): New. + (grs_langhook_gnu_attributes): New. + (grs_langhook_gnu_attribute_table): New. + (handle_malloc_attribute): Make it static. + (handle_fnspec_attribute): Likewise. + (handle_pure_attribute): Replace gcc_assert by explicit warning. + (handle_novops_attribute): Likewise. + (handle_nothrow_attribute): Likewise. + (handle_returns_twice_attribute): Likewise. + (handle_omp_declare_simd_attribute): Likewise and make it static. + * rust-lang.cc (grs_langhook_gnu_attribute_table): New. + (grs_langhook_common_attribute_table): Adjust type to new hook. + (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Remove. + (LANG_HOOKS_ATTRIBUTE_TABLE): New. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-path.cc + (TypePath::make_debug_string): Add definition. + * ast/rust-path.h + (TypePath::make_debug_string): Add declaration. + * resolve/rust-default-resolver.cc + (DefaultResolver::visit): Adjust InherentImpl and TraitImpl + visitors to better handle associated item scope. + * resolve/rust-default-resolver.h + (DefaultResolver::maybe_insert_big_self): Add. + * resolve/rust-late-name-resolver-2.0.cc + (Late::visit): Adjust type path resolution errors. + * resolve/rust-rib.h + (Rib::Kind): Add Generics kind. + * resolve/rust-toplevel-name-resolver-2.0.cc + (TopLevel::visit): Remove InherentImpl and TraitImpl visitor + overrides. + (TopLevel::maybe_insert_big_self): Add override in order to add + a definition of 'Self'. + * resolve/rust-toplevel-name-resolver-2.0.h + (TopLevel::visit): Remove InherentImpl and TraitImpl visitor + overrides. + (TopLevel::maybe_insert_big_self): Add override. + +2025-08-05 0xn4utilus <gyanendrabanjare8@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Implement for InlineAsm. + * ast/rust-ast-full-decls.h (enum class): Move InlineAsmOption enum inside InlineAsm. + * ast/rust-expr.h (enum class): Likewise. + (class InlineAsm): Likewise. + * expand/rust-macro-builtins-asm.cc (check_and_set): Likewise. + (parse_options): Likewise. + * expand/rust-macro-builtins-asm.h (check_and_set): Likewise. + * hir/tree/rust-hir-expr.cc (InlineAsm::InlineAsm): Likewise. + * hir/tree/rust-hir-expr.h: Likewise. + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. + +2025-08-05 Tom Schollenberger <tss2344@g.rit.edu> + + * backend/rust-constexpr.cc (eval_constant_expression): Check if t is a NULL_TREE + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * ast/rust-desugar-apit.cc: track if this is a impl-trait generic + * ast/rust-item.h (class TypeParam): add field to track if from impl trait + * hir/rust-ast-lower-type.cc (ASTLowerGenericParam::visit): likewise + * hir/tree/rust-hir-item.cc (TypeParam::TypeParam): upate hir as well + (TypeParam::operator=): likewise + * hir/tree/rust-hir-item.h (class TypeParam): likewise + * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): add error + * typecheck/rust-tyty-subst.h: add const getter for the associated TypeParm + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-visitor.cc + (DefaultASTVisitor::visit): Make call to EnumItem visitor from + EnumItem derived class visitors non-virtual. + * ast/rust-collect-lang-items.cc + (CollectLangItems::visit): Handle visitation of classes derived + from EnumItem. + * ast/rust-collect-lang-items.h + (CollectLangItems::visit): Likewise. + * resolve/rust-toplevel-name-resolver-2.0.cc + (TopLevel::visit): Call DefaultResolver::visit on EnumItem + instances. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * backend/rust-compile-pattern.cc + (CompilePatternCheckExpr::visit): Fix GENERIC generation in + light of enum layout changes since this code was written. + (CompilePatternBindings::handle_struct_pattern_ident_pat): + Delegate handling of child patterns to another + CompilePatternBindings::Compile call. + (CompilePatternBindings::make_struct_access): Make field name + parameter const qualified. + * backend/rust-compile-pattern.h + (CompilePatternBindings::make_struct_access): Likewise. + +2025-08-05 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-ast-resolve-item.cc + (ResolveItem::visit): Use the return values of + CanonicalPath::inherent_impl_seg and + CanonicalPath::trait_impl_projection_seg more directly. + * util/rust-canonical-path.h + (CanonicalPath::trait_impl_projection_seg): Append "<impl " + instead of "<" to the beginning of the returned path segment. + (CanonicalPath::inherent_impl_seg): Likewise. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * Make-lang.in: new desugar file + * ast/rust-ast.cc (ImplTraitTypeOneBound::as_string): its a unique_ptr now + (FormatArgs::set_outer_attrs): reformat + * ast/rust-path.h: remove has_generic_args assertion (can be empty because of desugar) + * ast/rust-type.h (class ImplTraitTypeOneBound): add copy ctor and use unique_ptr + * hir/rust-ast-lower-type.cc (ASTLoweringType::visit): update to use unique_ptr + * parse/rust-parse-impl.h (Parser::parse_type): reuse the existing unique_ptr instead + (Parser::parse_type_no_bounds): likewise + (Parser::parse_pattern): likewise + * resolve/rust-ast-resolve-type.cc (ResolveType::visit): its a unique_ptr now + * rust-session-manager.cc (Session::compile_crate): call desugar + * ast/rust-desugar-apit.cc: New file. + * ast/rust-desugar-apit.h: New file. + +2025-08-05 Philip Herron <herron.philip@googlemail.com> + + * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): allow impl type + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): likewise + * hir/rust-ast-lower-type.cc (ASTLoweringType::ASTLoweringType): new flag for impl trait + (ASTLoweringType::translate): pass flag + (ASTLoweringType::visit): track impl trait tag + (ASTLoweringType::emit_impl_trait_error): new diagnostic + * hir/rust-ast-lower-type.h: add new field + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-derive-partial-eq.cc (DerivePartialEq::match_enum_tuple): Remove debug call. + (DerivePartialEq::match_enum_struct): Add proper implementation. + (DerivePartialEq::visit_enum): Call it. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-builder.cc (Builder::struct_pattern_ident_pattern): New. + * ast/rust-ast-builder.h: New declaration. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * backend/rust-compile-pattern.cc (CompilePatternBindings::make_struct_access): + New function. + (CompilePatternBindings::visit): Properly implement patterns mentioned above + and call make_struct_accesss. + * backend/rust-compile-pattern.h: New declaration. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * backend/rust-compile-pattern.h: Split struct pattern compilation into three functions. + * backend/rust-compile-pattern.cc: Implement them. + +2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::Late): False initialize the + funny_error field. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * resolve/rust-ice-finalizer.cc: Update usage of "diagnostic_info" + to explicitly refer to "diagnostics::diagnostic_info". + * resolve/rust-ice-finalizer.h: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * backend/rust-tree.cc: Update for diagnostic_t becoming + enum class diagnostics::kind. + * backend/rust-tree.h: Likewise. + * resolve/rust-ast-resolve-expr.cc: Likewise. + * resolve/rust-ice-finalizer.cc: Likewise. + * resolve/rust-ice-finalizer.h: Likewise. + * resolve/rust-late-name-resolver-2.0.cc: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * resolve/rust-ast-resolve-expr.cc: Update for diagnostic_text_finalizer + becoming diagnostics::text_finalizer. + * resolve/rust-late-name-resolver-2.0.cc: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * resolve/rust-ice-finalizer.cc: Update for move of diagnostics + output formats into namespace "diagnostics" as "sinks". + * resolve/rust-ice-finalizer.h: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * rust-diagnostics.cc: Update #include for move of + "diagnostic-metadata.h" to "diagnostics/metadata.h", and update + for move of diagnostic_metadata to diagnostics::metadata. + +2025-06-26 Martin Jambor <mjambor@suse.cz> + + * checks/errors/borrowck/rust-borrow-checker-diagnostics.cc + (BorrowCheckerDiagnostics::get_loan): Type cast loan to uint32_t. + +2025-04-28 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/borrowck/rust-bir-place.h + (IndexVec::size_type): Add. + (IndexVec::MAX_INDEX): Add. + (IndexVec::size): Change the return type to the type of the + internal value used by the index type. + (PlaceDB::lookup_or_add_variable): Use the return value from the + PlaceDB::add_place call. + * checks/errors/borrowck/rust-bir.h + (struct BasicBlockId): Move this definition before the + definition of the struct Function. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit visibility. + +2025-04-28 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-visitor.cc + (DefaultASTVisitor::visit): Visit the loop labels of + WhileLetLoopExpr instances before visiting their scrutinee + expressions. + * resolve/rust-early-name-resolver-2.0.cc + (Early::resolve_glob_import): Pass the glob import's path + directly to NameResolutionContext::resolve_path. + * resolve/rust-toplevel-name-resolver-2.0.cc + (TopLevel::visit): Remove unnecessary call to + Identifier::as_string. + (flatten_glob): Improve handling of cases where a glob use tree + has no path. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-derive-clone.cc (DeriveClone::clone_enum_struct): Clone + path to avoid using the same nodeid. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit_function_params): + Add specialized function to visit function parameters. + (DefaultASTVisitor::visit): Remove parameter visit and call specialized + function instead. + * ast/rust-ast-visitor.h: Add function prototye. + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove + function. + (Late::visit_function_params): Override specialized visit function. + * resolve/rust-late-name-resolver-2.0.h: Add overriden function + prototype. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-name-resolution-context.h: Use BindingLayer instead. + * resolve/rust-name-resolution-context.cc (BindingLayer::BindingLayer): + Add new constructor for binding layer. + (BindingLayer::bind_test): Add a function to test a binding constraint. + (BindingLayer::push): Push a new binding group. + (BindingLayer::and_binded): Add function to test and-binding + constraint. + (BindingLayer::or_binded): Add function to test or-binding constraints. + (BindingLayer::insert_ident): Insert a new identifier in the current + binding group. + (BindingLayer::merge): Merge current binding group with it's parent. + (BindingLayer::get_source): Get the source of the current binding + group. + * resolve/rust-late-name-resolver-2.0.cc: Use stacked context for + binding group. + * util/rust-stacked-contexts.h: Add mutable peek function. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add binding + creation in visitor. + * resolve/rust-late-name-resolver-2.0.h: Add function prototypes. + * resolve/rust-name-resolution-context.h: Add binding context. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-name-resolution-context.h (struct Binding): Add Binding + struct to differentiate Or and Product bindings in patterns. + (enum class): Add Binding kind. + (class BindingContext): Add binding context with Binding stack. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.h: Add hash function. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.h: Add equality operator. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add visit + function for TypeParam. + * resolve/rust-default-resolver.h: Add function prototype. + * resolve/rust-forever-stack.h: Add function to check for forward + declaration ban. + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Check forward + declarations. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Remove error kind + and change function call. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Change call name. + * ast/rust-path.cc (ConstGenericParam::as_string): Likewise. + * ast/rust-path.h: Remove error kind. + * hir/rust-ast-lower-type.cc (ASTLowerGenericParam::visit): Change call + name. + * parse/rust-parse-impl.h (Parser::parse_generic_param): Use optional + on parsing failure. + (Parser::parse_generic_arg): Likewise. + (Parser::parse_path_generic_args): Likewise. + * parse/rust-parse.h: Likewise. + * resolve/rust-ast-resolve-type.h: Change call name. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Change error + message. + +2025-04-28 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-early-name-resolver-2.0.cc + (Early::build_import_mapping): Avoid outputting an "unresolved + import" error if other errors are outputted during resolution. + * resolve/rust-early-name-resolver-2.0.h + (Early::resolve_path_in_all_ns): Collect path resolution errors + while avoiding duplicate errors for resolutions in each + namespace. + * resolve/rust-forever-stack.h + (ForeverStack::resolve_path): Add parameter for collecting + errors. + (ForeverStack::find_starting_point): Likewise. + (ForeverStack::resolve_segments): Likewise. + * resolve/rust-forever-stack.hxx + (check_leading_kw_at_start): Likewise. + (ForeverStack::find_starting_point): Likewise. + (ForeverStack::resolve_segments): Likewise. + (ForeverStack::resolve_path): Likewise. + * resolve/rust-name-resolution-context.h + (NameResolutionContext::resolve_path): Add optional parameter + for collecting errors. + +2025-04-28 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::array_copied_expr): prealloc the vector + +2025-04-28 Philip Herron <herron.philip@googlemail.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): add guard + * expand/rust-expand-visitor.cc (ExpandVisitor::visit): add guard + +2025-04-28 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-ast-resolve-path.cc + (ResolvePath::resolve_path): Adjust error messages. + * resolve/rust-ast-resolve-type.cc + (ResolveRelativeTypePath::go): Likewise. + * resolve/rust-forever-stack.hxx + (check_leading_kw_at_start): Likewise. + +2025-04-28 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): fix bad assertion + +2025-04-28 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-forever-stack.hxx + (ForeverStack::resolve_path): Pass instance of Node to lambda by + reference instead of by value. + +2025-04-28 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-struct-field.h: keep reference to parent expression + * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::TypeCheckStructExpr): + update ctor + (TypeCheckStructExpr::resolve): remove bad rust_fatal_errors + (TypeCheckStructExpr::visit): cleanup errors + +2025-04-28 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-late-name-resolver-2.0.cc + (Late::visit): Handle StructPatternFieldIdent. + * resolve/rust-late-name-resolver-2.0.h + (Late::visit): Likewise. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Dump llvm inline + asm tokens. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Remove unreachable + code. + * ast/rust-expr.h (struct LlvmOperand): Add LlvmOperand struct to + represent input and outputs. + (class LlvmInlineAsm): Add input, output and clobber operands. + (struct TupleTemplateStr): Add locus getter. + * backend/rust-compile-block.h: Add visit for LlvmInlineAsm. + * backend/rust-compile-expr.cc (CompileExpr::visit): Add llvm inline + asm stmt compilation. + * backend/rust-compile-expr.h: Add function prototype. + * backend/rust-compile-asm.h (class CompileLlvmAsm): Add llvm asm hir + not to gimple. + * backend/rust-compile-asm.cc (CompileLlvmAsm::CompileLlvmAsm): Add + constructor. + (CompileLlvmAsm::construct_operands): Add function to construct operand + tree. + (CompileLlvmAsm::construct_clobbers): Add function to construct clobber + tree. + (CompileLlvmAsm::tree_codegen_asm): Generate the whole tree for a given + llvm inline assembly node. + * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): + Add visit function. + * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Add function + prototype. + * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Add visit + function. + * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise. + * checks/errors/borrowck/rust-function-collector.h: Likewise. + * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit): + Likewise. + * checks/errors/privacy/rust-privacy-reporter.h: Add visit function + prototype. + * checks/errors/rust-const-checker.cc (ConstChecker::visit): Add visit + function. + * checks/errors/rust-const-checker.h: Add visit function prototype. + * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): + Add visit function. + * checks/errors/rust-hir-pattern-analysis.h: Add visit function + prototype. + * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Add + visit function. + * checks/errors/rust-unsafe-checker.h: Add function prototype. + * expand/rust-macro-builtins-asm.cc (parse_llvm_templates): Parse + templates. + (parse_llvm_arguments): Add function to parse non template tokens. + (parse_llvm_operands): Add function to parse operands, either input or + output. + (parse_llvm_outputs): Add function to parse and collect llvm asm + outputs. + (parse_llvm_inputs): Likewise with inputs. + (parse_llvm_clobbers): Add function to parse llvm asm clobbers. + (parse_llvm_options): Add function to parse llvm asm options. + (parse_llvm_asm): Add function to parse llvm asm. + * expand/rust-macro-builtins-asm.h (class LlvmAsmContext): Add context + for llvm asm parser. + (parse_llvm_outputs): Add function prototype. + (parse_llvm_inputs): Likewise. + (parse_llvm_clobbers): Likewise. + (parse_llvm_options): Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Lower AST llvm + asm node to HIR. + * hir/rust-ast-lower-expr.h: Add function prototype. + * hir/rust-hir-dump.cc (Dump::visit): Add visit function. + * hir/rust-hir-dump.h: Add function prototype. + * hir/tree/rust-hir-expr-abstract.h: Add HIR llvm asm node kind. + * hir/tree/rust-hir-expr.h (struct LlvmOperand): Add LlvmOperand type + to represent input and outputs. + (class LlvmInlineAsm): Add LlvmInlineAsm hir node. + * hir/tree/rust-hir-full-decls.h (class LlvmInlineAsm): Add + LlvmInlineAsm hir node forward declaration. + * hir/tree/rust-hir-visitor.h: Add visit functions for LlvmInlineAsm + hir node. + * hir/tree/rust-hir.cc (LlvmInlineAsm::accept_vis): Add hir node + visitor related functions. + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): + Type check input and output operands. + * typecheck/rust-hir-type-check-expr.h: Add function prototype. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit input and + output operand expressions. + * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Resolve input + and output expressions. + * resolve/rust-ast-resolve-expr.h: Add function prototypes. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Make visitor + unreachable. + * ast/rust-ast-collector.h: Add visit for LlvmInlineAsmNode. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add visit + function for the default ast visitor. + * ast/rust-ast-visitor.h: Add function prototype. + * ast/rust-ast.cc (LlvmInlineAsm::accept_vis): Add accept_vis to + LlvmInlineAsm node. + * ast/rust-ast.h: Add LlvmInlineAsm node kind. + * ast/rust-expr.h (class LlvmInlineAsm): Add LlvmInlineAsm node. + * expand/rust-derive.h: Add visit function for LlvmInlineAsm node. + * expand/rust-macro-builtins-asm.cc (MacroBuiltin::llvm_asm_handler): + Add handler for llvm inline assembly nodes. + (parse_llvm_asm): Add function to parse llvm assembly nodes. + * expand/rust-macro-builtins-asm.h (parse_llvm_asm): Add function + prototypes. + * expand/rust-macro-builtins.cc (inline_llvm_asm_maker): Add macro + transcriber. + * expand/rust-macro-builtins.h: Add transcriber function prototype. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Add visit + function for LlvmInlineAsm node. + * hir/rust-ast-lower-base.h: Add visit function prototype. + * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Add visit + function for LlvmInlineAsm node. + * resolve/rust-ast-resolve-base.h: Add visit function prototype. + +2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-asm.cc (parse_asm_arg): Emit error + message. + +2025-04-28 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): add diagnostic + * typecheck/rust-tyty.cc (BaseType::contains_infer): new helper to grab first infer var + * typecheck/rust-tyty.h: prototype + +2025-04-28 Philip Herron <herron.philip@googlemail.com> + + * rust-gcc.cc (arithmetic_or_logical_expression): Ensure this is an integer + +2025-04-28 Philip Herron <herron.philip@googlemail.com> + + * hir/rust-hir-dump.cc (Dump::visit): add guard for optional label + +2025-04-28 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-tyty.h: Remove extra redundant comment. + * typecheck/rust-hir-type-check-base.cc: Update comment on repr + handling. + +2025-04-28 Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-base.cc: Set enum representing + type properly if repr is an integer type. + * typecheck/rust-hir-type-check-item.cc: Update comments. + +2025-04-28 Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-tyty.h: Add new `ReprKind` enum to + `ReprOptions`. + * typecheck/rust-hir-type-check-base.cc: Handle setting of + `repr_kind`. + * typecheck/rust-hir-type-check-item.cc: New check for + zero-variant enums. + +2025-04-28 Philip Herron <herron.philip@googlemail.com> + + * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): add null check + * hir/tree/rust-hir-item.h: add has_type helper + * typecheck/rust-hir-trait-resolve.cc (TraitItemReference::resolve_item): + add missing type checking + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * util/rust-lang-item.h: Add new manually_drop lang item. + * util/rust-lang-item.cc: Likewise. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * util/rust-attribute-values.h: Add RUSTFMT value. + * util/rust-attributes.cc: Define the attribute. + * util/rust-attributes.h (enum CompilerPass): Add EXTERNAL variant. + * expand/rust-macro-builtins.cc: Fix formatting. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): Remove assertion. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * util/rust-attribute-values.h: Add missing attributes. + * util/rust-attributes.cc: Likewise. + * util/rust-attributes.h (enum CompilerPass): Mention adding something for const + functions. + +2025-04-14 beamandala <mandalapubhavesh@gmail.com> + + * expand/rust-macro-builtins.cc (MacroBuiltin::builtin_transcribers): + Add entry for track_caller. + * util/rust-attribute-values.h: add `TRACK_CALLER` attribute. + * util/rust-attributes.cc: add `track_caller` attribute definition. + +2025-04-14 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/rust-const-checker.cc + (ConstChecker::visit): Visit the enum items of enums. + * resolve/rust-ast-resolve-item.cc + (ResolveItem::visit): Resolve enum discriminants during nr1.0. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-macro-builtins-format-args.cc (format_args_parse_arguments): Improve safety, + allow extra commas after end of argument list. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-macro-expand.cc (MacroExpander::expand_decl_macro): Call into + TokenTreeDesugar. + * expand/rust-token-tree-desugar.cc: New file. + * expand/rust-token-tree-desugar.h: New file. + * Make-lang.in: Compile them. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-macro-expand.cc (MacroExpander::match_n_matches): Do not + insert fragments and substack fragments if the matcher failed. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * rust-session-manager.cc (Session::compile_crate): Call the visitor later in the pipeline. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.h (DelimTokenTree::get_locus): New function. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-expr.h (class RangeExpr): Add empty outer attributes and allow getting them + and setting them. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Return if module + is unloaded. + +2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com> + + * typecheck/rust-hir-type-check-expr.cc (is_default_fn): New. + (emit_ambiguous_resolution_error): New. + (handle_multiple_candidates): Properly handle multiple candidates in + the case of specialization. + (TypeCheckExpr::visit): Call `handle_multiple_candidates`. + +2025-04-14 Andrew Pinski <quic_apinski@quicinc.com> + + PR rust/119342 + * rust-gcc.cc (block): Add comment on why chaining + the variables of the scope toether. + +2025-04-14 Andrew Pinski <quic_apinski@quicinc.com> + + PR rust/119341 + * rust-gcc.cc (function_type): Use range fors. + (function_type_variadic): Likewise. + (fill_in_fields): Likewise. + (statement_list): Likewise. + (block): Likewise. + (block_add_statements): Likewise. + (function_set_parameters): Likewise. + (write_global_definitions): Likewise. + +2025-04-14 Andrew Pinski <quic_apinski@quicinc.com> + + * rust-gcc.cc (Bvariable::get_tree): Use error_operand_p. + (pointer_type): Likewise. + (reference_type): Likewise. + (immutable_type): Likewise. + (function_type): Likewise. + (function_type_variadic): Likewise. + Cleanup the check for receiver.type first. + (function_ptr_type): Use error_operand_p. + (fill_in_fields): Likewise. + (fill_in_array): Likewise. + (named_type): Likewise. + (type_size): Likewise. + (type_alignment): Likewise. + (type_field_alignment): Likewise. + (type_field_offset): Likewise. + (zero_expression): Likewise. + (float_constant_expression): Likewise. + (convert_expression): Likewise. + (struct_field_expression): Likewise. + (compound_expression): Likewise. + (conditional_expression): Likewise. + (negation_expression): Likewise. + (arithmetic_or_logical_expression): Likewise. + (arithmetic_or_logical_expression_checked): Likewise. + (comparison_expression): Likewise. + (lazy_boolean_expression): Likewise. + (constructor_expression): Likewise. + (array_constructor_expression): Likewise. + (array_index_expression): Likewise. + (call_expression): Likewise. + (init_statement): Likewise. + (assignment_statement): Likewise. + (return_statement): Likewise. + (exception_handler_statement): Likewise. + (if_statement): Likewise. + (compound_statement): Likewise. + Tighten up the code, removing t variable. + (statement_list): Use error_operand_p. + (block): Likewise. + (block_add_statements): Likewise. + (convert_tree): Likewise. + (global_variable): Likewise. + (global_variable_set_init): Likewise. + (local_variable): Likewise. + (parameter_variable): Likewise. + (static_chain_variable): Likewise. + (temporary_variable): Likewise. + (function): Likewise. Tighten up the code. + (function_defer_statement): Use error_operand_p. + (function_set_parameters): Use error_operand_p. + (write_global_definitions): Use error_operand_p. + Tighten up the code around the loop. + +2025-04-14 Andrew Pinski <quic_apinski@quicinc.com> + + * rust-gcc.cc (is_floating_point): Use FLOAT_TYPE_P + instead of manually checking the type. + +2025-04-08 Matty Kuhn <matty.kuhn.1@gmail.com> + + * ast/rust-ast.h: (AST::Attribute): add empty_input function + * checks/errors/rust-feature-gate.cc: (FeatureGate::visit): check for empty feature gate + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Update label + getter call. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * ast/rust-ast.cc (BreakExpr::as_string): Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Likewise. + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise. + * ast/rust-expr.h: Add optional getter and rename label getter to + get_label_unchecked. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): + Call unchecked getter. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): + Likewise. + * ast/rust-ast.cc (ContinueExpr::as_string): Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Likewise. + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise. + * ast/rust-expr.h: Add new getter for the optional and rename getter + to get_label_unchecked. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse-impl.h (Parser::parse_loop_label): Change function + return type to expected. + (Parser::parse_labelled_loop_expr): Adapt call location to new return + type. + * parse/rust-parse.h (enum class): Update function prototype. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add call + to label resolution if there is one label. + (Late::resolve_label): Look for labels and emit an error message on + failure. + * resolve/rust-late-name-resolver-2.0.h: Add function prototypes. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): + Change error message to match rustc. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-builder.cc (Builder::self_ref_param): Remove error state + and use optional. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Check label + before visiting. + * ast/rust-ast.cc (ContinueExpr::as_string): Retrieve label value. + (Lifetime::as_string): Retrieve lifetime value. + (ReferenceType::as_string): Likewise. + (SelfParam::as_string): Likewise. + * ast/rust-ast.h: Remove lifetime and LifetimeParam error state. + * ast/rust-desugar-for-loops.cc (DesugarForLoops::DesugarCtx::make_break_arm): + Use optional instead of error state. + * ast/rust-expr.h (class ContinueExpr): Make label optional. + * ast/rust-item.h (class SelfParam): Make lifetime optional. + * ast/rust-type.h (class ReferenceType): Likewise. + * backend/rust-compile-base.cc: Use optional for self param instead + of error state. + * backend/rust-compile-base.h: Update function prototype. + * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Use optional. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_self): Lower + lifetime only if it exists. + * hir/rust-ast-lower-block.h: Lower loop label only if it exists. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Remove + references to error state. + (ASTLowerTraitItem::visit): Lower self param only if it exists. + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Use nullopt + for default value instead of SelfParam error state. + * hir/rust-ast-lower.cc (ASTLoweringExprWithBlock::visit): Lower label + only if it exists. + * hir/rust-hir-dump.cc (Dump::do_traitfunctiondecl): Print self only if + it exists. + (Dump::visit): Liewise. + * hir/tree/rust-hir-bound.h: Remove error state. + * hir/tree/rust-hir-expr.cc (ContinueExpr::ContinueExpr): Use optional + in constructor for loop label. + (BreakExpr::BreakExpr): Likewise. + * hir/tree/rust-hir-expr.h (class ContinueExpr): Remove error state + implementation. + (class BreakExpr): Likewise. + * hir/tree/rust-hir-generic-param.h: Likewise. + * hir/tree/rust-hir-item.cc (SelfParam::SelfParam): Make lifetime + optional. + (Function::Function): Make self param optional. + * hir/tree/rust-hir-item.h (class Function): Likewise. + * hir/tree/rust-hir-type.cc (ReferenceType::ReferenceType): Make + lifetime optional. + * hir/tree/rust-hir-type.h (class ReferenceType): Likewise. + * hir/tree/rust-hir.cc (ContinueExpr::as_string): Use new getter. + (BreakExpr::as_string): Likewise. + (Lifetime::as_string): Likewise. + (ReferenceType::as_string): Likewise. + (TraitFunctionDecl::as_string): Likewise. + (SelfParam::as_string): Remove error state checking. + * parse/rust-parse-impl.h (Parser::parse_generic_param): Adapt to + optional. + (Parser::parse_lifetime_params): Likewise. + (Parser::parse_lifetime_params_objs): Likewise. + (Parser::parse_lifetime_param): Likewise. + (Parser::parse_lifetime_where_clause_item): Likewise. + (Parser::parse_type_param_bound): Likewise. + (Parser::parse_lifetime_bounds): Likewise. + (Parser::parse_path_generic_args): Likewise. + (Parser::parse_self_param): Likewise. + (Parser::parse_break_expr): Likewise. + (Parser::parse_continue_expr): Likewise. + (Parser::parse_reference_type_inner): Likewise. + * parse/rust-parse.h (class ParseLifetimeParamError): Add new class for + lifetime param parsing errors. + (class ParseLifetimeError): Add new class for lifetime parsing errors. + (enum ParseSelfError): Add new class for self param parsing errors. + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): + Use unchecked getter in checked context. And make anonymous region. + * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): + Likewise. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add + check for loop label before visiting it. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h: Remove error getter and constructor. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-builder.cc (Builder::block): Call with a nullopt instead + of an error loop label. + (WhileLetLoopExpr::as_string): Use getter function and adapt to + newtype. + * ast/rust-ast.cc (WhileLoopExpr::as_string): Likewise. + (LoopExpr::as_string): Likewise. + (BreakExpr::as_string): Likewise. + (ForLoopExpr::as_string): Likewise. + * ast/rust-expr.h (class BlockExpr): Make loop label optional. + (class BreakExpr): Likewise. + * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Use nullopt. + * expand/rust-derive-debug.cc (DeriveDebug::stub_debug_fn): Likewise. + * expand/rust-derive-default.cc (DeriveDefault::default_fn): Likewise. + * expand/rust-derive-eq.cc: Likewise. + * parse/rust-parse-impl.h (Parser::parse_block_expr): Use optional + for arguments. + (Parser::parse_loop_expr): Likewise. + (Parser::parse_while_loop_expr): Likewise. + (Parser::parse_while_let_loop_expr): Likewise. + (Parser::parse_for_loop_expr): Likewise. + (Parser::parse_labelled_loop_expr): Likewise. + (Parser::parse_loop_label): Return an optional. + * parse/rust-parse.h: Update function prototype and use nullopt for + default values. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Change default + visit order. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit loop label + only if it exists. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * hir/rust-ast-lower.cc (ASTLoweringBlock::visit): Lower label only if + it exists. + * hir/tree/rust-hir-expr.cc (BlockExpr::BlockExpr): Make loop label + optional. + (BaseLoopExpr::BaseLoopExpr): Likewise. + (LoopExpr::LoopExpr): Likewise. + (WhileLoopExpr::WhileLoopExpr): Likewise. + * hir/tree/rust-hir-expr.h: Use optional for lifetime and labels. + * hir/tree/rust-hir.cc (WhileLoopExpr::as_string): Use getter. + (WhileLetLoopExpr::as_string): Likewise. + (LoopExpr::as_string): Likewise. + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Resolve labels. + * resolve/rust-late-name-resolver-2.0.h: Add visit function prototype + for loop labels. + +2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/expected.h: Use gcc_unreachable within gcc context. + +2025-04-08 Sri Ganesh Thota <sriganeshthota12345@gmail.com> + + * resolve/rust-ast-resolve-base.h (redefined_error): created a function for + rust_error_at for redefined at multiple times. + * resolve/rust-ast-resolve-implitem.h: changed rust_error_at to redefined_error. + * resolve/rust-ast-resolve-stmt.cc (ResolveStmt::visit): changed rust_error_at to + redefined_error. + * resolve/rust-ast-resolve-stmt.h: changed rust_error_at to redefined_error. + * resolve/rust-ast-resolve-toplevel.h: changed rust_error_at to redefined_error. + +2025-04-08 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-visitor.cc + (DefaultASTVisitor::visit): Remove explicit visitation of a + function's self parameter, as if it exists it'll be visited as + one of the function parameters. + +2025-04-08 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-typecheck-context.cc (TypeCheckContext::lookup_lifetime): emit error + +2025-04-08 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.cc (Function::Function): Rename is_default -> has_default. + (Function::operator=): Likewise. + * ast/rust-item.h (class Function): Add `is_default` method. + * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Lower default qualifier. + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise. + * hir/tree/rust-hir-item.cc (Function::Function): Add `is_default` member. + (Function::operator=): Likewise. + * hir/tree/rust-hir-item.h (enum class Defaultness): New enum. + (class Function): Use it. + +2025-04-08 Arthur Cohen <arthur.cohen@embecosm.com> + + * checks/errors/rust-feature.cc (Feature::create): Handle `#![feature(min_specialization)]`. + * checks/errors/rust-feature.h: Likewise. + +2025-04-08 Philip Herron <herron.philip@googlemail.com> + + * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): fix error msg + * typecheck/rust-substitution-mapper.cc (SubstMapper::Resolve): add validation + (SubstMapper::valid_type): new check + (SubstMapper::visit): check if can resolve + * typecheck/rust-substitution-mapper.h: new prototype + +2025-04-08 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-base.cc (HIRCompileBase::address_expression): allow optional type + * backend/rust-compile-base.h: update prototype + * backend/rust-compile-expr.cc (CompileExpr::visit): update borrow expr + * backend/rust-compile-extern.h: remove unused debug + * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): update usage + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): lower raw ref + * hir/tree/rust-hir-expr.cc (BorrowExpr::BorrowExpr): add flag for raw ref + * hir/tree/rust-hir-expr.h (class BorrowExpr): add new raw ref field + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): add handle for raw ref + +2025-04-08 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): emit error + +2025-04-08 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): new argument + * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::TypeCheckBase): new helper + * typecheck/rust-hir-type-check-base.h: new helper prototype + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit): + remove comment out code + * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_root_path): check for null + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): likewise + (TypeResolveGenericParam::Resolve): new args + (TypeResolveGenericParam::ApplyAnyTraitBounds): new helper + (TypeResolveGenericParam::apply_trait_bounds): new field + (TypeResolveGenericParam::visit): update + * typecheck/rust-hir-type-check-type.h: new args + * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): reuse helper + * typecheck/rust-type-util.cc (query_type): check for recursive query + * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping): + remove const + (SubstitutionParamMapping::get_generic_param): likewise + * typecheck/rust-tyty-subst.h: likewise + * typecheck/rust-tyty-variance-analysis.cc (GenericTyVisitorCtx::process_type): likewise + +2025-04-08 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-base.cc: new flag is_root_item + * backend/rust-compile-base.h: update prototype + * backend/rust-compile-implitem.cc (CompileTraitItem::visit): update call + * backend/rust-compile-implitem.h: remove old debug internal error + * backend/rust-compile-item.cc (CompileItem::visit): update call + * backend/rust-compile-item.h: remove old debug + * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): update calls + * backend/rust-compile.cc: likewise + * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_path_to_trait): + remove assertion and error + +2025-04-08 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-base.cc: remove assertion + +2025-04-08 Philip Herron <herron.philip@googlemail.com> + + * rust-gcc.cc (arithmetic_or_logical_expression): unwrap const decls + +2025-04-08 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-forever-stack.h + (ForeverStack::ForeverStack): Initialize extern_prelude. + (ForeverStack::resolve_path): Add parameter + has_opening_scope_resolution. + (ForeverStack::extern_prelude): Add field. + * resolve/rust-forever-stack.hxx: Include rust-edition.h. + (ForeverStacl::resolve_path): Handle global paths (paths with an + opening scope resolution operator). + * resolve/rust-late-name-resolver-2.0.cc + (Late::visit): Handle global paths. + * resolve/rust-name-resolution-context.h + (NameResolutionContext::resolve_path): Handle global paths. + +2025-04-08 Ryutaro Okada <1015ryu88@gmail.com> + + * backend/rust-compile-resolve-path.cc: Evaluate the enum's discriminant in a const context + 2025-03-31 Philip Herron <herron.philip@googlemail.com> * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): @@ -1939,7 +6937,7 @@ 2025-03-21 Owen Avery <powerboat9.gamer@gmail.com> - * resolve/rust-name-resolver.cc: Include options.txt. + * resolve/rust-name-resolver.cc: Include options.h. (Resolver::insert_resolved_name): Assert that name resolution 2.0 is disabled. (Resolver::lookup_resolved_name): Likewise. diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 4028b47..e5a8a5e 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -73,6 +73,9 @@ GRS_OBJS = \ rust/rust-lex.o \ rust/rust-cfg-parser.o \ rust/rust-parse.o \ + rust/rust-parse-impl-proc-macro.o \ + rust/rust-parse-impl-macro.o \ + rust/rust-parse-impl-lexer.o \ rust/rust-ast.o \ rust/rust-ast-formatting.o \ rust/rust-path.o \ @@ -81,6 +84,8 @@ GRS_OBJS = \ rust/rust-ast-dump.o \ rust/rust-ast-collector.o \ rust/rust-ast-visitor.o \ + rust/rust-ast-pointer-visitor.o \ + rust/rust-hir-visitor.o \ rust/rust-hir-dump.o \ rust/rust-session-manager.o \ rust/rust-compile.o \ @@ -92,14 +97,15 @@ GRS_OBJS = \ rust/rust-cfg-strip.o \ rust/rust-expand-visitor.o \ rust/rust-ast-builder.o \ - rust/rust-ast-builder-type.o \ rust/rust-derive.o \ + rust/rust-derive-cmp-common.o \ rust/rust-derive-clone.o \ rust/rust-derive-copy.o \ rust/rust-derive-debug.o \ rust/rust-derive-default.o \ rust/rust-derive-partial-eq.o \ rust/rust-derive-eq.o \ + rust/rust-derive-ord.o \ rust/rust-derive-hash.o \ rust/rust-proc-macro.o \ rust/rust-macro-invoc-lexer.o \ @@ -113,8 +119,10 @@ GRS_OBJS = \ rust/rust-macro-builtins-log-debug.o \ rust/rust-macro-builtins-test-bench.o \ rust/rust-macro-builtins-format-args.o \ + rust/rust-macro-builtins-offset-of.o \ rust/rust-macro-builtins-location.o \ rust/rust-macro-builtins-include.o \ + rust/rust-token-tree-desugar.o \ rust/rust-fmt.o \ rust/rust-hir.o \ rust/rust-hir-map.o \ @@ -122,7 +130,6 @@ GRS_OBJS = \ rust/rust-keyword-values.o \ rust/rust-abi.o \ rust/rust-token-converter.o \ - rust/rust-macro.o \ rust/rust-ast-lower.o \ rust/rust-ast-lower-base.o \ rust/rust-ast-lower-pattern.o \ @@ -141,17 +148,8 @@ GRS_OBJS = \ rust/rust-ice-finalizer.o \ rust/rust-late-name-resolver-2.0.o \ rust/rust-immutable-name-resolution-context.o \ - rust/rust-early-name-resolver.o \ rust/rust-name-resolver.o \ - rust/rust-ast-resolve.o \ - rust/rust-ast-resolve-base.o \ - rust/rust-ast-resolve-item.o \ - rust/rust-ast-resolve-pattern.o \ - rust/rust-ast-resolve-expr.o \ - rust/rust-ast-resolve-type.o \ - rust/rust-ast-resolve-path.o \ - rust/rust-ast-resolve-stmt.o \ - rust/rust-ast-resolve-struct-expr-field.o \ + rust/rust-resolve-builtins.o \ rust/rust-forever-stack.o \ rust/rust-hir-type-check.o \ rust/rust-privacy-check.o \ @@ -236,11 +234,16 @@ GRS_OBJS = \ rust/rust-punycode.o \ rust/rust-unwrap-segment.o \ rust/rust-edition.o \ + rust/rust-ggc.o \ rust/rust-expand-format-args.o \ rust/rust-lang-item.o \ rust/rust-collect-lang-items.o \ + rust/rust-expression-yeast.o \ rust/rust-desugar-for-loops.o \ + rust/rust-desugar-while-let.o \ rust/rust-desugar-question-mark.o \ + rust/rust-desugar-apit.o \ + rust/rust-desugar-try-block.o \ $(END) # removed object files from here @@ -431,6 +434,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \ -I $(srcdir)/rust/checks/errors \ -I $(srcdir)/rust/checks/errors/privacy \ -I $(srcdir)/rust/checks/errors/borrowck \ + -I $(srcdir)/rust/checks/errors/feature \ -I $(srcdir)/rust/util \ -I $(srcdir)/rust/metadata \ -I $(srcdir)/../libgrust @@ -503,6 +507,11 @@ rust/%.o: rust/checks/errors/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) +# build feature related files in rust folder +rust/%.o: rust/checks/errors/feature/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + # build privacy pass files in rust folder rust/%.o: rust/checks/errors/privacy/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc deleted file mode 100644 index 13126b4..0000000 --- a/gcc/rust/ast/rust-ast-builder-type.cc +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (C) 2020-2024 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-builder-type.h" -#include "rust-ast-builder.h" -#include "rust-ast-full.h" -#include "rust-common.h" - -namespace Rust { -namespace AST { - -ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {} - -Type * -ASTTypeBuilder::build (Type &type) -{ - ASTTypeBuilder builder; - type.accept_vis (builder); - rust_assert (builder.translated != nullptr); - return builder.translated; -} - -void -ASTTypeBuilder::visit (BareFunctionType &fntype) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (TupleType &tuple) -{ - std::vector<std::unique_ptr<Type> > elems; - for (auto &elem : tuple.get_elems ()) - { - Type *t = ASTTypeBuilder::build (*elem.get ()); - std::unique_ptr<Type> ty (t); - elems.push_back (std::move (ty)); - } - translated = new TupleType (std::move (elems), tuple.get_locus ()); -} - -void -ASTTypeBuilder::visit (TypePath &path) -{ - std::vector<std::unique_ptr<TypePathSegment> > segments; - for (auto &seg : path.get_segments ()) - { - switch (seg->get_type ()) - { - case TypePathSegment::REG: { - const TypePathSegment &segment - = (const TypePathSegment &) (*seg.get ()); - TypePathSegment *s - = new TypePathSegment (segment.get_ident_segment (), - segment.get_separating_scope_resolution (), - segment.get_locus ()); - std::unique_ptr<TypePathSegment> sg (s); - segments.push_back (std::move (sg)); - } - break; - - case TypePathSegment::GENERIC: { - TypePathSegmentGeneric &generic - = (TypePathSegmentGeneric &) (*seg.get ()); - - GenericArgs args - = Builder::new_generic_args (generic.get_generic_args ()); - TypePathSegmentGeneric *s - = new TypePathSegmentGeneric (generic.get_ident_segment (), false, - std::move (args), - generic.get_locus ()); - std::unique_ptr<TypePathSegment> sg (s); - segments.push_back (std::move (sg)); - } - break; - - case TypePathSegment::FUNCTION: { - rust_unreachable (); - // TODO - // const TypePathSegmentFunction &fn - // = (const TypePathSegmentFunction &) (*seg.get ()); - } - break; - } - } - - translated = new TypePath (std::move (segments), path.get_locus (), - path.has_opening_scope_resolution_op ()); -} - -void -ASTTypeBuilder::visit (QualifiedPathInType &path) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (ArrayType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (ReferenceType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (RawPointerType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (SliceType &type) -{ - Type *t = ASTTypeBuilder::build (type.get_elem_type ()); - std::unique_ptr<Type> ty (t); - translated = new SliceType (std::move (ty), type.get_locus ()); -} - -void -ASTTypeBuilder::visit (InferredType &type) -{ - translated = new InferredType (type.get_locus ()); -} - -void -ASTTypeBuilder::visit (NeverType &type) -{ - translated = new NeverType (type.get_locus ()); -} - -void -ASTTypeBuilder::visit (TraitObjectTypeOneBound &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (TraitObjectType &type) -{ - /* TODO */ -} - -} // namespace AST -} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h deleted file mode 100644 index b67ae3b..0000000 --- a/gcc/rust/ast/rust-ast-builder-type.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2020-2024 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_AST_BUILDER_TYPE -#define RUST_AST_BUILDER_TYPE - -#include "rust-ast-visitor.h" - -namespace Rust { -namespace AST { - -class ASTTypeBuilder : public DefaultASTVisitor -{ -protected: - using DefaultASTVisitor::visit; - -public: - static Type *build (Type &type); - - void visit (BareFunctionType &fntype) override; - void visit (TupleType &tuple) override; - void visit (TypePath &path) override; - void visit (QualifiedPathInType &path) override; - void visit (ArrayType &type) override; - void visit (ReferenceType &type) override; - void visit (RawPointerType &type) override; - void visit (SliceType &type) override; - void visit (InferredType &type) override; - void visit (NeverType &type) override; - void visit (TraitObjectTypeOneBound &type) override; - void visit (TraitObjectType &type) override; - -private: - ASTTypeBuilder (); - - Type *translated; -}; - -} // namespace AST -} // namespace Rust - -#endif // RUST_AST_BUILDER_TYPE diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index cdc6eec..632f945 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -18,7 +18,6 @@ #include "rust-ast-builder.h" #include "optional.h" -#include "rust-ast-builder-type.h" #include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" @@ -29,7 +28,6 @@ #include "rust-pattern.h" #include "rust-system.h" #include "rust-token.h" -#include <memory> namespace Rust { namespace AST { @@ -137,7 +135,7 @@ Builder::tuple (std::vector<std::unique_ptr<Expr>> &&values) const std::unique_ptr<Param> Builder::self_ref_param (bool mutability) const { - return std::make_unique<SelfParam> (Lifetime::error (), mutability, loc); + return std::make_unique<SelfParam> (tl::nullopt, mutability, loc); } std::unique_ptr<Param> @@ -332,12 +330,18 @@ Builder::block () const } std::unique_ptr<BlockExpr> +Builder::block (std::unique_ptr<Expr> &&tail_expr) const +{ + return block (tl::nullopt, std::move (tail_expr)); +} + +std::unique_ptr<BlockExpr> Builder::block (std::vector<std::unique_ptr<Stmt>> &&stmts, std::unique_ptr<Expr> &&tail_expr) const { - return std::unique_ptr<BlockExpr> ( - new BlockExpr (std::move (stmts), std::move (tail_expr), {}, {}, - LoopLabel::error (), loc, loc)); + return std::unique_ptr<BlockExpr> (new BlockExpr (std::move (stmts), + std::move (tail_expr), {}, + {}, tl::nullopt, loc, loc)); } std::unique_ptr<Expr> @@ -442,6 +446,14 @@ Builder::field_access (std::unique_ptr<Expr> &&instance, new FieldAccessExpr (std::move (instance), field, {}, loc)); } +std::unique_ptr<StructPatternField> +Builder::struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr<Pattern> &&pattern) +{ + return std::make_unique<StructPatternFieldIdentPat> ( + field_name, std::move (pattern), std::vector<Attribute> (), loc); +} + std::unique_ptr<Pattern> Builder::wildcard () const { @@ -482,9 +494,14 @@ MatchCase Builder::match_case (std::unique_ptr<Pattern> &&pattern, std::unique_ptr<Expr> &&expr) { - return MatchCase (match_arm (std::move (pattern)), std::move (expr)); + return match_case (match_arm (std::move (pattern)), std::move (expr)); } +MatchCase +Builder::match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr) +{ + return MatchCase (std::move (arm), std::move (expr)); +} std::unique_ptr<Expr> Builder::loop (std::vector<std::unique_ptr<Stmt>> &&stmts) { @@ -523,23 +540,26 @@ Builder::generic_type_param ( std::vector<Attribute> ()); } -std::unique_ptr<Type> -Builder::new_type (Type &type) +std::unique_ptr<Stmt> +Builder::discriminant_value (std::string binding_name, std::string instance) { - Type *t = ASTTypeBuilder::build (type); - return std::unique_ptr<Type> (t); + auto intrinsic = ptrify ( + path_in_expression ({"core", "intrinsics", "discriminant_value"}, true)); + + return let (identifier_pattern (binding_name), nullptr, + call (std::move (intrinsic), identifier (instance))); } std::unique_ptr<GenericParam> Builder::new_lifetime_param (LifetimeParam ¶m) { Lifetime l = new_lifetime (param.get_lifetime ()); + std::vector<Lifetime> lifetime_bounds; + lifetime_bounds.reserve (param.get_lifetime_bounds ().size ()); + for (auto b : param.get_lifetime_bounds ()) - { - Lifetime bl = new_lifetime (b); - lifetime_bounds.push_back (bl); - } + lifetime_bounds.emplace_back (new_lifetime (b)); auto p = new LifetimeParam (l, std::move (lifetime_bounds), param.get_outer_attrs (), param.get_locus ()); @@ -547,6 +567,16 @@ Builder::new_lifetime_param (LifetimeParam ¶m) } std::unique_ptr<GenericParam> +Builder::new_const_param (ConstGenericParam ¶m) const +{ + return std::make_unique<ConstGenericParam> (param.get_name (), + param.get_type ().clone_type (), + param.get_default_value (), + param.get_outer_attrs (), + param.get_locus ()); +} + +std::unique_ptr<GenericParam> Builder::new_type_param ( TypeParam ¶m, std::vector<std::unique_ptr<TypeParamBound>> extra_bounds) { @@ -557,7 +587,7 @@ Builder::new_type_param ( std::unique_ptr<Type> type = nullptr; if (param.has_type ()) - type = new_type (param.get_type ()); + type = param.get_type ().reconstruct (); for (auto &&extra_bound : extra_bounds) type_param_bounds.emplace_back (std::move (extra_bound)); @@ -566,7 +596,8 @@ Builder::new_type_param ( { switch (b->get_bound_type ()) { - case TypeParamBound::TypeParamBoundType::TRAIT: { + case TypeParamBound::TypeParamBoundType::TRAIT: + { const TraitBound &tb = (const TraitBound &) *b.get (); const TypePath &path = tb.get_type_path (); @@ -574,11 +605,11 @@ Builder::new_type_param ( for (const auto &lifetime : tb.get_for_lifetimes ()) { std::vector<Lifetime> lifetime_bounds; + lifetime_bounds.reserve ( + lifetime.get_lifetime_bounds ().size ()); + for (const auto &b : lifetime.get_lifetime_bounds ()) - { - Lifetime bl = new_lifetime (b); - lifetime_bounds.push_back (std::move (bl)); - } + lifetime_bounds.emplace_back (new_lifetime (b)); Lifetime nl = new_lifetime (lifetime.get_lifetime ()); LifetimeParam p (std::move (nl), std::move (lifetime_bounds), @@ -591,33 +622,34 @@ Builder::new_type_param ( { switch (seg->get_type ()) { - case TypePathSegment::REG: { + case TypePathSegment::REG: + { const TypePathSegment &segment = (const TypePathSegment &) (*seg.get ()); - TypePathSegment *s = new TypePathSegment ( + + segments.emplace_back (new TypePathSegment ( segment.get_ident_segment (), segment.get_separating_scope_resolution (), - segment.get_locus ()); - std::unique_ptr<TypePathSegment> sg (s); - segments.push_back (std::move (sg)); + segment.get_locus ())); } break; - case TypePathSegment::GENERIC: { + case TypePathSegment::GENERIC: + { TypePathSegmentGeneric &generic = (TypePathSegmentGeneric &) (*seg.get ()); GenericArgs args = new_generic_args (generic.get_generic_args ()); - TypePathSegmentGeneric *s = new TypePathSegmentGeneric ( + + segments.emplace_back (new TypePathSegmentGeneric ( generic.get_ident_segment (), false, std::move (args), - generic.get_locus ()); - std::unique_ptr<TypePathSegment> sg (s); - segments.push_back (std::move (sg)); + generic.get_locus ())); } break; - case TypePathSegment::FUNCTION: { + case TypePathSegment::FUNCTION: + { rust_unreachable (); // TODO // const TypePathSegmentFunction &fn @@ -630,22 +662,19 @@ Builder::new_type_param ( TypePath p (std::move (segments), path.get_locus (), path.has_opening_scope_resolution_op ()); - TraitBound *b = new TraitBound (std::move (p), tb.get_locus (), - tb.is_in_parens (), - tb.has_opening_question_mark (), - std::move (for_lifetimes)); - std::unique_ptr<TypeParamBound> bound (b); - type_param_bounds.push_back (std::move (bound)); + type_param_bounds.emplace_back (new TraitBound ( + std::move (p), tb.get_locus (), tb.is_in_parens (), + tb.has_opening_question_mark (), std::move (for_lifetimes))); } break; - case TypeParamBound::TypeParamBoundType::LIFETIME: { + case TypeParamBound::TypeParamBoundType::LIFETIME: + { const Lifetime &l = (const Lifetime &) *b.get (); - auto bl = new Lifetime (l.get_lifetime_type (), - l.get_lifetime_name (), l.get_locus ()); - std::unique_ptr<TypeParamBound> bound (bl); - type_param_bounds.push_back (std::move (bound)); + type_param_bounds.emplace_back ( + new Lifetime (l.get_lifetime_type (), l.get_lifetime_name (), + l.get_locus ())); } break; } @@ -674,35 +703,37 @@ Builder::new_generic_args (GenericArgs &args) location_t locus = args.get_locus (); for (const auto &lifetime : args.get_lifetime_args ()) - { - Lifetime l = new_lifetime (lifetime); - lifetime_args.push_back (std::move (l)); - } + lifetime_args.push_back (new_lifetime (lifetime)); for (auto &binding : args.get_binding_args ()) { Type &t = *binding.get_type_ptr ().get (); - std::unique_ptr<Type> ty = new_type (t); - GenericArgsBinding b (binding.get_identifier (), std::move (ty), - binding.get_locus ()); - binding_args.push_back (std::move (b)); + std::unique_ptr<Type> ty = t.reconstruct (); + binding_args.emplace_back (binding.get_identifier (), std::move (ty), + binding.get_locus ()); } for (auto &arg : args.get_generic_args ()) { + tl::optional<GenericArg> new_arg = tl::nullopt; + switch (arg.get_kind ()) { - case GenericArg::Kind::Type: { - std::unique_ptr<Type> ty = new_type (arg.get_type ()); - GenericArg arg = GenericArg::create_type (std::move (ty)); - } + case GenericArg::Kind::Type: + new_arg = GenericArg::create_type (arg.get_type ().reconstruct ()); break; - - default: - // FIXME - rust_unreachable (); + case GenericArg::Kind::Either: + new_arg + = GenericArg::create_ambiguous (arg.get_path (), arg.get_locus ()); + break; + case GenericArg::Kind::Const: + new_arg + = GenericArg::create_const (arg.get_expression ().clone_expr ()); + // FIXME: Use `reconstruct()` here, not `clone_expr()` break; } + + generic_args.emplace_back (*new_arg); } return GenericArgs (std::move (lifetime_args), std::move (generic_args), diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 41ce118..843bab8 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -24,6 +24,7 @@ #include "rust-ast.h" #include "rust-item.h" #include "rust-operators.h" +#include <initializer_list> namespace Rust { namespace AST { @@ -51,6 +52,19 @@ vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2) return v; } +template <typename T> +std::vector<std::unique_ptr<T>> +vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2, std::unique_ptr<T> &&t3) +{ + auto v = std::vector<std::unique_ptr<T>> (); + + v.emplace_back (std::move (t1)); + v.emplace_back (std::move (t2)); + v.emplace_back (std::move (t3)); + + return v; +} + /* Pointer-ify something */ template <typename T> static std::unique_ptr<T> @@ -117,6 +131,9 @@ public: /* Create an empty block */ std::unique_ptr<BlockExpr> block () const; + /* Create a block with just a tail expression */ + std::unique_ptr<BlockExpr> block (std::unique_ptr<Expr> &&tail_expr) const; + /* Create an early return expression with an optional expression */ std::unique_ptr<Expr> return_expr (std::unique_ptr<Expr> &&to_return = nullptr); @@ -254,6 +271,10 @@ public: std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance, std::string field) const; + std::unique_ptr<StructPatternField> + struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr<Pattern> &&pattern); + /* Create a wildcard pattern (`_`) */ std::unique_ptr<Pattern> wildcard () const; /* Create a reference pattern (`&pattern`) */ @@ -268,6 +289,7 @@ public: MatchArm match_arm (std::unique_ptr<Pattern> &&pattern); MatchCase match_case (std::unique_ptr<Pattern> &&pattern, std::unique_ptr<Expr> &&expr); + MatchCase match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr); /* Create a loop expression */ std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts); @@ -285,11 +307,20 @@ public: std::vector<std::unique_ptr<TypeParamBound>> &&bounds, std::unique_ptr<Type> &&type = nullptr); - static std::unique_ptr<Type> new_type (Type &type); + /** + * Create a let statement with the discriminant value of a given enum + * instance. This helper exists since it is a common operation in a lot of the + * derive implementations, and it sucks to repeat all the steps every time. + */ + std::unique_ptr<Stmt> discriminant_value (std::string binding_name, + std::string instance = "self"); static std::unique_ptr<GenericParam> new_lifetime_param (LifetimeParam ¶m); + std::unique_ptr<GenericParam> + new_const_param (ConstGenericParam ¶m) const; + static std::unique_ptr<GenericParam> new_type_param ( TypeParam ¶m, std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {}); @@ -298,11 +329,13 @@ public: static GenericArgs new_generic_args (GenericArgs &args); -private: - /** - * Location of the generated AST nodes - */ + /* Location of the generated AST nodes */ location_t loc; + +private: + /* Some constexpr helpers for some of the builders */ + static constexpr std::initializer_list<const char *> discriminant_value_path + = {"core", "intrinsics", "discriminant_value"}; }; } // namespace AST diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 3297407..721d274 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -18,6 +18,7 @@ #include "rust-ast-collector.h" #include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" #include "rust-diagnostics.h" #include "rust-expr.h" #include "rust-item.h" @@ -75,13 +76,13 @@ TokenCollector::trailing_comma () void TokenCollector::newline () { - tokens.push_back ({CollectItem::Kind::Newline}); + tokens.emplace_back (CollectItem::Kind::Newline); } void TokenCollector::indentation () { - tokens.push_back ({indent_level}); + tokens.emplace_back (indent_level); } void @@ -100,7 +101,7 @@ TokenCollector::decrement_indentation () void TokenCollector::comment (std::string comment) { - tokens.push_back ({comment}); + tokens.emplace_back (comment); } void @@ -154,20 +155,24 @@ TokenCollector::visit (Attribute &attrib) { switch (attrib.get_attr_input ().get_attr_input_type ()) { - case AST::AttrInput::AttrInputType::LITERAL: { + case AST::AttrInput::AttrInputType::LITERAL: + { visit (static_cast<AttrInputLiteral &> (attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::MACRO: { + case AST::AttrInput::AttrInputType::MACRO: + { visit (static_cast<AttrInputMacro &> (attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::META_ITEM: { + case AST::AttrInput::AttrInputType::META_ITEM: + { visit (static_cast<AttrInputMetaItemContainer &> ( attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::TOKEN_TREE: { + case AST::AttrInput::AttrInputType::TOKEN_TREE: + { visit (static_cast<DelimTokenTree &> (attrib.get_attr_input ())); break; } @@ -350,7 +355,8 @@ TokenCollector::visit (MaybeNamedParam ¶m) void TokenCollector::visit (Token &tok) { - std::string data = tok.get_tok_ptr ()->has_str () ? tok.get_str () : ""; + std::string data + = tok.get_tok_ptr ()->should_have_str () ? tok.get_str () : ""; switch (tok.get_id ()) { case IDENTIFIER: @@ -491,7 +497,7 @@ TokenCollector::visit (ConstGenericParam ¶m) if (param.has_default_value ()) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); - visit (param.get_default_value ()); + visit (param.get_default_value_unchecked ()); } } @@ -634,13 +640,12 @@ TokenCollector::visit (GenericArg &arg) case GenericArg::Kind::Type: visit (arg.get_type ()); break; - case GenericArg::Kind::Either: { + case GenericArg::Kind::Either: + { auto path = arg.get_path (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path))); } break; - case GenericArg::Kind::Error: - rust_unreachable (); } } @@ -791,7 +796,8 @@ TokenCollector::visit (Literal &lit, location_t locus) push (Rust::Token::make_float (locus, std::move (value), lit.get_type_hint ())); break; - case Literal::LitType::BOOL: { + case Literal::LitType::BOOL: + { if (value == Values::Keywords::FALSE_LITERAL) push (Rust::Token::make (FALSE_LITERAL, locus)); else if (value == Values::Keywords::TRUE_LITERAL) @@ -835,13 +841,13 @@ TokenCollector::visit (MetaItemLitExpr &item) } void -TokenCollector::visit (MetaItemPathLit &item) +TokenCollector::visit (MetaItemPathExpr &item) { - auto path = item.get_path (); - auto lit = item.get_literal (); + auto &path = item.get_path (); + auto &expr = item.get_expr (); visit (path); - push (Rust::Token::make (COLON, item.get_locus ())); - visit (lit); + push (Rust::Token::make (EQUAL, item.get_locus ())); + visit (expr); } void @@ -866,7 +872,8 @@ TokenCollector::visit (BorrowExpr &expr) push (Rust::Token::make (MUT, UNDEF_LOCATION)); } - visit (expr.get_borrowed_expr ()); + if (expr.has_borrow_expr ()) + visit (expr.get_borrowed_expr ()); } void @@ -1266,12 +1273,34 @@ TokenCollector::visit (BlockExpr &expr) } void +TokenCollector::visit (AnonConst &expr) +{ + if (!expr.is_deferred ()) + { + visit (expr.get_inner_expr ()); + return; + } + + push (Rust::Token::make_string (expr.get_locus (), "_")); +} + +void +TokenCollector::visit (ConstBlock &expr) +{ + push (Rust::Token::make (CONST, expr.get_locus ())); + + // The inner expression is already a block expr, so we don't need to add + // curlies + visit (expr.get_const_expr ()); +} + +void TokenCollector::visit (ClosureExprInnerTyped &expr) { visit_closure_common (expr); push (Rust::Token::make (RETURN_TYPE, expr.get_locus ())); visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void @@ -1279,7 +1308,7 @@ TokenCollector::visit (ContinueExpr &expr) { push (Rust::Token::make (CONTINUE, expr.get_locus ())); if (expr.has_label ()) - visit (expr.get_label ()); + visit (expr.get_label_unchecked ()); } void @@ -1287,7 +1316,7 @@ TokenCollector::visit (BreakExpr &expr) { push (Rust::Token::make (BREAK, expr.get_locus ())); if (expr.has_label ()) - visit (expr.get_label ()); + visit (expr.get_label_unchecked ()); if (expr.has_break_expr ()) visit (expr.get_break_expr ()); } @@ -1351,6 +1380,13 @@ TokenCollector::visit (ReturnExpr &expr) } void +TokenCollector::visit (TryExpr &expr) +{ + push (Rust::Token::make (TRY, expr.get_locus ())); + visit (expr.get_block_expr ()); +} + +void TokenCollector::visit (UnsafeBlockExpr &expr) { push (Rust::Token::make (UNSAFE, expr.get_locus ())); @@ -1520,7 +1556,136 @@ TokenCollector::visit (AsyncBlockExpr &expr) void TokenCollector::visit (InlineAsm &expr) -{} +{ + push (Rust::Token::make_identifier (expr.get_locus (), "asm")); + push (Rust::Token::make (EXCLAM, expr.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + + for (auto &template_str : expr.get_template_strs ()) + push (Rust::Token::make_string (template_str.get_locus (), + std::move (template_str.symbol))); + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &operand : expr.get_operands ()) + { + using RegisterType = AST::InlineAsmOperand::RegisterType; + switch (operand.get_register_type ()) + { + case RegisterType::In: + { + visit (operand.get_in ().expr); + break; + } + case RegisterType::Out: + { + visit (operand.get_out ().expr); + break; + } + case RegisterType::InOut: + { + visit (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: + { + auto split = operand.get_split_in_out (); + visit (split.in_expr); + visit (split.out_expr); + break; + } + case RegisterType::Const: + { + visit (operand.get_const ().anon_const.get_inner_expr ()); + break; + } + case RegisterType::Sym: + { + visit (operand.get_sym ().expr); + break; + } + case RegisterType::Label: + { + visit (operand.get_label ().expr); + break; + } + } + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &clobber : expr.get_clobber_abi ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (clobber.symbol))); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it) + { + auto &arg = *it; + push ( + Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ())); + push (Rust::Token::make (EQUAL, expr.get_locus ())); + push (Rust::Token::make_identifier (expr.get_locus (), + std::to_string (arg.second))); + + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &option : expr.get_options ()) + { + push (Rust::Token::make_identifier ( + expr.get_locus (), InlineAsm::option_to_string (option).c_str ())); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); +} + +void +TokenCollector::visit (LlvmInlineAsm &expr) +{ + push (Rust::Token::make_identifier (expr.get_locus (), "llvm_asm")); + push (Rust::Token::make (EXCLAM, expr.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + for (auto &template_str : expr.get_templates ()) + push (Rust::Token::make_string (template_str.get_locus (), + std::move (template_str.symbol))); + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto output : expr.get_outputs ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (output.constraint))); + visit (output.expr); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto input : expr.get_inputs ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (input.constraint))); + visit (input.expr); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto &clobber : expr.get_clobbers ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (clobber.symbol))); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + // Dump options + + push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); +} // rust-item.h @@ -1656,7 +1821,8 @@ TokenCollector::visit (UseTreeGlob &use_tree) { switch (use_tree.get_glob_type ()) { - case UseTreeGlob::PathType::PATH_PREFIXED: { + case UseTreeGlob::PathType::PATH_PREFIXED: + { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -1676,7 +1842,8 @@ TokenCollector::visit (UseTreeList &use_tree) { switch (use_tree.get_path_type ()) { - case UseTreeList::PathType::PATH_PREFIXED: { + case UseTreeList::PathType::PATH_PREFIXED: + { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -1704,7 +1871,8 @@ TokenCollector::visit (UseTreeRebind &use_tree) visit (path); switch (use_tree.get_new_bind_type ()) { - case UseTreeRebind::NewBindType::IDENTIFIER: { + case UseTreeRebind::NewBindType::IDENTIFIER: + { push (Rust::Token::make (AS, UNDEF_LOCATION)); auto id = use_tree.get_identifier ().as_string (); push ( @@ -1925,8 +2093,7 @@ TokenCollector::visit (ConstantItem &item) } else { - auto id = item.get_identifier (); - push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); + push (Rust::Token::make_identifier (item.get_identifier ())); } push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (item.get_type ()); @@ -2005,19 +2172,6 @@ TokenCollector::visit (SelfParam ¶m) } void -TokenCollector::visit (TraitItemConst &item) -{ - auto id = item.get_identifier ().as_string (); - indentation (); - push (Rust::Token::make (CONST, item.get_locus ())); - push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); - push (Rust::Token::make (COLON, UNDEF_LOCATION)); - visit (item.get_type ()); - push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); - newline (); -} - -void TokenCollector::visit (TraitItemType &item) { visit_items_as_lines (item.get_outer_attrs ()); @@ -2331,10 +2485,10 @@ TokenCollector::visit (IdentifierPattern &pattern) auto id = pattern.get_ident ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); - if (pattern.has_pattern_to_bind ()) + if (pattern.has_subpattern ()) { push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION)); - visit (pattern.get_pattern_to_bind ()); + visit (pattern.get_subpattern ()); } } @@ -2466,7 +2620,7 @@ TokenCollector::visit (StructPattern &pattern) if (elems.has_struct_pattern_fields ()) { visit_items_joined_by_separator (elems.get_struct_pattern_fields ()); - if (elems.has_etc ()) + if (elems.has_rest ()) { push (Rust::Token::make (COMMA, UNDEF_LOCATION)); visit_items_as_lines (elems.get_etc_outer_attrs ()); @@ -2483,13 +2637,13 @@ TokenCollector::visit (StructPattern &pattern) // void TokenCollector::visit(TupleStructItems& ){} void -TokenCollector::visit (TupleStructItemsNoRange &pattern) +TokenCollector::visit (TupleStructItemsNoRest &pattern) { visit_items_joined_by_separator (pattern.get_patterns ()); } void -TokenCollector::visit (TupleStructItemsRange &pattern) +TokenCollector::visit (TupleStructItemsHasRest &pattern) { for (auto &lower : pattern.get_lower_patterns ()) { @@ -2516,13 +2670,13 @@ TokenCollector::visit (TupleStructPattern &pattern) // {} void -TokenCollector::visit (TuplePatternItemsMultiple &pattern) +TokenCollector::visit (TuplePatternItemsNoRest &pattern) { visit_items_joined_by_separator (pattern.get_patterns (), COMMA); } void -TokenCollector::visit (TuplePatternItemsRanged &pattern) +TokenCollector::visit (TuplePatternItemsHasRest &pattern) { for (auto &lower : pattern.get_lower_patterns ()) { @@ -2552,10 +2706,34 @@ TokenCollector::visit (GroupedPattern &pattern) } void +TokenCollector::visit (SlicePatternItemsNoRest &items) +{ + visit_items_joined_by_separator (items.get_patterns (), COMMA); +} + +void +TokenCollector::visit (SlicePatternItemsHasRest &items) +{ + if (!items.get_lower_patterns ().empty ()) + { + visit_items_joined_by_separator (items.get_lower_patterns (), COMMA); + push (Rust::Token::make (COMMA, UNDEF_LOCATION)); + } + + push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION)); + + if (!items.get_upper_patterns ().empty ()) + { + push (Rust::Token::make (COMMA, UNDEF_LOCATION)); + visit_items_joined_by_separator (items.get_upper_patterns (), COMMA); + } +} + +void TokenCollector::visit (SlicePattern &pattern) { push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ())); - visit_items_joined_by_separator (pattern.get_items (), COMMA); + visit (pattern.get_items ()); push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); } @@ -2819,8 +2997,234 @@ TokenCollector::visit (BareFunctionType &type) void TokenCollector::visit (AST::FormatArgs &fmt) { - rust_sorry_at (fmt.get_locus (), "%s:%u: unimplemented FormatArgs visitor", - __FILE__, __LINE__); + push (Rust::Token::make_identifier (fmt.get_locus (), "format_args")); + push (Rust::Token::make (EXCLAM, fmt.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, fmt.get_locus ())); + + std::string reconstructed_template = "\""; + const auto &template_pieces = fmt.get_template (); + + for (const auto &piece : template_pieces.get_pieces ()) + { + if (piece.tag == Fmt::ffi::Piece::Tag::String) + { + std::string literal = piece.string._0.to_string (); + for (char c : literal) + { + if (c == '"' || c == '\\') + { + reconstructed_template += '\\'; + } + else if (c == '\n') + { + reconstructed_template += "\\n"; + continue; + } + else if (c == '\r') + { + reconstructed_template += "\\r"; + continue; + } + else if (c == '\t') + { + reconstructed_template += "\\t"; + continue; + } + reconstructed_template += c; + } + } + else if (piece.tag == Fmt::ffi::Piece::Tag::NextArgument) + { + reconstructed_template += "{"; + + const auto &argument = piece.next_argument._0; + const auto &position = argument.position; + + switch (position.tag) + { + case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: + break; + case Fmt::ffi::Position::Tag::ArgumentIs: + reconstructed_template + += std::to_string (position.argument_is._0); + break; + case Fmt::ffi::Position::Tag::ArgumentNamed: + reconstructed_template += position.argument_named._0.to_string (); + break; + } + + // Add format specifiers if any (like :?, :x, etc.) + const auto &format_spec = argument.format; + + bool has_format_spec = false; + std::string format_part; + + // For now, skipping the complex format specifications that use FFIOpt + // since FFIOpt::get_opt() has a bug. + + // Alignment + if (format_spec.align != Fmt::ffi::Alignment::AlignUnknown) + { + has_format_spec = true; + switch (format_spec.align) + { + case Fmt::ffi::Alignment::AlignLeft: + format_part += "<"; + break; + case Fmt::ffi::Alignment::AlignRight: + format_part += ">"; + break; + case Fmt::ffi::Alignment::AlignCenter: + format_part += "^"; + break; + case Fmt::ffi::Alignment::AlignUnknown: + break; + } + } + + // Alternate flag + if (format_spec.alternate) + { + has_format_spec = true; + format_part += "#"; + } + + // Zero pad flag + if (format_spec.zero_pad) + { + has_format_spec = true; + format_part += "0"; + } + + // Width + if (format_spec.width.tag != Fmt::ffi::Count::Tag::CountImplied) + { + has_format_spec = true; + switch (format_spec.width.tag) + { + case Fmt::ffi::Count::Tag::CountIs: + format_part += std::to_string (format_spec.width.count_is._0); + break; + case Fmt::ffi::Count::Tag::CountIsParam: + format_part + += std::to_string (format_spec.width.count_is_param._0) + + "$"; + break; + case Fmt::ffi::Count::Tag::CountIsName: + format_part + += format_spec.width.count_is_name._0.to_string () + "$"; + break; + case Fmt::ffi::Count::Tag::CountIsStar: + format_part += "*"; + break; + case Fmt::ffi::Count::Tag::CountImplied: + break; + } + } + + // Precision + if (format_spec.precision.tag != Fmt::ffi::Count::Tag::CountImplied) + { + has_format_spec = true; + format_part += "."; + switch (format_spec.precision.tag) + { + case Fmt::ffi::Count::Tag::CountIs: + format_part + += std::to_string (format_spec.precision.count_is._0); + break; + case Fmt::ffi::Count::Tag::CountIsParam: + format_part + += std::to_string (format_spec.precision.count_is_param._0) + + "$"; + break; + case Fmt::ffi::Count::Tag::CountIsName: + format_part + += format_spec.precision.count_is_name._0.to_string () + + "$"; + break; + case Fmt::ffi::Count::Tag::CountIsStar: + format_part += "*"; + break; + case Fmt::ffi::Count::Tag::CountImplied: + break; + } + } + + // Type/trait (like ?, x, X, etc.) + std::string type_str = format_spec.ty.to_string (); + if (!type_str.empty ()) + { + has_format_spec = true; + format_part += type_str; + } + + // Add the format specification if any + if (has_format_spec) + { + reconstructed_template += ":"; + reconstructed_template += format_part; + } + + reconstructed_template += "}"; + } + } + reconstructed_template += "\""; + + push (Rust::Token::make_string (fmt.get_locus (), reconstructed_template)); + + // Visit format arguments if any exist + auto &arguments = fmt.get_arguments (); + if (!arguments.empty ()) + { + push (Rust::Token::make (COMMA, fmt.get_locus ())); + + auto &args = arguments.get_args (); + for (size_t i = 0; i < args.size (); ++i) + { + if (i > 0) + { + push (Rust::Token::make (COMMA, fmt.get_locus ())); + } + + auto kind = args[i].get_kind (); + + // Handle named arguments: name = expr + if (kind.kind == FormatArgumentKind::Kind::Named) + { + auto ident = kind.get_ident ().as_string (); + push (Rust::Token::make_identifier (fmt.get_locus (), + std::move (ident))); + push (Rust::Token::make (EQUAL, fmt.get_locus ())); + } + // Note: Captured arguments are handled implicitly in the template + // reconstruction They don't need explicit "name =" syntax in the + // reconstructed macro call + + auto &expr = args[i].get_expr (); + expr.accept_vis (*this); + } + } + + push (Rust::Token::make (RIGHT_PAREN, fmt.get_locus ())); +} + +void +TokenCollector::visit (AST::OffsetOf &offset_of) +{ + auto loc = offset_of.get_locus (); + + push (Rust::Token::make_identifier (loc, "offset_of")); + push (Rust::Token::make (EXCLAM, loc)); + push (Rust::Token::make (LEFT_PAREN, loc)); + + visit (offset_of.get_type ()); + + push (Rust::Token::make (COMMA, loc)); + + push (Rust::Token::make_identifier (offset_of.get_field ())); + + push (Rust::Token::make (RIGHT_PAREN, loc)); } } // namespace AST diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index b014c23..3e33476 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -246,7 +246,7 @@ public: void visit (AttrInputLiteral &attr_input); void visit (AttrInputMacro &attr_input); void visit (MetaItemLitExpr &meta_item); - void visit (MetaItemPathLit &meta_item); + void visit (MetaItemPathExpr &meta_item); void visit (BorrowExpr &expr); void visit (DereferenceExpr &expr); void visit (ErrorPropagationExpr &expr); @@ -277,6 +277,8 @@ public: void visit (ClosureParam ¶m); void visit (ClosureExprInner &expr); void visit (BlockExpr &expr); + void visit (AnonConst &expr); + void visit (ConstBlock &expr); void visit (ClosureExprInnerTyped &expr); void visit (ContinueExpr &expr); void visit (BreakExpr &expr); @@ -287,6 +289,7 @@ public: void visit (RangeFromToInclExpr &expr); void visit (RangeToInclExpr &expr); void visit (ReturnExpr &expr); + void visit (TryExpr &expr); void visit (BoxExpr &expr); void visit (UnsafeBlockExpr &expr); void visit (LoopExpr &expr); @@ -303,6 +306,7 @@ public: void visit (AwaitExpr &expr); void visit (AsyncBlockExpr &expr); void visit (InlineAsm &expr); + void visit (LlvmInlineAsm &expr); // rust-item.h void visit (TypeParam ¶m); void visit (LifetimeWhereClauseItem &item); @@ -326,7 +330,6 @@ public: void visit (ConstantItem &const_item); void visit (StaticItem &static_item); void visit (SelfParam ¶m); - void visit (TraitItemConst &item); void visit (TraitItemType &item); void visit (Trait &trait); void visit (InherentImpl &impl); @@ -366,14 +369,16 @@ public: void visit (StructPatternFieldIdent &field); void visit (StructPattern &pattern); // void visit(TupleStructItems& tuple_items); - void visit (TupleStructItemsNoRange &tuple_items); - void visit (TupleStructItemsRange &tuple_items); + void visit (TupleStructItemsNoRest &tuple_items); + void visit (TupleStructItemsHasRest &tuple_items); void visit (TupleStructPattern &pattern); // void visit(TuplePatternItems& tuple_items); - void visit (TuplePatternItemsMultiple &tuple_items); - void visit (TuplePatternItemsRanged &tuple_items); + void visit (TuplePatternItemsNoRest &tuple_items); + void visit (TuplePatternItemsHasRest &tuple_items); void visit (TuplePattern &pattern); void visit (GroupedPattern &pattern); + void visit (SlicePatternItemsNoRest &items); + void visit (SlicePatternItemsHasRest &items); void visit (SlicePattern &pattern); void visit (AltPattern &pattern); @@ -399,6 +404,7 @@ public: void visit (BareFunctionType &type); void visit (FormatArgs &fmt); + void visit (OffsetOf &offset_of); }; } // namespace AST diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h index 02c99b7..0c3875e 100644 --- a/gcc/rust/ast/rust-ast-dump.h +++ b/gcc/rust/ast/rust-ast-dump.h @@ -49,7 +49,8 @@ public: { switch (item.get_kind ()) { - case AST::CollectItem::Kind::Token: { + case AST::CollectItem::Kind::Token: + { TokenPtr current = item.get_token (); if (require_spacing (previous, current)) stream << " "; @@ -90,7 +91,6 @@ private: } // namespace Rust // In the global namespace to make it easier to call from debugger -void -debug (Rust::AST::Visitable &v); +void debug (Rust::AST::Visitable &v); #endif // !RUST_AST_DUMP_H diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h index 3dfabbc..075c51c 100644 --- a/gcc/rust/ast/rust-ast-formatting.h +++ b/gcc/rust/ast/rust-ast-formatting.h @@ -19,6 +19,9 @@ #ifndef RUST_AST_FORMATTING_H #define RUST_AST_FORMATTING_H +#include "rust-ast.h" +#include "rust-system.h" + namespace Rust { namespace AST { @@ -35,23 +38,18 @@ enum AttrMode INNER }; -std::string -indent_spaces (enum indent_mode mode); +std::string indent_spaces (enum indent_mode mode); // Gets a string in a certain delim type. -std::string -get_string_in_delims (std::string str_input, DelimType delim_type); +std::string get_string_in_delims (std::string str_input, DelimType delim_type); -std::string -get_mode_dump_desc (AttrMode mode); +std::string get_mode_dump_desc (AttrMode mode); // Adds lines below adding attributes -std::string -append_attributes (std::vector<Attribute> attrs, AttrMode mode); +std::string append_attributes (std::vector<Attribute> attrs, AttrMode mode); // Removes the beginning and end quotes of a quoted string. -std::string -unquote_string (std::string input); +std::string unquote_string (std::string input); } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc index 076cab3..8a547b4 100644 --- a/gcc/rust/ast/rust-ast-fragment.cc +++ b/gcc/rust/ast/rust-ast-fragment.cc @@ -107,29 +107,42 @@ Fragment::should_expand () const bool Fragment::is_expression_fragment () const { - return is_single_fragment_of_kind (SingleASTNode::NodeType::EXPRESSION); + return is_single_fragment_of_kind (SingleASTNode::Kind::Expr); } bool Fragment::is_type_fragment () const { - return is_single_fragment_of_kind (SingleASTNode::NodeType::TYPE); + return is_single_fragment_of_kind (SingleASTNode::Kind::Type); +} + +bool +Fragment::is_pattern_fragment () const +{ + return is_single_fragment_of_kind (SingleASTNode::Kind::Pattern); } std::unique_ptr<Expr> Fragment::take_expression_fragment () { - assert_single_fragment (SingleASTNode::NodeType::EXPRESSION); + assert_single_fragment (SingleASTNode::Kind::Expr); return nodes[0].take_expr (); } std::unique_ptr<Type> Fragment::take_type_fragment () { - assert_single_fragment (SingleASTNode::NodeType::TYPE); + assert_single_fragment (SingleASTNode::Kind::Type); return nodes[0].take_type (); } +std::unique_ptr<Pattern> +Fragment::take_pattern_fragment () +{ + assert_single_fragment (SingleASTNode::Kind::Pattern); + return nodes[0].take_pattern (); +} + void Fragment::accept_vis (ASTVisitor &vis) { @@ -144,21 +157,22 @@ Fragment::is_single_fragment () const } bool -Fragment::is_single_fragment_of_kind (SingleASTNode::NodeType expected) const +Fragment::is_single_fragment_of_kind (SingleASTNode::Kind expected) const { return is_single_fragment () && nodes[0].get_kind () == expected; } void -Fragment::assert_single_fragment (SingleASTNode::NodeType expected) const -{ - static const std::map<SingleASTNode::NodeType, const char *> str_map = { - {SingleASTNode::NodeType::ASSOC_ITEM, "associated item"}, - {SingleASTNode::NodeType::ITEM, "item"}, - {SingleASTNode::NodeType::TYPE, "type"}, - {SingleASTNode::NodeType::EXPRESSION, "expr"}, - {SingleASTNode::NodeType::STMT, "stmt"}, - {SingleASTNode::NodeType::EXTERN, "extern"}, +Fragment::assert_single_fragment (SingleASTNode::Kind expected) const +{ + static const std::map<SingleASTNode::Kind, const char *> str_map = { + {SingleASTNode::Kind::Assoc, "associated item"}, + {SingleASTNode::Kind::Item, "item"}, + {SingleASTNode::Kind::Type, "type"}, + {SingleASTNode::Kind::Expr, "expr"}, + {SingleASTNode::Kind::Stmt, "stmt"}, + {SingleASTNode::Kind::Extern, "extern"}, + {SingleASTNode::Kind::Pattern, "pattern"}, }; auto actual = nodes[0].get_kind (); diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h index 7d01fd7..23f26d3 100644 --- a/gcc/rust/ast/rust-ast-fragment.h +++ b/gcc/rust/ast/rust-ast-fragment.h @@ -86,9 +86,11 @@ public: bool is_expression_fragment () const; bool is_type_fragment () const; + bool is_pattern_fragment () const; std::unique_ptr<Expr> take_expression_fragment (); std::unique_ptr<Type> take_type_fragment (); + std::unique_ptr<Pattern> take_pattern_fragment (); void accept_vis (ASTVisitor &vis); @@ -119,8 +121,8 @@ private: * one Node will be extracted from the `nodes` vector */ bool is_single_fragment () const; - bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const; - void assert_single_fragment (SingleASTNode::NodeType expected) const; + bool is_single_fragment_of_kind (SingleASTNode::Kind expected) const; + void assert_single_fragment (SingleASTNode::Kind expected) const; }; enum class InvocKind diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 9359248..2903ba7 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -78,7 +78,7 @@ class LiteralExpr; class AttrInputLiteral; class AttrInputMacro; class MetaItemLitExpr; -class MetaItemPathLit; +class MetaItemPathExpr; class OperatorExpr; class BorrowExpr; class DereferenceExpr; @@ -115,6 +115,8 @@ struct ClosureParam; class ClosureExpr; class ClosureExprInner; class BlockExpr; +class AnonConst; +class ConstBlock; class ClosureExprInnerTyped; class ContinueExpr; class BreakExpr; @@ -126,6 +128,7 @@ class RangeFullExpr; class RangeFromToInclExpr; class RangeToInclExpr; class ReturnExpr; +class TryExpr; class UnsafeBlockExpr; class LoopLabel; class BaseLoopExpr; @@ -146,7 +149,6 @@ class MatchExpr; class AwaitExpr; class AsyncBlockExpr; enum class InlineAsmOption; -struct AnonConst; struct InlineAsmRegOrRegClass; class InlineAsmOperand; struct InlineAsmPlaceHolder; @@ -193,7 +195,6 @@ class Enum; class Union; class ConstantItem; class StaticItem; -class TraitItemConst; class TraitItemType; class Trait; class Impl; @@ -238,14 +239,16 @@ class StructPatternFieldIdent; class StructPatternElements; class StructPattern; class TupleStructItems; -class TupleStructItemsNoRange; -class TupleStructItemsRange; +class TupleStructItemsNoRest; +class TupleStructItemsHasRest; class TupleStructPattern; class TuplePatternItems; -class TuplePatternItemsMultiple; -class TuplePatternItemsRanged; +class TuplePatternItemsNoRest; +class TuplePatternItemsHasRest; class TuplePattern; class GroupedPattern; +class SlicePatternItemsNoRest; +class SlicePatternItemsHasRest; class SlicePattern; class AltPattern; diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.cc b/gcc/rust/ast/rust-ast-pointer-visitor.cc new file mode 100644 index 0000000..ee1f001 --- /dev/null +++ b/gcc/rust/ast/rust-ast-pointer-visitor.cc @@ -0,0 +1,1475 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-ast-pointer-visitor.h" +#include "rust-ast-visitor.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace AST { + +void +PointerVisitor::visit (AST::Crate &crate) +{ + visit_inner_attrs (crate); + for (auto &item : crate.items) + reseat (item); +} + +void +PointerVisitor::visit (AST::AttrInputMetaItemContainer &input) +{ + // FIXME: I think we might actually have to reseat sub-items for macro + // invocations within attributes correct? + + for (auto &item : input.get_items ()) + visit (item); +} + +void +PointerVisitor::visit (AST::IdentifierExpr &ident_expr) +{ + visit_outer_attrs (ident_expr); +} + +void +PointerVisitor::visit (AST::LifetimeParam &lifetime_param) +{ + visit_outer_attrs (lifetime_param); + + // Nothing to do for lifetimes right? +} + +void +PointerVisitor::visit (AST::ConstGenericParam &const_param) +{ + visit_outer_attrs (const_param); + if (const_param.has_type ()) + reseat (const_param.get_type_ptr ()); + + if (const_param.has_default_value ()) + visit (const_param.get_default_value_unchecked ()); +} + +void +PointerVisitor::visit (AST::PathInExpression &path) +{ + visit_outer_attrs (path); + + if (!path.is_lang_item ()) + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (GenericArgsBinding &binding) +{ + reseat (binding.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::TypePathSegmentGeneric &segment) +{ + if (segment.has_generic_args ()) + visit (segment.get_generic_args ()); +} + +void +PointerVisitor::visit (AST::TypePathFunction &tpf) +{ + for (auto &input : tpf.get_params ()) + reseat (input); + if (tpf.has_return_type ()) + reseat (tpf.get_return_type_ptr ()); +} + +void +PointerVisitor::visit (AST::TypePathSegmentFunction &segment) +{ + // FIXME: No reseating here correct? No macros possible or desugar? + visit (segment.get_type_path_function ()); + visit (segment.get_ident_segment ()); +} + +void +PointerVisitor::visit (AST::GenericArgs &args) +{ + // Nothing to do for lifetimes? + // for (auto &lifetime : args.get_lifetime_args ()) + // reseat (lifetime); + + // FIXME: Actually this can probably be a macro invocation, so we need to + // reseat them? + for (auto &generic : args.get_generic_args ()) + visit (generic); + + for (auto &binding : args.get_binding_args ()) + visit (binding); +} + +void +PointerVisitor::visit (AST::PathExprSegment &segment) +{ + visit (segment.get_ident_segment ()); + if (segment.has_generic_args ()) + visit (segment.get_generic_args ()); +} +void +PointerVisitor::visit (AST::TypePath &path) +{ + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (AST::QualifiedPathInExpression &path) +{ + visit_outer_attrs (path); + visit (path.get_qualified_path_type ()); + + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (AST::QualifiedPathType &path) +{ + reseat (path.get_type_ptr ()); + if (path.has_as_clause ()) + visit (path.get_as_type_path ()); +} + +void +PointerVisitor::visit (AST::QualifiedPathInType &path) +{ + visit (path.get_qualified_path_type ()); + visit (path.get_associated_segment ()); + + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (AST::LiteralExpr &expr) +{ + visit_outer_attrs (expr); +} + +void +PointerVisitor::visit (AST::AttrInputLiteral &attr_input) +{ + visit (attr_input.get_literal ()); +} + +void +PointerVisitor::visit (AST::AttrInputMacro &attr_input) +{ + visit (attr_input.get_macro ()); +} + +void +PointerVisitor::visit (AST::MetaItemLitExpr &meta_item) +{ + visit (meta_item.get_literal ()); +} + +void +PointerVisitor::visit (AST::SimplePath &path) +{ + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (AST::MetaItemPathExpr &meta_item) +{ + visit (meta_item.get_path ()); + reseat (meta_item.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::BorrowExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_borrowed_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::DereferenceExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_dereferenced_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ErrorPropagationExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_propagating_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::NegationExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_negated_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ArithmeticOrLogicalExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ComparisonExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::LazyBooleanExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TypeCastExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_casted_expr_ptr ()); + reseat (expr.get_type_to_cast_to_ptr ()); +} + +void +PointerVisitor::visit (AST::AssignmentExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::CompoundAssignmentExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::GroupedExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + reseat (expr.get_expr_in_parens_ptr ()); +} + +void +PointerVisitor::visit (AST::ArrayElemsValues &elems) +{ + for (auto &value : elems.get_values ()) + reseat (value); +} + +void +PointerVisitor::visit (AST::ArrayElemsCopied &elems) +{ + reseat (elems.get_elem_to_copy_ptr ()); + reseat (elems.get_num_copies_ptr ()); +} + +void +PointerVisitor::visit (AST::ArrayExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + visit (expr.get_array_elems ()); +} + +void +PointerVisitor::visit (AST::ArrayIndexExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_array_expr_ptr ()); + reseat (expr.get_index_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TupleExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + for (auto &elem : expr.get_tuple_elems ()) + reseat (elem); +} + +void +PointerVisitor::visit (AST::TupleIndexExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_tuple_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::StructExprStruct &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + visit (expr.get_struct_name ()); +} + +void +PointerVisitor::visit (AST::StructExprFieldIdentifier &field) +{} + +void +PointerVisitor::visit (AST::StructExprFieldIdentifierValue &field) +{ + reseat (field.get_value_ptr ()); +} + +void +PointerVisitor::visit (AST::StructExprFieldIndexValue &field) +{ + reseat (field.get_value_ptr ()); +} + +void +PointerVisitor::visit (AST::StructBase &base) +{ + reseat (base.get_base_struct_ptr ()); +} + +void +PointerVisitor::visit (AST::StructExprStructFields &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + visit (expr.get_struct_name ()); + if (expr.has_struct_base ()) + visit (expr.get_struct_base ()); + for (auto &field : expr.get_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::StructExprStructBase &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + visit (expr.get_struct_name ()); + visit (expr.get_struct_base ()); +} + +void +PointerVisitor::visit (AST::CallExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_function_expr_ptr ()); + for (auto ¶m : expr.get_params ()) + reseat (param); +} + +void +PointerVisitor::visit (AST::MethodCallExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_receiver_expr_ptr ()); + visit (expr.get_method_name ()); + for (auto ¶m : expr.get_params ()) + reseat (param); +} + +void +PointerVisitor::visit (AST::FieldAccessExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_receiver_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ClosureExprInner &expr) +{ + visit_outer_attrs (expr); + + // TODO: Actually we need to handle macro invocations as closure parameters so + // this needs to be a reseat + for (auto ¶m : expr.get_params ()) + visit (param); + + reseat (expr.get_definition_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::BlockExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + + if (expr.has_label ()) + visit (expr.get_label ()); + + for (auto &stmt : expr.get_statements ()) + reseat (stmt); + + if (expr.has_tail_expr ()) + reseat (expr.get_tail_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ConstBlock &expr) +{ + visit (expr.get_const_expr ()); +} + +void +PointerVisitor::visit (AST::AnonConst &expr) +{ + if (!expr.is_deferred ()) + reseat (expr.get_inner_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ClosureExprInnerTyped &expr) +{ + visit_outer_attrs (expr); + + // TODO: Same as ClosureExprInner + for (auto ¶m : expr.get_params ()) + visit (param); + + reseat (expr.get_return_type_ptr ()); + + reseat (expr.get_definition_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ClosureParam ¶m) +{ + visit_outer_attrs (param); + reseat (param.get_pattern_ptr ()); + if (param.has_type_given ()) + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::ContinueExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_label ()) + visit (expr.get_label_unchecked ()); +} + +void +PointerVisitor::visit (AST::BreakExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_label ()) + visit (expr.get_label_unchecked ()); + + if (expr.has_break_expr ()) + reseat (expr.get_break_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeFromToExpr &expr) +{ + reseat (expr.get_from_expr_ptr ()); + reseat (expr.get_to_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeFromExpr &expr) +{ + reseat (expr.get_from_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeToExpr &expr) +{ + reseat (expr.get_to_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeFullExpr &expr) +{} + +void +PointerVisitor::visit (AST::RangeFromToInclExpr &expr) +{ + reseat (expr.get_from_expr_ptr ()); + reseat (expr.get_to_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeToInclExpr &expr) +{ + reseat (expr.get_to_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ReturnExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_returned_expr ()) + reseat (expr.get_returned_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TryExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_block_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::BoxExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_boxed_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::UnsafeBlockExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_block_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::LoopLabel &label) +{ + visit (label.get_lifetime ()); +} + +void +PointerVisitor::visit (AST::LoopExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + reseat (expr.get_loop_block_ptr ()); +} + +void +PointerVisitor::visit (AST::WhileLoopExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + reseat (expr.get_predicate_expr_ptr ()); + reseat (expr.get_loop_block_ptr ()); +} + +void +PointerVisitor::visit (AST::WhileLetLoopExpr &expr) +{ + visit_outer_attrs (expr); + for (auto &pattern : expr.get_patterns ()) + reseat (pattern); + + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + + reseat (expr.get_scrutinee_expr_ptr ()); + reseat (expr.get_loop_block_ptr ()); +} + +void +PointerVisitor::visit (AST::ForLoopExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_pattern_ptr ()); + reseat (expr.get_iterator_expr_ptr ()); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + reseat (expr.get_loop_block_ptr ()); +} + +void +PointerVisitor::visit (AST::IfExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_condition_expr_ptr ()); + visit (expr.get_if_block ()); +} + +void +PointerVisitor::visit (AST::IfExprConseqElse &expr) +{ + visit (reinterpret_cast<AST::IfExpr &> (expr)); + visit (expr.get_else_block ()); +} + +void +PointerVisitor::visit (AST::IfLetExpr &expr) +{ + visit_outer_attrs (expr); + for (auto &pattern : expr.get_patterns ()) + reseat (pattern); + reseat (expr.get_value_expr_ptr ()); + visit (expr.get_if_block ()); +} + +void +PointerVisitor::visit (AST::IfLetExprConseqElse &expr) +{ + visit (reinterpret_cast<AST::IfLetExpr &> (expr)); + visit (expr.get_else_block ()); +} + +void +PointerVisitor::visit (AST::MatchArm &arm) +{ + visit_outer_attrs (arm); + for (auto &pattern : arm.get_patterns ()) + reseat (pattern); + if (arm.has_match_arm_guard ()) + reseat (arm.get_guard_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::MatchCase &arm) +{ + visit (arm.get_arm ()); + reseat (arm.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::MatchExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + reseat (expr.get_scrutinee_expr_ptr ()); + for (auto &arm : expr.get_match_cases ()) + visit (arm); +} + +void +PointerVisitor::visit (AST::AwaitExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_awaited_expr ()); +} + +void +PointerVisitor::visit (AST::AsyncBlockExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_block_expr ()); +} + +void +PointerVisitor::visit (AST::InlineAsm &expr) +{ + visit_outer_attrs (expr); + using RegisterType = AST::InlineAsmOperand::RegisterType; + for (auto &operand : expr.get_operands ()) + { + switch (operand.get_register_type ()) + { + case RegisterType::In: + { + reseat (operand.get_in ().expr); + break; + } + case RegisterType::Out: + { + reseat (operand.get_out ().expr); + break; + } + case RegisterType::InOut: + { + reseat (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: + { + auto split = operand.get_split_in_out (); + reseat (split.in_expr); + reseat (split.out_expr); + break; + } + case RegisterType::Const: + { + reseat (operand.get_const ().anon_const.get_inner_expr_ptr ()); + break; + } + case RegisterType::Sym: + { + reseat (operand.get_sym ().expr); + break; + } + case RegisterType::Label: + { + reseat (operand.get_label ().expr); + break; + } + } + } +} + +void +PointerVisitor::visit (AST::LlvmInlineAsm &expr) +{ + for (auto &output : expr.get_outputs ()) + reseat (output.expr); + + for (auto &input : expr.get_inputs ()) + reseat (input.expr); +} + +void +PointerVisitor::visit (AST::TypeParam ¶m) +{ + visit_outer_attrs (param); + // FIXME: Can we do macro expansion here? + for (auto &bound : param.get_type_param_bounds ()) + visit (bound); + if (param.has_type ()) + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::LifetimeWhereClauseItem &item) +{ + visit (item.get_lifetime ()); + for (auto &bound : item.get_lifetime_bounds ()) + visit (bound); +} + +void +PointerVisitor::visit (AST::TypeBoundWhereClauseItem &item) +{ + for (auto &lifetime : item.get_for_lifetimes ()) + visit (lifetime); + reseat (item.get_type_ptr ()); + // FIXME: Likewise? + for (auto ¶m : item.get_type_param_bounds ()) + visit (param); +} + +void +PointerVisitor::visit (AST::Visibility &vis) +{ + if (vis.has_path ()) + visit (vis.get_path ()); +} + +void +PointerVisitor::visit (AST::WhereClause &where) +{ + for (auto &item : where.get_items ()) + visit (item); +} + +void +PointerVisitor::visit (AST::FunctionParam ¶m) +{ + visit_outer_attrs (param); + if (param.has_name ()) + reseat (param.get_pattern_ptr ()); + + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::SelfParam ¶m) +{ + visit_outer_attrs (param); + + if (param.has_lifetime ()) + visit (param.get_lifetime ()); + + if (param.has_type ()) + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::Module &module) +{ + visit_outer_attrs (module); + visit (module.get_visibility ()); + visit_inner_attrs (module); + for (auto &item : module.get_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::ExternCrate &crate) +{ + visit_outer_attrs (crate); + visit (crate.get_visibility ()); +} + +void +PointerVisitor::visit (AST::UseTreeGlob &use_tree) +{ + visit (use_tree.get_path ()); +} + +void +PointerVisitor::visit (AST::UseTreeList &use_tree) +{ + visit (use_tree.get_path ()); +} + +void +PointerVisitor::visit (AST::UseTreeRebind &use_tree) +{ + visit (use_tree.get_path ()); +} + +void +PointerVisitor::visit (AST::UseDeclaration &use_decl) +{ + visit (use_decl.get_visibility ()); + visit (use_decl.get_tree ()); +} + +void +PointerVisitor::visit_function_params (AST::Function &function) +{ + for (auto ¶m : function.get_function_params ()) + visit (param); +} + +void +PointerVisitor::visit (AST::Function &function) +{ + visit_outer_attrs (function); + visit (function.get_visibility ()); + visit (function.get_qualifiers ()); + for (auto &generic : function.get_generic_params ()) + visit (generic); + + visit_function_params (function); + + if (function.has_return_type ()) + reseat (function.get_return_type_ptr ()); + if (function.has_where_clause ()) + visit (function.get_where_clause ()); + if (function.has_body ()) + reseat (*function.get_definition ()); +} + +void +PointerVisitor::visit (AST::TypeAlias &type_alias) +{ + visit_outer_attrs (type_alias); + visit (type_alias.get_visibility ()); + for (auto &generic : type_alias.get_generic_params ()) + visit (generic); + if (type_alias.has_where_clause ()) + visit (type_alias.get_where_clause ()); + reseat (type_alias.get_type_aliased_ptr ()); +} + +void +PointerVisitor::visit (AST::StructField &field) +{ + visit_outer_attrs (field); + visit (field.get_visibility ()); + reseat (field.get_field_type_ptr ()); +} + +void +PointerVisitor::visit (AST::StructStruct &struct_item) +{ + visit_outer_attrs (struct_item); + visit (struct_item.get_visibility ()); + for (auto &generic : struct_item.get_generic_params ()) + visit (generic); + if (struct_item.has_where_clause ()) + visit (struct_item.get_where_clause ()); + for (auto &field : struct_item.get_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::TupleField &field) +{ + visit_outer_attrs (field); + visit (field.get_visibility ()); + reseat (field.get_field_type_ptr ()); +} + +void +PointerVisitor::visit (AST::TupleStruct &tuple_struct) +{ + visit_outer_attrs (tuple_struct); + visit (tuple_struct.get_visibility ()); + for (auto &generic : tuple_struct.get_generic_params ()) + visit (generic); + if (tuple_struct.has_where_clause ()) + visit (tuple_struct.get_where_clause ()); + for (auto &field : tuple_struct.get_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::EnumItem &item) +{ + visit_outer_attrs (item); + visit (item.get_visibility ()); +} + +void +PointerVisitor::visit (AST::EnumItemTuple &item) +{ + PointerVisitor::visit (static_cast<EnumItem &> (item)); + for (auto &field : item.get_tuple_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::EnumItemStruct &item) +{ + PointerVisitor::visit (static_cast<EnumItem &> (item)); + for (auto &field : item.get_struct_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::EnumItemDiscriminant &item) +{ + PointerVisitor::visit (static_cast<EnumItem &> (item)); + reseat (item.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::Enum &enum_item) +{ + visit_outer_attrs (enum_item); + visit (enum_item.get_visibility ()); + for (auto &generic : enum_item.get_generic_params ()) + visit (generic); + if (enum_item.has_where_clause ()) + visit (enum_item.get_where_clause ()); + for (auto &item : enum_item.get_variants ()) + visit (item); +} + +void +PointerVisitor::visit (AST::Union &union_item) +{ + visit_outer_attrs (union_item); + visit (union_item.get_visibility ()); + for (auto &generic : union_item.get_generic_params ()) + visit (generic); + if (union_item.has_where_clause ()) + visit (union_item.get_where_clause ()); + for (auto &variant : union_item.get_variants ()) + visit (variant); +} + +void +PointerVisitor::visit (AST::ConstantItem &const_item) +{ + visit_outer_attrs (const_item); + visit (const_item.get_visibility ()); + reseat (const_item.get_type_ptr ()); + if (const_item.has_expr ()) + reseat (const_item.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::StaticItem &static_item) +{ + visit_outer_attrs (static_item); + visit (static_item.get_visibility ()); + reseat (static_item.get_type_ptr ()); + reseat (static_item.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TraitItemType &item) +{ + visit_outer_attrs (item); + for (auto &bound : item.get_type_param_bounds ()) + visit (bound); +} + +void +PointerVisitor::visit (AST::Trait &trait) +{ + visit_outer_attrs (trait); + visit (trait.get_visibility ()); + + visit_inner_attrs (trait); + + visit (trait.get_implicit_self ()); + + for (auto &generic : trait.get_generic_params ()) + visit (generic); + + if (trait.has_where_clause ()) + visit (trait.get_where_clause ()); + + for (auto &bound : trait.get_type_param_bounds ()) + visit (bound); + + for (auto &item : trait.get_trait_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::InherentImpl &impl) +{ + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + reseat (impl.get_type_ptr ()); + visit_inner_attrs (impl); + for (auto &item : impl.get_impl_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::TraitImpl &impl) +{ + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + reseat (impl.get_type_ptr ()); + visit (impl.get_trait_path ()); + visit_inner_attrs (impl); + for (auto &item : impl.get_impl_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::ExternalTypeItem &item) +{ + visit_outer_attrs (item); + visit (item.get_visibility ()); +} + +void +PointerVisitor::visit (AST::ExternalStaticItem &item) +{ + visit_outer_attrs (item); + visit (item.get_visibility ()); + reseat (item.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::ExternBlock &block) +{ + visit_outer_attrs (block); + visit (block.get_visibility ()); + visit_inner_attrs (block); + for (auto &item : block.get_extern_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::MacroMatchFragment &match) +{} + +void +PointerVisitor::visit (AST::MacroMatchRepetition &match) +{ + for (auto &m : match.get_matches ()) + visit (m); +} + +void +PointerVisitor::visit (AST::MacroMatcher &matcher) +{ + for (auto &m : matcher.get_matches ()) + visit (m); +} + +void +PointerVisitor::visit (AST::MacroTranscriber &transcriber) +{ + visit (transcriber.get_token_tree ()); +} + +void +PointerVisitor::visit (AST::MacroRule &rule) +{ + visit (rule.get_matcher ()); + visit (rule.get_transcriber ()); +} + +void +PointerVisitor::visit (AST::MacroRulesDefinition &rules_def) +{ + visit_outer_attrs (rules_def); + for (auto &rule : rules_def.get_macro_rules ()) + visit (rule); +} + +void +PointerVisitor::visit (AST::MacroInvocData &data) +{ + visit (data.get_path ()); + visit (data.get_delim_tok_tree ()); +} + +void +PointerVisitor::visit (AST::MacroInvocation ¯o_invoc) +{ + visit_outer_attrs (macro_invoc); + visit (macro_invoc.get_invoc_data ()); +} + +void +PointerVisitor::visit (AST::MetaItemPath &meta_item) +{ + visit (meta_item.get_path ()); +} + +void +PointerVisitor::visit (AST::MetaItemSeq &meta_item) +{ + visit (meta_item.get_path ()); + for (auto &inner : meta_item.get_seq ()) + visit (inner); +} + +void +PointerVisitor::visit (AST::MetaListPaths &meta_item) +{ + for (auto &path : meta_item.get_paths ()) + visit (path); +} + +void +PointerVisitor::visit (AST::MetaListNameValueStr &meta_item) +{ + for (auto &str : meta_item.get_values ()) + visit (str); +} + +void +PointerVisitor::visit (AST::IdentifierPattern &pattern) +{ + if (pattern.has_subpattern ()) + reseat (pattern.get_subpattern_ptr ()); +} + +void +PointerVisitor::visit (AST::RangePatternBoundPath &bound) +{ + visit (bound.get_path ()); +} + +void +PointerVisitor::visit (AST::RangePatternBoundQualPath &bound) +{ + visit (bound.get_qualified_path ()); +} + +void +PointerVisitor::visit (AST::RangePattern &pattern) +{ + // FIXME: So should this be reseat() instead? Can we have macro invocations as + // patterns in range patterns? + if (pattern.get_has_lower_bound ()) + visit (pattern.get_lower_bound ()); + if (pattern.get_has_upper_bound ()) + visit (pattern.get_upper_bound ()); +} + +void +PointerVisitor::visit (AST::ReferencePattern &pattern) +{ + reseat (pattern.get_referenced_pattern_ptr ()); +} + +void +PointerVisitor::visit (AST::StructPatternFieldTuplePat &field) +{ + visit_outer_attrs (field); + reseat (field.get_index_pattern_ptr ()); +} + +void +PointerVisitor::visit (AST::StructPatternFieldIdentPat &field) +{ + visit_outer_attrs (field); + reseat (field.get_ident_pattern_ptr ()); +} + +void +PointerVisitor::visit (AST::StructPatternFieldIdent &field) +{ + visit_outer_attrs (field); +} + +void +PointerVisitor::visit (AST::StructPatternElements &spe) +{ + for (auto &field : spe.get_struct_pattern_fields ()) + visit (field); + for (auto &attribute : spe.get_etc_outer_attrs ()) + visit (attribute); +} + +void +PointerVisitor::visit (AST::StructPattern &pattern) +{ + visit (pattern.get_path ()); + visit (pattern.get_struct_pattern_elems ()); +} + +void +PointerVisitor::visit (AST::TupleStructItemsNoRest &tuple_items) +{ + for (auto &pattern : tuple_items.get_patterns ()) + reseat (pattern); +} + +void +PointerVisitor::visit (AST::TupleStructItemsHasRest &tuple_items) +{ + for (auto &lower : tuple_items.get_lower_patterns ()) + reseat (lower); + for (auto &upper : tuple_items.get_upper_patterns ()) + reseat (upper); +} + +void +PointerVisitor::visit (AST::TupleStructPattern &pattern) +{ + visit (pattern.get_path ()); + visit (pattern.get_items ()); +} + +void +PointerVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items) +{ + for (auto &pattern : tuple_items.get_patterns ()) + reseat (pattern); +} + +void +PointerVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items) +{ + for (auto &lower : tuple_items.get_lower_patterns ()) + reseat (lower); + for (auto &upper : tuple_items.get_upper_patterns ()) + reseat (upper); +} + +void +PointerVisitor::visit (AST::TuplePattern &pattern) +{ + visit (pattern.get_items ()); +} + +void +PointerVisitor::visit (AST::GroupedPattern &pattern) +{ + reseat (pattern.get_pattern_in_parens_ptr ()); +} + +void +PointerVisitor::visit (AST::SlicePatternItemsNoRest &items) +{ + for (auto &item : items.get_patterns ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::SlicePatternItemsHasRest &items) +{ + for (auto &item : items.get_lower_patterns ()) + reseat (item); + for (auto &item : items.get_upper_patterns ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::SlicePattern &pattern) +{ + visit (pattern.get_items ()); +} + +void +PointerVisitor::visit (AST::AltPattern &pattern) +{ + for (auto &alt : pattern.get_alts ()) + reseat (alt); +} + +void +PointerVisitor::visit (AST::EmptyStmt &stmt) +{} + +void +PointerVisitor::visit (AST::LetStmt &stmt) +{ + visit_outer_attrs (stmt); + reseat (stmt.get_pattern_ptr ()); + if (stmt.has_type ()) + reseat (stmt.get_type_ptr ()); + if (stmt.has_init_expr ()) + reseat (stmt.get_init_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ExprStmt &stmt) +{ + reseat (stmt.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TraitBound &bound) +{ + for (auto &lifetime : bound.get_for_lifetimes ()) + visit (lifetime); + visit (bound.get_type_path ()); +} + +void +PointerVisitor::visit (AST::ImplTraitType &type) +{ + for (auto &bound : type.get_type_param_bounds ()) + visit (bound); +} + +void +PointerVisitor::visit (AST::TraitObjectType &type) +{ + for (auto &bound : type.get_type_param_bounds ()) + visit (bound); +} + +void +PointerVisitor::visit (AST::ParenthesisedType &type) +{ + reseat (type.get_type_in_parens ()); +} + +void +PointerVisitor::visit (AST::ImplTraitTypeOneBound &type) +{ + // FIXME: Do we need to reseat here? + visit (type.get_trait_bound ()); +} + +void +PointerVisitor::visit (AST::TraitObjectTypeOneBound &type) +{ + // FIXME: Do we need to reseat here? + visit (type.get_trait_bound ()); +} + +void +PointerVisitor::visit (AST::TupleType &type) +{ + for (auto &elem : type.get_elems ()) + reseat (elem); +} + +void +PointerVisitor::visit (AST::NeverType &type) +{} + +void +PointerVisitor::visit (AST::RawPointerType &type) +{ + reseat (type.get_type_pointed_to_ptr ()); +} + +void +PointerVisitor::visit (AST::ReferenceType &type) +{ + visit (type.get_lifetime ()); + reseat (type.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::ArrayType &type) +{ + reseat (type.get_elem_type_ptr ()); + visit (type.get_size_expr ()); +} + +void +PointerVisitor::visit (AST::SliceType &type) +{ + reseat (type.get_elem_type_ptr ()); +} + +void +PointerVisitor::visit (AST::InferredType &type) +{} + +void +PointerVisitor::visit (AST::MaybeNamedParam ¶m) +{ + visit_outer_attrs (param); + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::BareFunctionType &type) +{ + for (auto &lifetime : type.get_for_lifetimes ()) + visit (lifetime); + visit (type.get_function_qualifiers ()); + for (auto ¶m : type.get_function_params ()) + visit (param); + if (type.is_variadic ()) + for (auto attr : type.get_variadic_attr ()) + visit (attr); + if (type.has_return_type ()) + reseat (type.get_return_type_ptr ()); +} + +void +PointerVisitor::visit (AST::FormatArgs &) +{ + // FIXME: Do we have anything to do? any subnodes to visit? Probably, right? +} + +void +PointerVisitor::visit (AST::OffsetOf &offset_of) +{ + reseat (offset_of.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::VariadicParam ¶m) +{ + if (param.has_pattern ()) + reseat (param.get_pattern_ptr ()); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.h b/gcc/rust/ast/rust-ast-pointer-visitor.h new file mode 100644 index 0000000..8c12b4e --- /dev/null +++ b/gcc/rust/ast/rust-ast-pointer-visitor.h @@ -0,0 +1,234 @@ +// 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/>. + +#ifndef RUST_AST_POINTER_VISITOR_H +#define RUST_AST_POINTER_VISITOR_H + +#include "rust-ast-visitor.h" +#include "rust-ast.h" +#include "rust-item.h" + +namespace Rust { +namespace AST { + +/** + * Regular AST visitor which may reseat pointers when necessary. + */ +class PointerVisitor : public DefaultASTVisitor +{ +public: + using DefaultASTVisitor::visit; + + virtual void reseat (std::unique_ptr<AST::Expr> &ptr) { visit (ptr); } + virtual void reseat (std::unique_ptr<AST::BlockExpr> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::Stmt> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::Item> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::AssociatedItem> &ptr) + { + visit (ptr); + } + + virtual void reseat (std::unique_ptr<AST::ExternalItem> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::Type> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::TypeNoBounds> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::Pattern> &ptr) { visit (ptr); } + + void visit (AST::Crate &crate) override; + void visit (AST::AttrInputMetaItemContainer &input) override; + void visit (AST::IdentifierExpr &ident_expr) override; + void visit (AST::LifetimeParam &lifetime_param) override; + void visit (AST::ConstGenericParam &const_param) override; + void visit (AST::PathInExpression &path) override; + void visit (GenericArgsBinding &binding) override; + void visit (AST::TypePathSegmentGeneric &segment) override; + void visit (AST::TypePathFunction &tpf) override; + void visit (AST::TypePathSegmentFunction &segment) override; + void visit (AST::GenericArgs &args) override; + void visit (AST::PathExprSegment &segment) override; + void visit (AST::TypePath &path) override; + void visit (AST::QualifiedPathInExpression &path) override; + void visit (AST::QualifiedPathType &path) override; + void visit (AST::QualifiedPathInType &path) override; + void visit (AST::LiteralExpr &expr) override; + void visit (AST::AttrInputLiteral &attr_input) override; + void visit (AST::AttrInputMacro &attr_input) override; + void visit (AST::MetaItemLitExpr &meta_item) override; + void visit (AST::SimplePath &path) override; + void visit (AST::MetaItemPathExpr &meta_item) override; + void visit (AST::BorrowExpr &expr) override; + void visit (AST::DereferenceExpr &expr) override; + void visit (AST::ErrorPropagationExpr &expr) override; + void visit (AST::NegationExpr &expr) override; + void visit (AST::ArithmeticOrLogicalExpr &expr) override; + void visit (AST::ComparisonExpr &expr) override; + void visit (AST::LazyBooleanExpr &expr) override; + void visit (AST::TypeCastExpr &expr) override; + void visit (AST::AssignmentExpr &expr) override; + void visit (AST::CompoundAssignmentExpr &expr) override; + void visit (AST::GroupedExpr &expr) override; + void visit (AST::ArrayElemsValues &elems) override; + void visit (AST::ArrayElemsCopied &elems) override; + void visit (AST::ArrayExpr &expr) override; + void visit (AST::ArrayIndexExpr &expr) override; + void visit (AST::TupleExpr &expr) override; + void visit (AST::TupleIndexExpr &expr) override; + void visit (AST::StructExprStruct &expr) override; + void visit (AST::StructExprFieldIdentifier &field) override; + void visit (AST::StructExprFieldIdentifierValue &field) override; + void visit (AST::StructExprFieldIndexValue &field) override; + void visit (AST::StructBase &base) override; + void visit (AST::StructExprStructFields &expr) override; + void visit (AST::StructExprStructBase &expr) override; + void visit (AST::CallExpr &expr) override; + void visit (AST::MethodCallExpr &expr) override; + void visit (AST::FieldAccessExpr &expr) override; + void visit (AST::ClosureExprInner &expr) override; + void visit (AST::BlockExpr &expr) override; + void visit (AST::ConstBlock &expr) override; + void visit (AST::AnonConst &expr) override; + void visit (AST::ClosureExprInnerTyped &expr) override; + void visit (AST::ClosureParam ¶m) override; + void visit (AST::ContinueExpr &expr) override; + void visit (AST::BreakExpr &expr) override; + void visit (AST::RangeFromToExpr &expr) override; + void visit (AST::RangeFromExpr &expr) override; + void visit (AST::RangeToExpr &expr) override; + void visit (AST::RangeFullExpr &expr) override; + void visit (AST::RangeFromToInclExpr &expr) override; + void visit (AST::RangeToInclExpr &expr) override; + void visit (AST::ReturnExpr &expr) override; + void visit (AST::TryExpr &expr) override; + void visit (AST::BoxExpr &expr) override; + void visit (AST::UnsafeBlockExpr &expr) override; + void visit (AST::LoopLabel &label) override; + void visit (AST::LoopExpr &expr) override; + void visit (AST::WhileLoopExpr &expr) override; + void visit (AST::WhileLetLoopExpr &expr) override; + void visit (AST::ForLoopExpr &expr) override; + void visit (AST::IfExpr &expr) override; + void visit (AST::IfExprConseqElse &expr) override; + void visit (AST::IfLetExpr &expr) override; + void visit (AST::IfLetExprConseqElse &expr) override; + void visit (AST::MatchArm &arm) override; + void visit (AST::MatchCase &arm) override; + void visit (AST::MatchExpr &expr) override; + void visit (AST::AwaitExpr &expr) override; + void visit (AST::AsyncBlockExpr &expr) override; + void visit (AST::InlineAsm &expr) override; + void visit (AST::LlvmInlineAsm &expr) override; + void visit (AST::TypeParam ¶m) override; + void visit (AST::LifetimeWhereClauseItem &item) override; + void visit (AST::TypeBoundWhereClauseItem &item) override; + void visit (AST::Visibility &vis) override; + void visit (AST::WhereClause &where) override; + void visit (AST::FunctionParam ¶m) override; + void visit (AST::SelfParam ¶m) override; + void visit (AST::Module &module) override; + void visit (AST::ExternCrate &crate) override; + void visit (AST::UseTreeGlob &use_tree) override; + void visit (AST::UseTreeList &use_tree) override; + void visit (AST::UseTreeRebind &use_tree) override; + void visit (AST::UseDeclaration &use_decl) override; + void visit_function_params (AST::Function &function) override; + void visit (AST::Function &function) override; + void visit (AST::TypeAlias &type_alias) override; + void visit (AST::StructField &field) override; + void visit (AST::StructStruct &struct_item) override; + void visit (AST::TupleField &field) override; + void visit (AST::TupleStruct &tuple_struct) override; + void visit (AST::EnumItem &item) override; + void visit (AST::EnumItemTuple &item) override; + void visit (AST::EnumItemStruct &item) override; + void visit (AST::EnumItemDiscriminant &item) override; + void visit (AST::Enum &enum_item) override; + void visit (AST::Union &union_item) override; + void visit (AST::ConstantItem &const_item) override; + void visit (AST::StaticItem &static_item) override; + void visit (AST::TraitItemType &item) override; + void visit (AST::Trait &trait) override; + void visit (AST::InherentImpl &impl) override; + void visit (AST::TraitImpl &impl) override; + void visit (AST::ExternalTypeItem &item) override; + void visit (AST::ExternalStaticItem &item) override; + void visit (AST::ExternBlock &block) override; + void visit (AST::MacroMatchFragment &match) override; + void visit (AST::MacroMatchRepetition &match) override; + void visit (AST::MacroMatcher &matcher) override; + void visit (AST::MacroTranscriber &transcriber) override; + void visit (AST::MacroRule &rule) override; + void visit (AST::MacroRulesDefinition &rules_def) override; + void visit (AST::MacroInvocData &data) override; + void visit (AST::MacroInvocation ¯o_invoc) override; + void visit (AST::MetaItemPath &meta_item) override; + void visit (AST::MetaItemSeq &meta_item) override; + void visit (AST::MetaListPaths &meta_item) override; + void visit (AST::MetaListNameValueStr &meta_item) override; + void visit (AST::IdentifierPattern &pattern) override; + void visit (AST::RangePatternBoundPath &bound) override; + void visit (AST::RangePatternBoundQualPath &bound) override; + void visit (AST::RangePattern &pattern) override; + void visit (AST::ReferencePattern &pattern) override; + void visit (AST::StructPatternFieldTuplePat &field) override; + void visit (AST::StructPatternFieldIdentPat &field) override; + void visit (AST::StructPatternFieldIdent &field) override; + void visit (AST::StructPatternElements &spe) override; + void visit (AST::StructPattern &pattern) override; + void visit (AST::TupleStructItemsNoRest &tuple_items) override; + void visit (AST::TupleStructItemsHasRest &tuple_items) override; + void visit (AST::TupleStructPattern &pattern) override; + void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + void visit (AST::TuplePatternItemsHasRest &tuple_items) override; + void visit (AST::TuplePattern &pattern) override; + void visit (AST::GroupedPattern &pattern) override; + void visit (AST::SlicePatternItemsNoRest &items) override; + void visit (AST::SlicePatternItemsHasRest &items) override; + void visit (AST::SlicePattern &pattern) override; + void visit (AST::AltPattern &pattern) override; + void visit (AST::EmptyStmt &stmt) override; + void visit (AST::LetStmt &stmt) override; + void visit (AST::ExprStmt &stmt) override; + void visit (AST::TraitBound &bound) override; + void visit (AST::ImplTraitType &type) override; + void visit (AST::TraitObjectType &type) override; + void visit (AST::ParenthesisedType &type) override; + void visit (AST::ImplTraitTypeOneBound &type) override; + void visit (AST::TraitObjectTypeOneBound &type) override; + void visit (AST::TupleType &type) override; + void visit (AST::NeverType &type) override; + void visit (AST::RawPointerType &type) override; + void visit (AST::ReferenceType &type) override; + void visit (AST::ArrayType &type) override; + void visit (AST::SliceType &type) override; + void visit (AST::InferredType &type) override; + void visit (AST::MaybeNamedParam ¶m) override; + void visit (AST::BareFunctionType &type) override; + void visit (AST::FormatArgs &) override; + void visit (AST::OffsetOf &offset_of) override; + void visit (AST::VariadicParam ¶m) override; +}; + +} // namespace AST +} // namespace Rust + +#endif diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index ba5f87b..afdd2b1 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -19,6 +19,7 @@ #include "rust-ast-visitor.h" #include "rust-ast-full-decls.h" #include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" #include "rust-path.h" #include "rust-token.h" #include "rust-expr.h" @@ -82,7 +83,7 @@ DefaultASTVisitor::visit (AST::ConstGenericParam &const_param) if (const_param.has_type ()) visit (const_param.get_type ()); if (const_param.has_default_value ()) - visit (const_param.get_default_value ()); + visit (const_param.get_default_value_unchecked ()); } void @@ -108,7 +109,8 @@ DefaultASTVisitor::visit (GenericArgsBinding &binding) void DefaultASTVisitor::visit (AST::TypePathSegmentGeneric &segment) { - visit (segment.get_generic_args ()); + if (segment.has_generic_args ()) + visit (segment.get_generic_args ()); } void @@ -222,10 +224,10 @@ DefaultASTVisitor::visit (AST::SimplePath &path) } void -DefaultASTVisitor::visit (AST::MetaItemPathLit &meta_item) +DefaultASTVisitor::visit (AST::MetaItemPathExpr &meta_item) { visit (meta_item.get_path ()); - visit (meta_item.get_literal ()); + visit (meta_item.get_expr ()); } void @@ -246,6 +248,7 @@ void DefaultASTVisitor::visit (AST::ErrorPropagationExpr &expr) { visit_outer_attrs (expr); + visit (expr.get_propagating_expr ()); } void @@ -448,20 +451,38 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr) { visit_outer_attrs (expr); visit_inner_attrs (expr); + + if (expr.has_label ()) + visit (expr.get_label ()); + for (auto &stmt : expr.get_statements ()) visit (stmt); + if (expr.has_tail_expr ()) visit (expr.get_tail_expr ()); } void +DefaultASTVisitor::visit (AST::ConstBlock &expr) +{ + visit (expr.get_const_expr ()); +} + +void +DefaultASTVisitor::visit (AST::AnonConst &expr) +{ + if (!expr.is_deferred ()) + visit (expr.get_inner_expr ()); +} + +void DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr) { visit_outer_attrs (expr); for (auto ¶m : expr.get_params ()) visit (param); visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void @@ -477,7 +498,8 @@ void DefaultASTVisitor::visit (AST::ContinueExpr &expr) { visit_outer_attrs (expr); - visit (expr.get_label ()); + if (expr.has_label ()) + visit (expr.get_label_unchecked ()); } void @@ -485,7 +507,7 @@ DefaultASTVisitor::visit (AST::BreakExpr &expr) { visit_outer_attrs (expr); if (expr.has_label ()) - visit (expr.get_label ()); + visit (expr.get_label_unchecked ()); if (expr.has_break_expr ()) visit (expr.get_break_expr ()); @@ -536,6 +558,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr) } void +DefaultASTVisitor::visit (AST::TryExpr &expr) +{ + visit_outer_attrs (expr); + visit (expr.get_block_expr ()); +} + +void DefaultASTVisitor::visit (AST::BoxExpr &expr) { visit_outer_attrs (expr); @@ -559,7 +588,8 @@ void DefaultASTVisitor::visit (AST::LoopExpr &expr) { visit_outer_attrs (expr); - visit (expr.get_loop_label ()); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); visit (expr.get_loop_block ()); } @@ -567,8 +597,9 @@ void DefaultASTVisitor::visit (AST::WhileLoopExpr &expr) { visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); visit (expr.get_predicate_expr ()); - visit (expr.get_loop_label ()); visit (expr.get_loop_block ()); } @@ -578,8 +609,11 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr) visit_outer_attrs (expr); for (auto &pattern : expr.get_patterns ()) visit (pattern); + + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + visit (expr.get_scrutinee_expr ()); - visit (expr.get_loop_label ()); visit (expr.get_loop_block ()); } @@ -589,7 +623,8 @@ DefaultASTVisitor::visit (AST::ForLoopExpr &expr) visit_outer_attrs (expr); visit (expr.get_pattern ()); visit (expr.get_iterator_expr ()); - visit (expr.get_loop_label ()); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); visit (expr.get_loop_block ()); } @@ -675,33 +710,40 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr) { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { visit (operand.get_in ().expr); break; } - case RegisterType::Out: { + case RegisterType::Out: + { visit (operand.get_out ().expr); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { visit (operand.get_in_out ().expr); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split = operand.get_split_in_out (); visit (split.in_expr); visit (split.out_expr); break; } - case RegisterType::Const: { - visit (operand.get_const ().anon_const.expr); + case RegisterType::Const: + { + visit (operand.get_const ().anon_const.get_inner_expr ()); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { visit (operand.get_sym ().expr); break; } - case RegisterType::Label: { + case RegisterType::Label: + { visit (operand.get_label ().expr); break; } @@ -710,6 +752,16 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr) } void +DefaultASTVisitor::visit (AST::LlvmInlineAsm &expr) +{ + for (auto &output : expr.get_outputs ()) + visit (output.expr); + + for (auto &input : expr.get_inputs ()) + visit (input.expr); +} + +void DefaultASTVisitor::visit (AST::TypeParam ¶m) { visit_outer_attrs (param); @@ -740,7 +792,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item) void DefaultASTVisitor::visit (AST::Visibility &vis) { - visit (vis.get_path ()); + if (vis.has_path ()) + visit (vis.get_path ()); } void @@ -813,10 +866,18 @@ DefaultASTVisitor::visit (AST::UseTreeRebind &use_tree) void DefaultASTVisitor::visit (AST::UseDeclaration &use_decl) { + visit (use_decl.get_visibility ()); visit (use_decl.get_tree ()); } void +DefaultASTVisitor::visit_function_params (AST::Function &function) +{ + for (auto ¶m : function.get_function_params ()) + visit (param); +} + +void DefaultASTVisitor::visit (AST::Function &function) { visit_outer_attrs (function); @@ -824,10 +885,9 @@ DefaultASTVisitor::visit (AST::Function &function) visit (function.get_qualifiers ()); for (auto &generic : function.get_generic_params ()) visit (generic); - if (function.has_self_param ()) - visit (function.get_self_param ()); - for (auto ¶m : function.get_function_params ()) - visit (param); + + visit_function_params (function); + if (function.has_return_type ()) visit (function.get_return_type ()); if (function.has_where_clause ()) @@ -900,7 +960,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item) void DefaultASTVisitor::visit (AST::EnumItemTuple &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (static_cast<EnumItem &> (item)); for (auto &field : item.get_tuple_fields ()) visit (field); } @@ -908,7 +968,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item) void DefaultASTVisitor::visit (AST::EnumItemStruct &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (static_cast<EnumItem &> (item)); for (auto &field : item.get_struct_fields ()) visit (field); } @@ -916,7 +976,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item) void DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (static_cast<EnumItem &> (item)); visit (item.get_expr ()); } @@ -966,15 +1026,6 @@ DefaultASTVisitor::visit (AST::StaticItem &static_item) } void -DefaultASTVisitor::visit (AST::TraitItemConst &item) -{ - visit_outer_attrs (item); - visit (item.get_type ()); - if (item.has_expr ()) - visit (item.get_expr ()); -} - -void DefaultASTVisitor::visit (AST::TraitItemType &item) { visit_outer_attrs (item); @@ -1157,8 +1208,8 @@ DefaultASTVisitor::visit (AST::LiteralPattern &pattern) void DefaultASTVisitor::visit (AST::IdentifierPattern &pattern) { - if (pattern.has_pattern_to_bind ()) - visit (pattern.get_pattern_to_bind ()); + if (pattern.has_subpattern ()) + visit (pattern.get_subpattern ()); } void @@ -1237,14 +1288,14 @@ DefaultASTVisitor::visit (AST::StructPattern &pattern) } void -DefaultASTVisitor::visit (AST::TupleStructItemsNoRange &tuple_items) +DefaultASTVisitor::visit (AST::TupleStructItemsNoRest &tuple_items) { for (auto &pattern : tuple_items.get_patterns ()) visit (pattern); } void -DefaultASTVisitor::visit (AST::TupleStructItemsRange &tuple_items) +DefaultASTVisitor::visit (AST::TupleStructItemsHasRest &tuple_items) { for (auto &lower : tuple_items.get_lower_patterns ()) visit (lower); @@ -1260,14 +1311,14 @@ DefaultASTVisitor::visit (AST::TupleStructPattern &pattern) } void -DefaultASTVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items) +DefaultASTVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items) { for (auto &pattern : tuple_items.get_patterns ()) visit (pattern); } void -DefaultASTVisitor::visit (AST::TuplePatternItemsRanged &tuple_items) +DefaultASTVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items) { for (auto &lower : tuple_items.get_lower_patterns ()) visit (lower); @@ -1288,13 +1339,28 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern) } void -DefaultASTVisitor::visit (AST::SlicePattern &pattern) +DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items) { - for (auto &item : pattern.get_items ()) + for (auto &item : items.get_patterns ()) visit (item); } void +DefaultASTVisitor::visit (AST::SlicePatternItemsHasRest &items) +{ + for (auto &item : items.get_lower_patterns ()) + visit (item); + for (auto &item : items.get_upper_patterns ()) + visit (item); +} + +void +DefaultASTVisitor::visit (AST::SlicePattern &pattern) +{ + visit (pattern.get_items ()); +} + +void DefaultASTVisitor::visit (AST::AltPattern &pattern) { for (auto &alt : pattern.get_alts ()) @@ -1432,6 +1498,12 @@ DefaultASTVisitor::visit (AST::FormatArgs &) } void +DefaultASTVisitor::visit (AST::OffsetOf &offset_of) +{ + visit (offset_of.get_type ()); +} + +void DefaultASTVisitor::visit (AST::VariadicParam ¶m) { if (param.has_pattern ()) diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 51661df..a7a2ac4 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -73,7 +73,7 @@ public: virtual void visit (AttrInputLiteral &attr_input) = 0; virtual void visit (AttrInputMacro &attr_input) = 0; virtual void visit (MetaItemLitExpr &meta_item) = 0; - virtual void visit (MetaItemPathLit &meta_item) = 0; + virtual void visit (MetaItemPathExpr &meta_item) = 0; virtual void visit (BorrowExpr &expr) = 0; virtual void visit (DereferenceExpr &expr) = 0; virtual void visit (ErrorPropagationExpr &expr) = 0; @@ -104,6 +104,8 @@ public: virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (ClosureExprInner &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ClosureExprInnerTyped &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; @@ -114,6 +116,7 @@ public: virtual void visit (RangeFromToInclExpr &expr) = 0; virtual void visit (RangeToInclExpr &expr) = 0; virtual void visit (ReturnExpr &expr) = 0; + virtual void visit (TryExpr &expr) = 0; virtual void visit (BoxExpr &expr) = 0; virtual void visit (UnsafeBlockExpr &expr) = 0; virtual void visit (LoopExpr &expr) = 0; @@ -131,6 +134,7 @@ public: virtual void visit (AwaitExpr &expr) = 0; virtual void visit (AsyncBlockExpr &expr) = 0; virtual void visit (InlineAsm &expr) = 0; + virtual void visit (LlvmInlineAsm &expr) = 0; // rust-item.h virtual void visit (TypeParam ¶m) = 0; @@ -160,7 +164,6 @@ public: virtual void visit (Union &union_item) = 0; virtual void visit (ConstantItem &const_item) = 0; virtual void visit (StaticItem &static_item) = 0; - virtual void visit (TraitItemConst &item) = 0; virtual void visit (TraitItemType &item) = 0; virtual void visit (Trait &trait) = 0; virtual void visit (InherentImpl &impl) = 0; @@ -200,14 +203,16 @@ public: virtual void visit (StructPatternFieldIdent &field) = 0; virtual void visit (StructPattern &pattern) = 0; // virtual void visit(TupleStructItems& tuple_items) = 0; - virtual void visit (TupleStructItemsNoRange &tuple_items) = 0; - virtual void visit (TupleStructItemsRange &tuple_items) = 0; + virtual void visit (TupleStructItemsNoRest &tuple_items) = 0; + virtual void visit (TupleStructItemsHasRest &tuple_items) = 0; virtual void visit (TupleStructPattern &pattern) = 0; // virtual void visit(TuplePatternItems& tuple_items) = 0; - virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0; - virtual void visit (TuplePatternItemsRanged &tuple_items) = 0; + virtual void visit (TuplePatternItemsNoRest &tuple_items) = 0; + virtual void visit (TuplePatternItemsHasRest &tuple_items) = 0; virtual void visit (TuplePattern &pattern) = 0; virtual void visit (GroupedPattern &pattern) = 0; + virtual void visit (SlicePatternItemsNoRest &items) = 0; + virtual void visit (SlicePatternItemsHasRest &items) = 0; virtual void visit (SlicePattern &pattern) = 0; virtual void visit (AltPattern &pattern) = 0; @@ -234,6 +239,7 @@ public: // special AST nodes for certain builtin macros such as `asm!()` virtual void visit (FormatArgs &fmt) = 0; + virtual void visit (OffsetOf &fmt) = 0; // TODO: rust-cond-compilation.h visiting? not currently used }; @@ -241,6 +247,8 @@ public: class DefaultASTVisitor : public ASTVisitor { public: + virtual void visit_function_params (AST::Function &function); + virtual void visit (AST::Crate &crate); virtual void visit (AST::Token &tok) override; @@ -261,7 +269,7 @@ public: virtual void visit (AST::AttrInputLiteral &attr_input) override; virtual void visit (AST::AttrInputMacro &attr_input) override; virtual void visit (AST::MetaItemLitExpr &meta_item) override; - virtual void visit (AST::MetaItemPathLit &meta_item) override; + virtual void visit (AST::MetaItemPathExpr &meta_item) override; virtual void visit (AST::BorrowExpr &expr) override; virtual void visit (AST::DereferenceExpr &expr) override; virtual void visit (AST::ErrorPropagationExpr &expr) override; @@ -290,6 +298,8 @@ public: virtual void visit (AST::FieldAccessExpr &expr) override; virtual void visit (AST::ClosureExprInner &expr) override; virtual void visit (AST::BlockExpr &expr) override; + virtual void visit (AST::AnonConst &expr) override; + virtual void visit (AST::ConstBlock &expr) override; virtual void visit (AST::ClosureExprInnerTyped &expr) override; virtual void visit (AST::ContinueExpr &expr) override; virtual void visit (AST::BreakExpr &expr) override; @@ -300,6 +310,7 @@ public: virtual void visit (AST::RangeFromToInclExpr &expr) override; virtual void visit (AST::RangeToInclExpr &expr) override; virtual void visit (AST::ReturnExpr &expr) override; + virtual void visit (AST::TryExpr &expr) override; virtual void visit (AST::BoxExpr &expr) override; virtual void visit (AST::UnsafeBlockExpr &expr) override; virtual void visit (AST::LoopExpr &expr) override; @@ -314,6 +325,7 @@ public: virtual void visit (AST::AwaitExpr &expr) override; virtual void visit (AST::AsyncBlockExpr &expr) override; virtual void visit (InlineAsm &expr) override; + virtual void visit (LlvmInlineAsm &expr) override; virtual void visit (AST::TypeParam ¶m) override; virtual void visit (AST::LifetimeWhereClauseItem &item) override; @@ -336,7 +348,6 @@ public: virtual void visit (AST::Union &union_item) override; virtual void visit (AST::ConstantItem &const_item) override; virtual void visit (AST::StaticItem &static_item) override; - virtual void visit (AST::TraitItemConst &item) override; virtual void visit (AST::TraitItemType &item) override; virtual void visit (AST::Trait &trait) override; virtual void visit (AST::InherentImpl &impl) override; @@ -368,13 +379,15 @@ public: virtual void visit (AST::StructPatternFieldIdentPat &field) override; virtual void visit (AST::StructPatternFieldIdent &field) override; virtual void visit (AST::StructPattern &pattern) override; - virtual void visit (AST::TupleStructItemsNoRange &tuple_items) override; - virtual void visit (AST::TupleStructItemsRange &tuple_items) override; + virtual void visit (AST::TupleStructItemsNoRest &tuple_items) override; + virtual void visit (AST::TupleStructItemsHasRest &tuple_items) override; virtual void visit (AST::TupleStructPattern &pattern) override; - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override; + virtual void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (AST::TuplePatternItemsHasRest &tuple_items) override; virtual void visit (AST::TuplePattern &pattern) override; virtual void visit (AST::GroupedPattern &pattern) override; + virtual void visit (AST::SlicePatternItemsNoRest &items) override; + virtual void visit (AST::SlicePatternItemsHasRest &items) override; virtual void visit (AST::SlicePattern &pattern) override; virtual void visit (AST::AltPattern &pattern) override; virtual void visit (AST::EmptyStmt &stmt) override; @@ -398,6 +411,7 @@ public: virtual void visit (AST::FunctionParam ¶m) override; virtual void visit (AST::VariadicParam ¶m) override; virtual void visit (AST::FormatArgs &fmt) override; + virtual void visit (AST::OffsetOf &fmt) override; template <typename T> void visit (T &node) { node.accept_vis (*this); } diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index ab82303..851f7ea 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "rust-operators.h" #include "rust-dir-owner.h" #include "rust-attribute-values.h" +#include "rust-macro-invoc-lexer.h" /* Compilation unit used for various AST-related functions that would make * the headers too long if they were defined inline and don't receive any @@ -47,29 +48,33 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other) kind = other.kind; switch (kind) { - case EXPRESSION: + case Kind::Expr: expr = other.expr->clone_expr (); break; - case ITEM: + case Kind::Item: item = other.item->clone_item (); break; - case STMT: + case Kind::Stmt: stmt = other.stmt->clone_stmt (); break; - case EXTERN: + case Kind::Extern: external_item = other.external_item->clone_external_item (); break; - case ASSOC_ITEM: + case Kind::Assoc: assoc_item = other.assoc_item->clone_associated_item (); break; - case TYPE: + case Kind::Type: type = other.type->clone_type (); break; + + case Kind::Pattern: + pattern = other.pattern->clone_pattern (); + break; } } @@ -79,29 +84,33 @@ SingleASTNode::operator= (SingleASTNode const &other) kind = other.kind; switch (kind) { - case EXPRESSION: + case Kind::Expr: expr = other.expr->clone_expr (); break; - case ITEM: + case Kind::Item: item = other.item->clone_item (); break; - case STMT: + case Kind::Stmt: stmt = other.stmt->clone_stmt (); break; - case EXTERN: + case Kind::Extern: external_item = other.external_item->clone_external_item (); break; - case ASSOC_ITEM: + case Kind::Assoc: assoc_item = other.assoc_item->clone_associated_item (); break; - case TYPE: + case Kind::Type: type = other.type->clone_type (); break; + + case Kind::Pattern: + pattern = other.pattern->clone_pattern (); + break; } return *this; } @@ -111,29 +120,33 @@ SingleASTNode::accept_vis (ASTVisitor &vis) { switch (kind) { - case EXPRESSION: + case Kind::Expr: expr->accept_vis (vis); break; - case ITEM: + case Kind::Item: item->accept_vis (vis); break; - case STMT: + case Kind::Stmt: stmt->accept_vis (vis); break; - case EXTERN: + case Kind::Extern: external_item->accept_vis (vis); break; - case ASSOC_ITEM: + case Kind::Assoc: assoc_item->accept_vis (vis); break; - case TYPE: + case Kind::Type: type->accept_vis (vis); break; + + case Kind::Pattern: + pattern->accept_vis (vis); + break; } } @@ -142,18 +155,20 @@ SingleASTNode::is_error () { switch (kind) { - case EXPRESSION: + case Kind::Expr: return expr == nullptr; - case ITEM: + case Kind::Item: return item == nullptr; - case STMT: + case Kind::Stmt: return stmt == nullptr; - case EXTERN: + case Kind::Extern: return external_item == nullptr; - case ASSOC_ITEM: + case Kind::Assoc: return assoc_item == nullptr; - case TYPE: + case Kind::Type: return type == nullptr; + case Kind::Pattern: + return pattern == nullptr; } rust_unreachable (); @@ -165,18 +180,20 @@ SingleASTNode::as_string () const { switch (kind) { - case EXPRESSION: + case Kind::Expr: return "Expr: " + expr->as_string (); - case ITEM: + case Kind::Item: return "Item: " + item->as_string (); - case STMT: + case Kind::Stmt: return "Stmt: " + stmt->as_string (); - case EXTERN: + case Kind::Extern: return "External Item: " + external_item->as_string (); - case ASSOC_ITEM: + case Kind::Assoc: return "Associated Item: " + assoc_item->as_string (); - case TYPE: + case Kind::Type: return "Type: " + type->as_string (); + case Kind::Pattern: + return "Pattern: " + pattern->as_string (); } rust_unreachable (); @@ -231,7 +248,7 @@ Attribute::as_string () const bool Attribute::is_derive () const { - return has_attr_input () && get_path () == "derive"; + return has_attr_input () && get_path () == Values::Attributes::DERIVE_ATTR; } /** @@ -249,27 +266,31 @@ Attribute::get_traits_to_derive () auto &input = get_attr_input (); switch (input.get_attr_input_type ()) { - case AST::AttrInput::META_ITEM: { + case AST::AttrInput::META_ITEM: + { auto &meta = static_cast<AST::AttrInputMetaItemContainer &> (input); for (auto ¤t : meta.get_items ()) { // HACK: Find a better way to achieve the downcast. switch (current->get_kind ()) { - case AST::MetaItemInner::Kind::MetaItem: { + case AST::MetaItemInner::Kind::MetaItem: + { // Let raw pointer go out of scope without freeing, it doesn't // own the data anyway auto meta_item = static_cast<AST::MetaItem *> (current.get ()); switch (meta_item->get_item_kind ()) { - case AST::MetaItem::ItemKind::Path: { + case AST::MetaItem::ItemKind::Path: + { auto path = static_cast<AST::MetaItemPath *> (meta_item); result.push_back (path->get_path ()); } break; - case AST::MetaItem::ItemKind::Word: { + case AST::MetaItem::ItemKind::Word: + { auto word = static_cast<AST::MetaWord *> (meta_item); // Convert current word to path current = std::make_unique<AST::MetaItemPath> ( @@ -283,7 +304,7 @@ Attribute::get_traits_to_derive () break; case AST::MetaItem::ItemKind::ListPaths: case AST::MetaItem::ItemKind::NameValueStr: - case AST::MetaItem::ItemKind::PathLit: + case AST::MetaItem::ItemKind::PathExpr: case AST::MetaItem::ItemKind::Seq: case AST::MetaItem::ItemKind::ListNameValueStr: default: @@ -384,7 +405,7 @@ DelimTokenTree::as_string () const std::string Token::as_string () const { - if (tok_ref->has_str ()) + if (tok_ref->should_have_str ()) { std::string str = tok_ref->get_str (); @@ -620,7 +641,7 @@ ConstantItem::as_string () const { std::string str = VisItem::as_string (); - str += "const " + identifier; + str += "const " + identifier.as_string (); // DEBUG: null pointer check if (type == nullptr) @@ -631,14 +652,8 @@ ConstantItem::as_string () const } str += "\n Type: " + type->as_string (); - // DEBUG: null pointer check - if (const_expr == nullptr) - { - rust_debug ("something really terrible has gone wrong - null " - "pointer expr in const item."); - return "NULL_POINTER_MARK"; - } - str += "\n Expression: " + const_expr->as_string (); + if (has_expr ()) + str += "\n Expression: " + const_expr->as_string (); return str + "\n"; } @@ -782,7 +797,8 @@ UseTreeGlob::as_string () const return "*"; case GLOBAL: return "::*"; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { std::string path_str = path.as_string (); return path_str + "::*"; } @@ -805,7 +821,8 @@ UseTreeList::as_string () const case GLOBAL: path_str = "::{"; break; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { path_str = path.as_string () + "::{"; break; } @@ -1068,7 +1085,7 @@ Function::Function (Function const &other) : VisItem (other), ExternalItem (other.get_node_id ()), qualifiers (other.qualifiers), function_name (other.function_name), where_clause (other.where_clause), locus (other.locus), - is_default (other.is_default), + has_default (other.has_default), is_external_function (other.is_external_function) { // guard to prevent null dereference (always required) @@ -1100,7 +1117,7 @@ Function::operator= (Function const &other) // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; - is_default = other.is_default; + has_default = other.has_default; is_external_function = other.is_external_function; // guard to prevent null dereference (always required) @@ -1272,6 +1289,25 @@ BlockExpr::as_string () const } std::string +AnonConst::as_string () const +{ + std::string str = "AnonConst: "; + + if (kind == AnonConst::Kind::DeferredInference) + str += "_"; + else + str += expr.value ()->as_string (); + + return str; +} + +std::string +ConstBlock::as_string () const +{ + return "ConstBlock: " + expr.as_string (); +} + +std::string TraitImpl::as_string () const { std::string str = VisItem::as_string (); @@ -1619,6 +1655,19 @@ ReturnExpr::as_string () const } std::string +TryExpr::as_string () const +{ + /* TODO: find way to incorporate outer attrs - may have to represent in + * different style (i.e. something more like BorrowExpr: \n outer attrs) */ + + std::string str ("try "); + + str += block_expr->as_string (); + + return str; +} + +std::string RangeToExpr::as_string () const { return ".." + to->as_string (); @@ -1631,7 +1680,7 @@ ContinueExpr::as_string () const std::string str ("continue "); if (has_label ()) - str += label.as_string (); + str += get_label_unchecked ().as_string (); return str; } @@ -2095,7 +2144,7 @@ WhileLoopExpr::as_string () const if (!has_loop_label ()) str += "none"; else - str += loop_label.as_string (); + str += get_loop_label ().as_string (); str += "\n Conditional expr: " + condition->as_string (); @@ -2115,7 +2164,7 @@ WhileLetLoopExpr::as_string () const if (!has_loop_label ()) str += "none"; else - str += loop_label.as_string (); + str += get_loop_label ().as_string (); str += "\n Match arm patterns: "; if (match_arm_patterns.empty ()) @@ -2146,7 +2195,7 @@ LoopExpr::as_string () const if (!has_loop_label ()) str += "none"; else - str += loop_label.as_string (); + str += get_loop_label ().as_string (); str += "\n Loop block: " + loop_block->as_string (); @@ -2183,7 +2232,7 @@ BreakExpr::as_string () const std::string str ("break "); if (has_label ()) - str += label.as_string () + " "; + str += get_label_unchecked ().as_string () + " "; if (has_break_expr ()) str += break_expr->as_string (); @@ -2485,9 +2534,6 @@ MacroMatchRepetition::as_string () const std::string Lifetime::as_string () const { - if (is_error ()) - return "error lifetime"; - switch (lifetime_type) { case NAMED: @@ -2545,7 +2591,7 @@ ForLoopExpr::as_string () const if (!has_loop_label ()) str += "none"; else - str += loop_label.as_string (); + str += get_loop_label ().as_string (); str += "\n Pattern: " + pattern->as_string (); @@ -2612,7 +2658,7 @@ ReferenceType::as_string () const std::string str ("&"); if (has_lifetime ()) - str += lifetime.as_string () + " "; + str += get_lifetime ().as_string () + " "; if (has_mut) str += "mut "; @@ -2717,7 +2763,7 @@ ImplTraitTypeOneBound::as_string () const { std::string str ("ImplTraitTypeOneBound: \n TraitBound: "); - return str + trait_bound.as_string (); + return str + trait_bound->as_string (); } std::string @@ -2739,7 +2785,7 @@ std::string ArrayType::as_string () const { // TODO: rewrite to work with non-linearisable types and exprs - return "[" + elem_type->as_string () + "; " + size->as_string () + "]"; + return "[" + elem_type->as_string () + "; " + size.as_string () + "]"; } std::string @@ -2998,26 +3044,24 @@ ExternalStaticItem::as_string () const } std::string -TraitItemConst::as_string () const -{ - // TODO: rewrite to work with non-linearisable exprs - std::string str = append_attributes (outer_attrs, OUTER); - - str += "\nconst " + name.as_string () + " : " + type->as_string (); - - if (has_expression ()) - str += " = " + expr->as_string (); - - return str; -} - -std::string TraitItemType::as_string () const { std::string str = append_attributes (outer_attrs, OUTER); 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 ()) { @@ -3070,7 +3114,7 @@ SelfParam::as_string () const else if (has_lifetime ()) { // ref and lifetime - std::string str = "&" + lifetime.as_string () + " "; + std::string str = "&" + get_lifetime ().as_string () + " "; if (is_mut) str += "mut "; @@ -3331,7 +3375,13 @@ void Module::process_file_path () { rust_assert (kind == Module::ModuleKind::UNLOADED); - rust_assert (module_file.empty ()); + + if (!module_file.empty ()) + { + rust_error_at (locus, "error handling module file for %qs", + module_name.as_string ().c_str ()); + return; + } // This corresponds to the path of the file 'including' the module. So the // file that contains the 'mod <file>;' directive @@ -3480,13 +3530,24 @@ DelimTokenTree::parse_to_meta_item () const return new AttrInputMetaItemContainer (std::move (meta_items)); } +AttributeParser::AttributeParser ( + std::vector<std::unique_ptr<Token>> token_stream, int stream_start_pos) + : lexer (new MacroInvocLexer (std::move (token_stream))), + parser (new Parser<MacroInvocLexer> (*lexer)) +{ + if (stream_start_pos) + lexer->skip_token (stream_start_pos - 1); +} + +AttributeParser::~AttributeParser () {} + std::unique_ptr<MetaItemInner> AttributeParser::parse_meta_item_inner () { // if first tok not identifier, not a "special" case one - if (peek_token ()->get_id () != IDENTIFIER) + if (lexer->peek_token ()->get_id () != IDENTIFIER) { - switch (peek_token ()->get_id ()) + switch (lexer->peek_token ()->get_id ()) { case CHAR_LITERAL: case STRING_LITERAL: @@ -3507,48 +3568,46 @@ AttributeParser::parse_meta_item_inner () return parse_path_meta_item (); default: - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "unrecognised token '%s' in meta item", - get_token_description (peek_token ()->get_id ())); + get_token_description ( + lexer->peek_token ()->get_id ())); return nullptr; } } // else, check for path - if (peek_token (1)->get_id () == SCOPE_RESOLUTION) + if (lexer->peek_token (1)->get_id () == SCOPE_RESOLUTION) { // path return parse_path_meta_item (); } - auto ident = peek_token ()->as_string (); - auto ident_locus = peek_token ()->get_locus (); + auto ident = lexer->peek_token ()->get_str (); + auto ident_locus = lexer->peek_token ()->get_locus (); - if (is_end_meta_item_tok (peek_token (1)->get_id ())) + if (is_end_meta_item_tok (lexer->peek_token (1)->get_id ())) { // meta word syntax - skip_token (); + lexer->skip_token (); return std::unique_ptr<MetaWord> (new MetaWord (ident, ident_locus)); } - if (peek_token (1)->get_id () == EQUAL) + if (lexer->peek_token (1)->get_id () == EQUAL) { // maybe meta name value str syntax - check next 2 tokens - if (peek_token (2)->get_id () == STRING_LITERAL - && is_end_meta_item_tok (peek_token (3)->get_id ())) + if (lexer->peek_token (2)->get_id () == STRING_LITERAL + && is_end_meta_item_tok (lexer->peek_token (3)->get_id ())) { // meta name value str syntax - auto &value_tok = peek_token (2); - auto value = value_tok->as_string (); + const_TokenPtr value_tok = lexer->peek_token (2); + auto value = value_tok->get_str (); auto locus = value_tok->get_locus (); - skip_token (2); - - // remove the quotes from the string value - std::string raw_value = unquote_string (std::move (value)); + lexer->skip_token (2); return std::unique_ptr<MetaNameValueStr> ( - new MetaNameValueStr (ident, ident_locus, std::move (raw_value), + new MetaNameValueStr (ident, ident_locus, std::move (value), locus)); } else @@ -3558,16 +3617,16 @@ AttributeParser::parse_meta_item_inner () } } - if (peek_token (1)->get_id () != LEFT_PAREN) + if (lexer->peek_token (1)->get_id () != LEFT_PAREN) { - rust_error_at (peek_token (1)->get_locus (), + rust_error_at (lexer->peek_token (1)->get_locus (), "unexpected token '%s' after identifier in attribute", - get_token_description (peek_token (1)->get_id ())); + get_token_description (lexer->peek_token (1)->get_id ())); return nullptr; } // is it one of those special cases like not? - if (peek_token ()->get_id () == IDENTIFIER) + if (lexer->peek_token ()->get_id () == IDENTIFIER) { return parse_path_meta_item (); } @@ -3646,49 +3705,46 @@ AttributeParser::is_end_meta_item_tok (TokenId id) const std::unique_ptr<MetaItem> AttributeParser::parse_path_meta_item () { - SimplePath path = parse_simple_path (); + SimplePath path = parser->parse_simple_path (); if (path.is_empty ()) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "failed to parse simple path in attribute"); return nullptr; } - switch (peek_token ()->get_id ()) + switch (lexer->peek_token ()->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { std::vector<std::unique_ptr<MetaItemInner>> meta_items = parse_meta_item_seq (); return std::unique_ptr<MetaItemSeq> ( new MetaItemSeq (std::move (path), std::move (meta_items))); } - case EQUAL: { - skip_token (); + case EQUAL: + { + lexer->skip_token (); - location_t locus = peek_token ()->get_locus (); - Literal lit = parse_literal (); - if (lit.is_error ()) - { - rust_error_at (peek_token ()->get_locus (), - "failed to parse literal in attribute"); - return nullptr; - } - LiteralExpr expr (std::move (lit), {}, locus); - // stream_pos++; - /* shouldn't be required anymore due to parsing literal actually - * skipping the token */ - return std::unique_ptr<MetaItemPathLit> ( - new MetaItemPathLit (std::move (path), std::move (expr))); + std::unique_ptr<Expr> expr = parser->parse_expr (); + + // handle error + // parse_expr should already emit an error and return nullptr + if (!expr) + return nullptr; + + return std::unique_ptr<MetaItemPathExpr> ( + new MetaItemPathExpr (std::move (path), std::move (expr))); } case COMMA: // just simple path return std::unique_ptr<MetaItemPath> ( new MetaItemPath (std::move (path))); default: - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "unrecognised token '%s' in meta item", - get_token_description (peek_token ()->get_id ())); + get_token_description (lexer->peek_token ()->get_id ())); return nullptr; } } @@ -3698,41 +3754,41 @@ AttributeParser::parse_path_meta_item () std::vector<std::unique_ptr<MetaItemInner>> AttributeParser::parse_meta_item_seq () { - int vec_length = token_stream.size (); std::vector<std::unique_ptr<MetaItemInner>> meta_items; - if (peek_token ()->get_id () != LEFT_PAREN) + if (lexer->peek_token ()->get_id () != LEFT_PAREN) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "missing left paren in delim token tree"); return {}; } - skip_token (); + lexer->skip_token (); - while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN) + while (lexer->peek_token ()->get_id () != END_OF_FILE + && lexer->peek_token ()->get_id () != RIGHT_PAREN) { std::unique_ptr<MetaItemInner> inner = parse_meta_item_inner (); if (inner == nullptr) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "failed to parse inner meta item in attribute"); return {}; } meta_items.push_back (std::move (inner)); - if (peek_token ()->get_id () != COMMA) + if (lexer->peek_token ()->get_id () != COMMA) break; - skip_token (); + lexer->skip_token (); } - if (peek_token ()->get_id () != RIGHT_PAREN) + if (lexer->peek_token ()->get_id () != RIGHT_PAREN) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "missing right paren in delim token tree"); return {}; } - skip_token (); + lexer->skip_token (); return meta_items; } @@ -3755,130 +3811,19 @@ DelimTokenTree::to_token_stream () const return tokens; } -Literal -AttributeParser::parse_literal () -{ - const std::unique_ptr<Token> &tok = peek_token (); - switch (tok->get_id ()) - { - case CHAR_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ()); - case STRING_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::STRING, - tok->get_type_hint ()); - case BYTE_CHAR_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ()); - case BYTE_STRING_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::BYTE_STRING, - tok->get_type_hint ()); - case RAW_STRING_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::RAW_STRING, - tok->get_type_hint ()); - case INT_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ()); - case FLOAT_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ()); - case TRUE_LITERAL: - skip_token (); - return Literal ("true", Literal::BOOL, tok->get_type_hint ()); - case FALSE_LITERAL: - skip_token (); - return Literal ("false", Literal::BOOL, tok->get_type_hint ()); - default: - rust_error_at (tok->get_locus (), "expected literal - found '%s'", - get_token_description (tok->get_id ())); - return Literal::create_error (); - } -} - -SimplePath -AttributeParser::parse_simple_path () -{ - bool has_opening_scope_res = false; - if (peek_token ()->get_id () == SCOPE_RESOLUTION) - { - has_opening_scope_res = true; - skip_token (); - } - - std::vector<SimplePathSegment> segments; - - SimplePathSegment segment = parse_simple_path_segment (); - if (segment.is_error ()) - { - rust_error_at ( - peek_token ()->get_locus (), - "failed to parse simple path segment in attribute simple path"); - return SimplePath::create_empty (); - } - segments.push_back (std::move (segment)); - - while (peek_token ()->get_id () == SCOPE_RESOLUTION) - { - skip_token (); - - SimplePathSegment segment = parse_simple_path_segment (); - if (segment.is_error ()) - { - rust_error_at ( - peek_token ()->get_locus (), - "failed to parse simple path segment in attribute simple path"); - return SimplePath::create_empty (); - } - segments.push_back (std::move (segment)); - } - segments.shrink_to_fit (); - - return SimplePath (std::move (segments), has_opening_scope_res); -} - -SimplePathSegment -AttributeParser::parse_simple_path_segment () -{ - const std::unique_ptr<Token> &tok = peek_token (); - switch (tok->get_id ()) - { - case IDENTIFIER: - skip_token (); - return SimplePathSegment (tok->as_string (), tok->get_locus ()); - case SUPER: - skip_token (); - return SimplePathSegment ("super", tok->get_locus ()); - case SELF: - skip_token (); - return SimplePathSegment ("self", tok->get_locus ()); - case CRATE: - skip_token (); - return SimplePathSegment ("crate", tok->get_locus ()); - case DOLLAR_SIGN: - if (peek_token (1)->get_id () == CRATE) - { - skip_token (1); - return SimplePathSegment ("$crate", tok->get_locus ()); - } - gcc_fallthrough (); - default: - rust_error_at (tok->get_locus (), - "unexpected token '%s' in simple path segment", - get_token_description (tok->get_id ())); - return SimplePathSegment::create_error (); - } -} - std::unique_ptr<MetaItemLitExpr> AttributeParser::parse_meta_item_lit () { - location_t locus = peek_token ()->get_locus (); - LiteralExpr lit_expr (parse_literal (), {}, locus); + std::unique_ptr<LiteralExpr> lit_expr = parser->parse_literal_expr ({}); + + // TODO: return nullptr instead? + if (!lit_expr) + lit_expr = std::unique_ptr<LiteralExpr> ( + new LiteralExpr (Literal::create_error (), {}, + lexer->peek_token ()->get_locus ())); + return std::unique_ptr<MetaItemLitExpr> ( - new MetaItemLitExpr (std::move (lit_expr))); + new MetaItemLitExpr (std::move (*lit_expr))); } bool @@ -3901,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; } @@ -4087,10 +4035,12 @@ MetaNameValueStr::check_cfg_predicate (const Session &session) const } bool -MetaItemPathLit::check_cfg_predicate (const Session &session) const +MetaItemPathExpr::check_cfg_predicate (const Session &session) const { + // FIXME: Accept path expressions + rust_assert (expr->is_literal ()); return session.options.target_data.has_key_value_pair (path.as_string (), - lit.as_string ()); + expr->as_string ()); } std::vector<std::unique_ptr<Token>> @@ -4178,8 +4128,10 @@ MetaListNameValueStr::to_attribute () const } Attribute -MetaItemPathLit::to_attribute () const +MetaItemPathExpr::to_attribute () const { + rust_assert (expr->is_literal ()); + auto &lit = static_cast<LiteralExpr &> (*expr); return Attribute (path, std::unique_ptr<AttrInputLiteral> ( new AttrInputLiteral (lit))); } @@ -4197,6 +4149,12 @@ AttrInputMetaItemContainer::separate_cfg_attrs () const for (auto it = items.begin () + 1; it != items.end (); ++it) { + if ((*it)->get_kind () == MetaItemInner::Kind::MetaItem + && static_cast<MetaItem &> (**it).get_item_kind () + == MetaItem::ItemKind::PathExpr + && !static_cast<MetaItemPathExpr &> (**it).get_expr ().is_literal ()) + continue; + Attribute attr = (*it)->to_attribute (); if (attr.is_empty ()) { @@ -4214,18 +4172,13 @@ AttrInputMetaItemContainer::separate_cfg_attrs () const bool 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 () - || (path.as_string () != Values::Attributes::CFG - && path.as_string () != 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; } @@ -4234,6 +4187,20 @@ Attribute::check_cfg_predicate (const Session &session) const return false; auto &meta_item = static_cast<AttrInputMetaItemContainer &> (*attr_input); + 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 (), "multiple %qs predicates are specified", + path.as_string ().c_str ()); + return false; + } return meta_item.get_items ().front ()->check_cfg_predicate (session); } @@ -4282,11 +4249,12 @@ AttrInputMacro::AttrInputMacro (const AttrInputMacro &oth) : macro (oth.macro->clone_macro_invocation_impl ()) {} -void +AttrInputMacro & AttrInputMacro::operator= (const AttrInputMacro &oth) { macro = std::unique_ptr<MacroInvocation> ( oth.macro->clone_macro_invocation_impl ()); + return *this; } /* Visitor implementations - these are short but inlining can't happen anyway @@ -4348,7 +4316,7 @@ MetaItemLitExpr::accept_vis (ASTVisitor &vis) } void -MetaItemPathLit::accept_vis (ASTVisitor &vis) +MetaItemPathExpr::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -4516,6 +4484,18 @@ BlockExpr::accept_vis (ASTVisitor &vis) } void +AnonConst::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void ClosureExprInnerTyped::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -4576,6 +4556,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis) } void +TryExpr::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void UnsafeBlockExpr::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -4654,6 +4640,12 @@ InlineAsm::accept_vis (ASTVisitor &vis) } void +LlvmInlineAsm::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void TypeParam::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -4780,12 +4772,6 @@ StaticItem::accept_vis (ASTVisitor &vis) } void -TraitItemConst::accept_vis (ASTVisitor &vis) -{ - vis.visit (*this); -} - -void TraitItemType::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -5007,6 +4993,12 @@ FormatArgs::accept_vis (ASTVisitor &vis) vis.visit (*this); } +void +OffsetOf::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + std::string FormatArgs::as_string () const { @@ -5014,6 +5006,12 @@ FormatArgs::as_string () const return "FormatArgs"; } +std::string +OffsetOf::as_string () const +{ + return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")"; +} + location_t FormatArgs::get_locus () const { @@ -5044,7 +5042,8 @@ FormatArgs::get_outer_attrs () rust_unreachable (); } -void FormatArgs::set_outer_attrs (std::vector<Attribute>) +void +FormatArgs::set_outer_attrs (std::vector<Attribute>) { rust_unreachable (); } @@ -5057,6 +5056,24 @@ FormatArgs::clone_expr_impl () const return new FormatArgs (*this); } +std::vector<Attribute> & +OffsetOf::get_outer_attrs () +{ + rust_unreachable (); +} + +void +OffsetOf::set_outer_attrs (std::vector<Attribute>) +{ + rust_unreachable (); +} + +Expr * +OffsetOf::clone_expr_impl () const +{ + return new OffsetOf (*this); +} + } // namespace AST std::ostream & diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 4d7d23d..8610ade 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -57,13 +57,19 @@ public: bool empty () const { return ident.empty (); } + bool operator== (const Identifier &other) const + { + return ident == other.ident; + } + + operator const std::string & () const { return ident; } + private: std::string ident; location_t loc; }; -std::ostream & -operator<< (std::ostream &os, Identifier const &i); +std::ostream &operator<< (std::ostream &os, Identifier const &i); namespace AST { // foward decl: ast visitor @@ -77,6 +83,38 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; }; +/** + * Base function for reconstructing and asserting that the new NodeId is + * different from the old NodeId. It then wraps the given pointer into a unique + * pointer and returns it. + */ +template <typename T> +std::unique_ptr<T> +reconstruct_base (const T *instance) +{ + auto *reconstructed = instance->reconstruct_impl (); + + rust_assert (reconstructed->get_node_id () != instance->get_node_id ()); + + return std::unique_ptr<T> (reconstructed); +} + +/** + * Reconstruct multiple items in a vector + */ +template <typename T> +std::vector<std::unique_ptr<T>> +reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct) +{ + std::vector<std::unique_ptr<T>> reconstructed; + reconstructed.reserve (to_reconstruct.size ()); + + for (const auto &elt : to_reconstruct) + reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ())); + + return reconstructed; +} + // Delimiter types - used in macros and whatever. enum DelimType { @@ -146,17 +184,6 @@ class Token : public TokenTree, public MacroMatch { // A token is a kind of token tree (except delimiter tokens) // A token is a kind of MacroMatch (except $ and delimiter tokens) -#if 0 - // TODO: improve member variables - current ones are the same as lexer token - // Token kind. - TokenId token_id; - // Token location. - location_t locus; - // Associated text (if any) of token. - std::string str; - // Token type hint (if any). - PrimitiveCoreType type_hint; -#endif const_TokenPtr tok_ref; @@ -171,53 +198,7 @@ public: return std::unique_ptr<Token> (clone_token_impl ()); } -#if 0 - /* constructor from general text - avoid using if lexer const_TokenPtr is - * available */ - Token (TokenId token_id, location_t locus, std::string str, - PrimitiveCoreType type_hint) - : token_id (token_id), locus (locus), str (std::move (str)), - type_hint (type_hint) - {} -#endif - // not doable with new implementation - will have to make a const_TokenPtr - // Constructor from lexer const_TokenPtr -#if 0 - /* TODO: find workaround for std::string being nullptr - probably have to - * introduce new method in lexer Token, or maybe make conversion method - * there */ - Token (const_TokenPtr lexer_token_ptr) - : token_id (lexer_token_ptr->get_id ()), - locus (lexer_token_ptr->get_locus ()), str (""), - type_hint (lexer_token_ptr->get_type_hint ()) - { - // FIXME: change to "should have str" later? - if (lexer_token_ptr->has_str ()) - { - str = lexer_token_ptr->get_str (); - - // DEBUG - rust_debug ("ast token created with str '%s'", str.c_str ()); - } - else - { - // FIXME: is this returning correct thing? - str = lexer_token_ptr->get_token_description (); - - // DEBUG - rust_debug ("ast token created with string '%s'", str.c_str ()); - } - - // DEBUG - if (lexer_token_ptr->should_have_str () && !lexer_token_ptr->has_str ()) - { - rust_debug ( - "BAD: for token '%s', should have string but does not!", - lexer_token_ptr->get_token_description ()); - } - } -#endif Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {} bool is_string_lit () const @@ -245,6 +226,7 @@ public: std::vector<std::unique_ptr<Token>> to_token_stream () const override; TokenId get_id () const { return tok_ref->get_id (); } + bool should_have_str () const { return tok_ref->should_have_str (); } const std::string &get_str () const { return tok_ref->get_str (); } location_t get_locus () const { return tok_ref->get_locus (); } @@ -398,15 +380,15 @@ class SimplePath public: // Constructor - SimplePath (std::vector<SimplePathSegment> path_segments, - bool has_opening_scope_resolution = false, - location_t locus = UNDEF_LOCATION) + explicit SimplePath (std::vector<SimplePathSegment> path_segments, + bool has_opening_scope_resolution = false, + location_t locus = UNDEF_LOCATION) : opening_scope_resolution (has_opening_scope_resolution), segments (std::move (path_segments)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} - SimplePath (Identifier ident) + explicit SimplePath (Identifier ident) : opening_scope_resolution (false), segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}), locus (ident.get_locus ()), @@ -657,6 +639,9 @@ public: // Returns whether the attribute is considered an "empty" attribute. bool is_empty () const { return attr_input == nullptr && path.is_empty (); } + // Returns whether the attribute has no input + bool empty_input () const { return !attr_input; } + location_t get_locus () const { return locus; } AttrInput &get_attr_input () const { return *attr_input; } @@ -1015,6 +1000,7 @@ public: } DelimType get_delim_type () const { return delim_type; } + location_t get_locus () const { return locus; } }; /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr @@ -1030,7 +1016,7 @@ public: Path, Word, NameValueStr, - PathLit, + PathExpr, Seq, ListPaths, ListNameValueStr, @@ -1048,7 +1034,7 @@ public: class MetaItemLitExpr; // Forward decl - defined in rust-expr.h -class MetaItemPathLit; +class MetaItemPathExpr; // Forward decl - defined in rust-macro.h class MetaItemPath; @@ -1094,7 +1080,9 @@ public: virtual void mark_for_strip () = 0; virtual bool is_marked_for_strip () const = 0; - NodeId get_node_id () const { return node_id; } + + // TODO: put this in a virtual base class? + virtual NodeId get_node_id () const { return node_id; } virtual Kind get_stmt_kind () = 0; @@ -1247,6 +1235,8 @@ public: FieldAccess, Closure, Block, + ConstExpr, + ConstBlock, Continue, Break, Range, @@ -1260,8 +1250,10 @@ public: Await, AsyncBlock, InlineAsm, + LlvmInlineAsm, Identifier, FormatArgs, + OffsetOf, MacroInvocation, Borrow, Dereference, @@ -1273,6 +1265,7 @@ public: TypeCast, Assignment, CompoundAssignment, + Try, }; virtual Kind get_expr_kind () const = 0; @@ -1467,6 +1460,10 @@ public: return std::unique_ptr<Type> (clone_type_impl ()); } + // Similar to `clone_type`, but generates a new instance of the node with a + // different NodeId + std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); } + // virtual destructor virtual ~Type () {} @@ -1484,12 +1481,15 @@ public: virtual location_t get_locus () const = 0; - NodeId get_node_id () const { return node_id; } + // TODO: put this in a virtual base class? + virtual NodeId get_node_id () const { return node_id; } + virtual Type *reconstruct_impl () const = 0; protected: Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + Type (NodeId node_id) : node_id (node_id) {} - // Clone function implementation as pure virtual method + // Clone and reconstruct function implementations as pure virtual methods virtual Type *clone_type_impl () const = 0; NodeId node_id; @@ -1505,6 +1505,13 @@ public: return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ()); } + std::unique_ptr<TypeNoBounds> reconstruct () const + { + return reconstruct_base (this); + } + + virtual TypeNoBounds *reconstruct_impl () const override = 0; + protected: // Clone function implementation as pure virtual method virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0; @@ -1539,6 +1546,11 @@ public: return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ()); } + std::unique_ptr<TypeParamBound> reconstruct () const + { + return reconstruct_base (this); + } + virtual std::string as_string () const = 0; NodeId get_node_id () const { return node_id; } @@ -1547,10 +1559,14 @@ public: virtual TypeParamBoundType get_bound_type () const = 0; + virtual TypeParamBound *reconstruct_impl () const = 0; + protected: // Clone function implementation as pure virtual method virtual TypeParamBound *clone_type_param_bound_impl () const = 0; + TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} TypeParamBound (NodeId node_id) : node_id (node_id) {} NodeId node_id; @@ -1587,17 +1603,9 @@ public: lifetime_name (std::move (name)), locus (locus) {} - // Creates an "error" lifetime. - static Lifetime error () { return Lifetime (NAMED, ""); } - static Lifetime elided () { return Lifetime (WILDCARD, ""); } // Returns true if the lifetime is in an error state. - bool is_error () const - { - return lifetime_type == NAMED && lifetime_name.empty (); - } - std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; @@ -1620,6 +1628,10 @@ protected: { return new Lifetime (node_id, lifetime_type, lifetime_name, locus); } + Lifetime *reconstruct_impl () const override + { + return new Lifetime (lifetime_type, lifetime_name, locus); + } }; /* Base generic parameter in AST. Abstract - can be represented by a Lifetime @@ -1688,15 +1700,6 @@ public: // Returns whether the lifetime param has an outer attribute. bool has_outer_attribute () const { return !outer_attrs.empty (); } - // Creates an error state lifetime param. - static LifetimeParam create_error () - { - return LifetimeParam (Lifetime::error (), {}, {}, UNDEF_LOCATION); - } - - // Returns whether the lifetime param is in an error state. - bool is_error () const { return lifetime.is_error (); } - // Constructor LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds, AST::AttrVec outer_attrs, location_t locus) @@ -1742,6 +1745,8 @@ public: virtual bool is_marked_for_strip () const = 0; virtual location_t get_locus () const = 0; + + virtual NodeId get_node_id () const = 0; }; // Item used in trait declarations - abstract base class @@ -1772,7 +1777,7 @@ public: return std::unique_ptr<TraitItem> (clone_associated_item_impl ()); } - NodeId get_node_id () const { return node_id; } + NodeId get_node_id () const override { return node_id; } location_t get_locus () const override { return locus; } }; @@ -1886,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; @@ -1900,18 +1904,19 @@ public: class SingleASTNode : public Visitable { public: - enum NodeType - { - EXPRESSION, - ITEM, - STMT, - EXTERN, - ASSOC_ITEM, - TYPE, + enum class Kind + { + Expr, + Item, + Stmt, + Extern, + Assoc, + Type, + Pattern, }; private: - NodeType kind; + Kind kind; // FIXME make this a union std::unique_ptr<Expr> expr; @@ -1920,30 +1925,35 @@ private: std::unique_ptr<ExternalItem> external_item; std::unique_ptr<AssociatedItem> assoc_item; std::unique_ptr<Type> type; + std::unique_ptr<Pattern> pattern; public: SingleASTNode (std::unique_ptr<Expr> expr) - : kind (EXPRESSION), expr (std::move (expr)) + : kind (Kind::Expr), expr (std::move (expr)) {} SingleASTNode (std::unique_ptr<Item> item) - : kind (ITEM), item (std::move (item)) + : kind (Kind::Item), item (std::move (item)) {} SingleASTNode (std::unique_ptr<Stmt> stmt) - : kind (STMT), stmt (std::move (stmt)) + : kind (Kind::Stmt), stmt (std::move (stmt)) {} SingleASTNode (std::unique_ptr<ExternalItem> item) - : kind (EXTERN), external_item (std::move (item)) + : kind (Kind::Extern), external_item (std::move (item)) {} SingleASTNode (std::unique_ptr<AssociatedItem> item) - : kind (ASSOC_ITEM), assoc_item (std::move (item)) + : kind (Kind::Assoc), assoc_item (std::move (item)) {} SingleASTNode (std::unique_ptr<Type> type) - : kind (TYPE), type (std::move (type)) + : kind (Kind::Type), type (std::move (type)) + {} + + SingleASTNode (std::unique_ptr<Pattern> pattern) + : kind (Kind::Pattern), pattern (std::move (pattern)) {} SingleASTNode (SingleASTNode const &other); @@ -1953,23 +1963,23 @@ public: SingleASTNode (SingleASTNode &&other) = default; SingleASTNode &operator= (SingleASTNode &&other) = default; - NodeType get_kind () const { return kind; } + Kind get_kind () const { return kind; } std::unique_ptr<Expr> &get_expr () { - rust_assert (kind == EXPRESSION); + rust_assert (kind == Kind::Expr); return expr; } std::unique_ptr<Item> &get_item () { - rust_assert (kind == ITEM); + rust_assert (kind == Kind::Item); return item; } std::unique_ptr<Stmt> &get_stmt () { - rust_assert (kind == STMT); + rust_assert (kind == Kind::Stmt); return stmt; } @@ -2014,6 +2024,12 @@ public: return std::move (type); } + std::unique_ptr<Pattern> take_pattern () + { + rust_assert (!is_error ()); + return std::move (pattern); + } + void accept_vis (ASTVisitor &vis) override; bool is_error (); @@ -2109,6 +2125,19 @@ template <> struct less<Rust::Identifier> return lhs.as_string () < rhs.as_string (); } }; + +template <> struct hash<Rust::Identifier> +{ + std::size_t operator() (const Rust::Identifier &k) const + { + using std::hash; + using std::size_t; + using std::string; + + return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ())); + } +}; + } // namespace std #endif diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h index 3684092..c784ad6 100644 --- a/gcc/rust/ast/rust-builtin-ast-nodes.h +++ b/gcc/rust/ast/rust-builtin-ast-nodes.h @@ -134,6 +134,7 @@ public: FormatArgumentKind get_kind () const { return kind; } const Expr &get_expr () const { return *expr; } + Expr &get_expr () { return *expr; } private: FormatArgument (FormatArgumentKind::Kind kind, tl::optional<Identifier> ident, @@ -164,6 +165,11 @@ public: void push (FormatArgument &&elt) { args.emplace_back (std::move (elt)); } const FormatArgument at (size_t idx) const { return args.at (idx); } + const std::vector<FormatArgument> &get_args () const { return args; } + std::vector<FormatArgument> &get_args () { return args; } + size_t size () const { return args.size (); } + bool empty () const { return args.empty (); } + private: std::vector<FormatArgument> args; }; @@ -200,6 +206,7 @@ public: const Fmt::Pieces &get_template () const { return template_pieces; } const FormatArguments &get_arguments () const { return arguments; } + FormatArguments &get_arguments () { return arguments; } virtual location_t get_locus () const override; Expr::Kind get_expr_kind () const override { return Expr::Kind::FormatArgs; } @@ -225,6 +232,60 @@ protected: virtual Expr *clone_expr_impl () const override; }; +/** + * The node associated with the builtin offset_of!() macro + */ +class OffsetOf : public Expr +{ +public: + OffsetOf (std::unique_ptr<Type> &&type, Identifier field, location_t loc) + : type (std::move (type)), field (field), loc (loc) + {} + + OffsetOf (const OffsetOf &other) + : type (other.type->clone_type ()), field (other.field), loc (other.loc), + marked_for_strip (other.marked_for_strip) + {} + + OffsetOf &operator= (const OffsetOf &other) + { + type = other.type->clone_type (); + field = other.field; + loc = other.loc; + marked_for_strip = other.marked_for_strip; + + return *this; + } + + void accept_vis (AST::ASTVisitor &vis) override; + + virtual location_t get_locus () const override { return loc; } + const Type &get_type () const { return *type; } + Type &get_type () { return *type; } + std::unique_ptr<Type> &get_type_ptr () { return type; } + const Identifier &get_field () const { return field; } + + bool is_expr_without_block () const override { return false; } + + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + + std::string as_string () const override; + + std::vector<Attribute> &get_outer_attrs () override; + void set_outer_attrs (std::vector<Attribute>) override; + Expr *clone_expr_impl () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::OffsetOf; } + +private: + std::unique_ptr<Type> type; + Identifier field; + + location_t loc; + bool marked_for_strip = false; +}; + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index cd6be7f..1efe26f 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -43,18 +43,16 @@ get_lang_item_attr (const T &maybe_lang_item) continue; } - 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; + bool is_lang_item = str_path == Values::Attributes::LANG; if (is_lang_item) { - auto &literal - = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &lang_item_type_str = literal.get_literal ().as_string (); + auto lang_item_type_str + = Analysis::Attributes::extract_string_literal (attr); - return LangItem::Parse (lang_item_type_str); + rust_assert (lang_item_type_str.has_value ()); + + return LangItem::Parse (*lang_item_type_str); } } @@ -109,5 +107,29 @@ CollectLangItems::visit (AST::EnumItem &item) DefaultASTVisitor::visit (item); } +void +CollectLangItems::visit (AST::EnumItemTuple &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemStruct &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemDiscriminant &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h index ddb34a9..ddc7b51 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -50,6 +50,9 @@ public: void visit (AST::Function &item) override; void visit (AST::StructStruct &item) override; void visit (AST::EnumItem &item) override; + void visit (AST::EnumItemTuple &item) override; + void visit (AST::EnumItemStruct &item) override; + void visit (AST::EnumItemDiscriminant &item) override; private: template <typename T> void maybe_add_lang_item (const T &item); diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h index 610b904..5d5fba5 100644 --- a/gcc/rust/ast/rust-cond-compilation.h +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -42,8 +42,8 @@ public: protected: // Clone function impl to be overriden in base classes - virtual ConfigurationPredicate * - clone_configuration_predicate_impl () const = 0; + virtual ConfigurationPredicate *clone_configuration_predicate_impl () const + = 0; }; // A configuration option - true if option is set, false if option is not set. @@ -91,9 +91,13 @@ class ConfigurationAll : public ConfigurationPredicate predicate_list; // inlined form public: + ConfigurationAll (const ConfigurationAll &) = delete; + + ConfigurationAll (ConfigurationAll &&) = default; + ConfigurationAll ( std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list) - : predicate_list (predicate_list) + : predicate_list (std::move (predicate_list)) {} void accept_vis (ASTVisitor &vis) override; @@ -103,7 +107,14 @@ protected: * than base */ ConfigurationAll *clone_configuration_predicate_impl () const override { - return new ConfigurationAll (*this); + decltype (predicate_list) predicate_list_clone = {}; + predicate_list_clone.reserve (predicate_list.size ()); + + for (const auto &predicate : predicate_list) + predicate_list_clone.push_back ( + predicate->clone_configuration_predicate ()); + + return new ConfigurationAll (std::move (predicate_list_clone)); } }; @@ -114,9 +125,13 @@ class ConfigurationAny : public ConfigurationPredicate predicate_list; // inlined form public: + ConfigurationAny (const ConfigurationAny &) = delete; + + ConfigurationAny (ConfigurationAny &&) = default; + ConfigurationAny ( std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list) - : predicate_list (predicate_list) + : predicate_list (std::move (predicate_list)) {} void accept_vis (ASTVisitor &vis) override; @@ -126,7 +141,14 @@ protected: * than base */ ConfigurationAny *clone_configuration_predicate_impl () const override { - return new ConfigurationAny (*this); + decltype (predicate_list) predicate_list_clone = {}; + predicate_list_clone.reserve (predicate_list.size ()); + + for (const auto &predicate : predicate_list) + predicate_list_clone.push_back ( + predicate->clone_configuration_predicate ()); + + return new ConfigurationAny (std::move (predicate_list_clone)); } }; @@ -226,7 +248,7 @@ public: CfgAttrAttribute (CfgAttrAttribute const &other) : config_to_include ( other.config_to_include->clone_configuration_predicate ()), - cfg_attrs (cfg_attrs) + cfg_attrs (other.cfg_attrs) {} // Overloaded assignment operator to clone diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc new file mode 100644 index 0000000..de34e15 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -0,0 +1,530 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-apit.h" +#include "rust-ast.h" +#include "rust-type.h" + +namespace Rust { +namespace AST { + +class DesugarApitType : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + static std::pair<AST::Type *, std::vector<std::unique_ptr<GenericParam>>> + Desugar (AST::Type &type) + { + DesugarApitType visitor (&type); + type.accept_vis (visitor); + rust_assert (visitor.translated != nullptr); + return std::make_pair (visitor.translated, + std::move (visitor.implicit_generic_params)); + } + + // Generate a unique impl trait parameter name + static Identifier get_impl_name () + { + static size_t counter = 0; + return Identifier ("Impl_" + std::to_string (counter++)); + } + + // these can hold other types + void visit (AST::TupleType &tuple) override + { + for (auto &elem : tuple.get_elems ()) + { + auto &type = *elem.get (); + auto desugar = Desugar (type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + continue; + + if (tt != elem.get ()) + elem = std::unique_ptr<Type> (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + } + + void visit (AST::ArrayType &type) override + { + auto &element_type = type.get_element_type (); + auto desugar = Desugar (*element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (tt != element_type.get ()) + element_type = std::unique_ptr<AST::Type> (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ReferenceType &type) override + { + // Get a reference to the current type for in-place modification + auto &referenced_type = type.get_type_referenced (); + auto desugar = Desugar (referenced_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the reference type's contents rather than creating a new one + if (&referenced_type != tt) + { + std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds ( + static_cast<AST::TypeNoBounds *> (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::RawPointerType &type) override + { + auto &pointed_type = type.get_type_pointed_to (); + auto desugar = Desugar (pointed_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the pointer's inner type directly using the new accessor + if (&pointed_type != tt) + { + std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds ( + static_cast<AST::TypeNoBounds *> (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::SliceType &type) override + { + auto &element_type = type.get_elem_type (); + auto desugar = Desugar (element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (&element_type != tt) + { + std::unique_ptr<AST::Type> new_elem_type (tt); + type.get_elem_type_ptr () = std::move (new_elem_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ParenthesisedType &type) override + { + auto &inner_type_ptr = type.get_type_in_parens (); + auto desugar = Desugar (*inner_type_ptr); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (inner_type_ptr.get () != tt) + { + std::unique_ptr<AST::Type> new_inner_type (tt); + inner_type_ptr = std::move (new_inner_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + // this is where the desugar happens + void visit (AST::ImplTraitType &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.emplace_back ( + new TypePathSegment (PathIdentSegment (ident.as_string (), + type.get_locus ()), + false, type.get_locus ())); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert bounds from impl trait to generic parameter bounds + std::vector<std::unique_ptr<TypeParamBound>> bounds; + bounds.reserve (type.get_type_param_bounds ().size ()); + + for (auto &bound : type.get_type_param_bounds ()) + bounds.push_back (bound->clone_type_param_bound ()); + + // Create the new generic parameter + auto generic_param = std::unique_ptr<TypeParam> ( + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + + void visit (AST::ImplTraitTypeOneBound &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.emplace_back ( + new TypePathSegment (PathIdentSegment (ident.as_string (), + type.get_locus ()), + false, type.get_locus ())); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert the bound to a generic parameter bound + std::vector<std::unique_ptr<TypeParamBound>> bounds; + bounds.push_back (std::move (type.get_trait_bound ())); + + // Create the new generic parameter + auto generic_param = std::unique_ptr<TypeParam> ( + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + +private: + DesugarApitType (AST::Type *base) + : translated (base), implicit_generic_params () + {} + + AST::Type *translated; + std::vector<std::unique_ptr<GenericParam>> implicit_generic_params; +}; + +// --------- + +class ApitBoundProcessor +{ +public: + ApitBoundProcessor ( + WhereClause &where_clause, + std::vector<std::unique_ptr<GenericParam>> &generic_params) + : where_clause (where_clause), generic_params (generic_params) + {} + + void go (std::vector<std::unique_ptr<GenericParam>> &implicit_generics) + { + // some desugars are more complex so imagine this case + // + // pub fn foo(_value: impl Bar<Baz = impl Foo>) -> i32 { + // 15 + // } + // + // this needs to become: + // + // pub fn foo<T, U>(_value: T) -> i32 + // where + // T: Bar<Baz = U>, + // U: Foo, + // { + // 15 + // } + // + // so we need to walk all the implicit generics and the trait bounds paths + // for more generics + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: + { + TypeParam &p + = *static_cast<TypeParam *> (implicit_generic.get ()); + + process_type_param (p); + generic_params.push_back (std::move (implicit_generic)); + for (auto &synth : synthetic_params) + generic_params.push_back (std::move (synth)); + synthetic_params.clear (); + } + break; + + default: + generic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + +private: + void process_type_param (TypeParam &p) + { + auto &bounds = p.get_type_param_bounds (); + std::vector<size_t> bounds_to_remove; + for (size_t i = 0; i < bounds.size (); i++) + { + auto &tb = bounds[i]; + switch (tb->get_bound_type ()) + { + case TypeParamBound::TypeParamBoundType::TRAIT: + { + TraitBound &ttb = *static_cast<TraitBound *> (tb.get ()); + TypePath &path = ttb.get_type_path (); + bool deusgared = process_type_path (p, ttb, path); + if (deusgared) + bounds_to_remove.push_back (i); + } + + default: + break; + } + } + for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend (); + ++it) + bounds.erase (bounds.begin () + *it); + } + + bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path) + { + bool desugared = false; + for (auto &segment : path.get_segments ()) + { + switch (segment->get_type ()) + { + case TypePathSegment::SegmentType::GENERIC: + { + TypePathSegmentGeneric &seg + = *static_cast<TypePathSegmentGeneric *> (segment.get ()); + desugared |= process_generic_segment (p, parent, path, seg); + } + + default: + break; + } + } + return desugared; + } + + bool process_generic_segment (TypeParam &p, TraitBound &parent, + TypePath &path, TypePathSegmentGeneric &seg) + { + // we need to look for any impl types as default arguments in any generics + // and remove this index from the generic arguments by using a where + // constraint instead + + std::vector<std::unique_ptr<WhereClauseItem>> new_clauses; + GenericArgs &generic_args = seg.get_generic_args (); + std::vector<std::reference_wrapper<const GenericArgsBinding>> + bindings_desugared; + std::vector<GenericArgsBinding> &bindings + = generic_args.get_binding_args (); + + for (auto &generic : bindings) + { + auto &t = generic.get_type (); + auto translated = DesugarApitType::Desugar (t); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (tt != &t) + { + bindings_desugared.push_back (generic); + generic.get_type_ptr () = std::unique_ptr<Type> (tt); + } + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: + { + TypeParam &tp + = *static_cast<TypeParam *> (implicit_generic.get ()); + + std::vector<std::unique_ptr<TypeParamBound>> + type_param_bounds; + type_param_bounds.reserve ( + tp.get_type_param_bounds ().size ()); + + for (auto &b : tp.get_type_param_bounds ()) + type_param_bounds.push_back (std::move (b)); + tp.get_type_param_bounds ().clear (); + + // add synthetic parameter for this + synthetic_params.push_back (std::move (implicit_generic)); + + auto bound_type_path + = get_type_for_identifier (tp.get_type_representation ()); + + auto clause = new TypeBoundWhereClauseItem ( + {}, std::move (bound_type_path), + std::move (type_param_bounds), tp.get_locus ()); + std::unique_ptr<WhereClauseItem> clause_item + = std::unique_ptr<WhereClauseItem> (clause); + new_clauses.push_back (std::move (clause_item)); + } + break; + + default: + synthetic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + auto bound = std::unique_ptr<TypeParamBound> (new TraitBound (parent)); + type_param_bounds.push_back (std::move (bound)); + auto parent_type_path + = get_type_for_identifier (p.get_type_representation ()); + auto clause + = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path), + std::move (type_param_bounds), + parent.get_locus ()); + std::unique_ptr<WhereClauseItem> clause_item + = std::unique_ptr<WhereClauseItem> (clause); + where_clause.get_items ().push_back (std::move (clause_item)); + + for (auto &where_item : new_clauses) + where_clause.get_items ().push_back (std::move (where_item)); + + return !bindings_desugared.empty (); + } + + static std::unique_ptr<Type> get_type_for_identifier (const Identifier &ident) + { + auto simple_seg + = SimplePathSegment (ident.as_string (), ident.get_locus ()); + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + auto simple_path = SimplePath (simple_segs, false, ident.get_locus ()); + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.emplace_back ( + new TypePathSegment (PathIdentSegment (ident.as_string (), + ident.get_locus ()), + false, ident.get_locus ())); + auto type_path = new TypePath (std::move (segments), ident.get_locus ()); + return std::unique_ptr<Type> (type_path); + } + +private: + WhereClause &where_clause; + std::vector<std::unique_ptr<GenericParam>> &generic_params; + + // mutates + std::vector<std::unique_ptr<GenericParam>> synthetic_params; +}; + +// --------- + +DesugarApit::DesugarApit () {} + +void +DesugarApit::go (AST::Crate &crate) +{ + DefaultASTVisitor::visit (crate); +} + +void +DesugarApit::visit (AST::Function &function) +{ + if (!function.has_function_params ()) + return; + + auto &fn_params = function.get_function_params (); + for (auto ¶m : fn_params) + { + if (param->is_variadic () || param->is_self ()) + continue; + + auto *p = param.get (); + auto &fp = *static_cast<AST::FunctionParam *> (p); + auto &type = fp.get_type (); + + auto translated = DesugarApitType::Desugar (type); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (fp.get_type_ptr ().get () != tt) + { + fp.get_type_ptr () = std::unique_ptr<AST::Type> (tt); + } + + ApitBoundProcessor processor (function.get_where_clause (), + function.get_generic_params ()); + processor.go (implicit_generics); + } +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-apit.h b/gcc/rust/ast/rust-desugar-apit.h new file mode 100644 index 0000000..07c25e2 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-apit.h @@ -0,0 +1,42 @@ +// 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/>. + +#ifndef RUST_DESUGAR_APIT_H +#define RUST_DESUGAR_APIT_H + +#include "rust-ast-visitor.h" + +namespace Rust { +namespace AST { + +class DesugarApit : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + DesugarApit (); + void go (AST::Crate &); + +private: + void visit (AST::Function &) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_APIT_H diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index 5e5cbbc..9a12423 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -17,7 +17,6 @@ // <http://www.gnu.org/licenses/>. #include "rust-desugar-for-loops.h" -#include "rust-ast-visitor.h" #include "rust-ast.h" #include "rust-hir-map.h" #include "rust-path.h" @@ -31,36 +30,14 @@ namespace AST { DesugarForLoops::DesugarForLoops () {} -void -DesugarForLoops::go (AST::Crate &crate) -{ - DefaultASTVisitor::visit (crate); -} - -static void -replace_for_loop (std::unique_ptr<Expr> &for_loop, - std::unique_ptr<Expr> &&expanded) -{ - for_loop = std::move (expanded); -} - -MatchArm -DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr<Pattern> &&path) -{ - auto patterns = std::vector<std::unique_ptr<Pattern>> (); - patterns.emplace_back (std::move (path)); - - return MatchArm (std::move (patterns), loc); -} - MatchCase DesugarForLoops::DesugarCtx::make_break_arm () { - auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression ( + auto arm = builder.match_arm (std::unique_ptr<Pattern> (new PathInExpression ( builder.path_in_expression (LangItem::Kind::OPTION_NONE)))); - auto break_expr = std::unique_ptr<Expr> ( - new BreakExpr (Lifetime::error (), nullptr, {}, loc)); + auto break_expr + = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc)); return MatchCase (std::move (arm), std::move (break_expr)); } @@ -74,12 +51,12 @@ DesugarForLoops::DesugarCtx::make_continue_arm () patterns.emplace_back (std::move (val)); auto pattern_item = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (patterns))); + new TupleStructItemsNoRest (std::move (patterns))); auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( builder.path_in_expression (LangItem::Kind::OPTION_SOME), std::move (pattern_item))); - auto val_arm = make_match_arm (std::move (pattern)); + auto val_arm = builder.match_arm (std::move (pattern)); auto next = builder.identifier (DesugarCtx::next_value_id); @@ -91,14 +68,8 @@ DesugarForLoops::DesugarCtx::make_continue_arm () return MatchCase (std::move (val_arm), std::move (assignment)); } -std::unique_ptr<Stmt> -DesugarForLoops::DesugarCtx::statementify (std::unique_ptr<Expr> &&expr) -{ - return std::unique_ptr<Stmt> (new ExprStmt (std::move (expr), loc, true)); -} - std::unique_ptr<Expr> -DesugarForLoops::desugar (AST::ForLoopExpr &expr) +DesugarForLoops::desugar (ForLoopExpr &expr) { auto ctx = DesugarCtx (expr.get_locus ()); @@ -140,10 +111,10 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) auto loop_stmts = std::vector<std::unique_ptr<Stmt>> (); loop_stmts.emplace_back (std::move (let_next)); - loop_stmts.emplace_back (ctx.statementify (std::move (match_next))); + loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_next))); loop_stmts.emplace_back (std::move (let_pat)); loop_stmts.emplace_back ( - ctx.statementify (expr.get_loop_block ().clone_expr ())); + ctx.builder.statementify (expr.get_loop_block ().clone_expr ())); // loop { // <let_next>; @@ -170,34 +141,18 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) } void -DesugarForLoops::maybe_desugar_expr (std::unique_ptr<Expr> &expr) +DesugarForLoops::go (std::unique_ptr<Expr> &ptr) { - if (expr->get_expr_kind () == AST::Expr::Kind::Loop) - { - auto &loop = static_cast<AST::BaseLoopExpr &> (*expr); + rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop); - if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For) - { - auto &for_loop = static_cast<AST::ForLoopExpr &> (loop); + auto &loop = static_cast<BaseLoopExpr &> (*ptr); - auto desugared = desugar (for_loop); - - replace_for_loop (expr, std::move (desugared)); - } - } -} - -void -DesugarForLoops::visit (AST::BlockExpr &block) -{ - for (auto &stmt : block.get_statements ()) - if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr) - maybe_desugar_expr (static_cast<AST::ExprStmt &> (*stmt).get_expr_ptr ()); + rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::For); - if (block.has_tail_expr ()) - maybe_desugar_expr (block.get_tail_expr_ptr ()); + auto &for_loop = static_cast<ForLoopExpr &> (loop); + auto desugared = DesugarForLoops ().desugar (for_loop); - DefaultASTVisitor::visit (block); + ptr = std::move (desugared); } } // namespace AST diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h index 7beb692..96b63ff 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.h +++ b/gcc/rust/ast/rust-desugar-for-loops.h @@ -20,7 +20,6 @@ #define RUST_DESUGAR_FOR_LOOPS_H #include "rust-ast-builder.h" -#include "rust-ast-visitor.h" #include "rust-expr.h" namespace Rust { @@ -69,15 +68,14 @@ namespace AST { // of the way the typechecker is currently structured, where it will fetch name // resolution information in order to typecheck paths - which technically isn't // necessary. -class DesugarForLoops : public DefaultASTVisitor +class DesugarForLoops { - using DefaultASTVisitor::visit; - public: - DesugarForLoops (); - void go (AST::Crate &); + static void go (std::unique_ptr<Expr> &ptr); private: + DesugarForLoops (); + struct DesugarCtx { DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {} @@ -85,10 +83,8 @@ private: Builder builder; location_t loc; - MatchArm make_match_arm (std::unique_ptr<Pattern> &&pattern); MatchCase make_break_arm (); MatchCase make_continue_arm (); - std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&expr); constexpr static const char *continue_pattern_id = "#val"; constexpr static const char *next_value_id = "#__next"; @@ -96,10 +92,7 @@ private: constexpr static const char *result_id = "#result"; }; - std::unique_ptr<Expr> desugar (AST::ForLoopExpr &expr); - void maybe_desugar_expr (std::unique_ptr<Expr> &expr); - - void visit (AST::BlockExpr &) override; + std::unique_ptr<Expr> desugar (ForLoopExpr &expr); }; } // namespace AST diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc index 4d2933b..20a4903 100644 --- a/gcc/rust/ast/rust-desugar-question-mark.cc +++ b/gcc/rust/ast/rust-desugar-question-mark.cc @@ -18,7 +18,6 @@ #include "rust-desugar-question-mark.h" #include "rust-ast-builder.h" -#include "rust-ast-visitor.h" namespace Rust { namespace AST { @@ -26,42 +25,14 @@ namespace AST { DesugarQuestionMark::DesugarQuestionMark () {} void -DesugarQuestionMark::go (AST::Crate &crate) +DesugarQuestionMark::go (std::unique_ptr<Expr> &ptr) { - DesugarQuestionMark::visit (crate); -} - -void -DesugarQuestionMark::visit (ExprStmt &stmt) -{ - if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation) - desugar_and_replace (stmt.get_expr_ptr ()); - - DefaultASTVisitor::visit (stmt); -} - -void -DesugarQuestionMark::visit (CallExpr &call) -{ - if (call.get_function_expr ().get_expr_kind () - == Expr::Kind::ErrorPropagation) - desugar_and_replace (call.get_function_expr_ptr ()); - - for (auto &arg : call.get_params ()) - if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation) - desugar_and_replace (arg); - - DefaultASTVisitor::visit (call); -} + rust_assert (ptr->get_expr_kind () == Expr::Kind::ErrorPropagation); -void -DesugarQuestionMark::visit (LetStmt &stmt) -{ - if (stmt.has_init_expr () - && stmt.get_init_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation) - desugar_and_replace (stmt.get_init_expr_ptr ()); + auto original = static_cast<ErrorPropagationExpr &> (*ptr); + auto desugared = DesugarQuestionMark ().desugar (original); - DefaultASTVisitor::visit (stmt); + ptr = std::move (desugared); } MatchArm @@ -84,7 +55,7 @@ ok_case (Builder &builder) patterns.emplace_back (std::move (val)); auto pattern_item = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (patterns))); + new TupleStructItemsNoRest (std::move (patterns))); auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( builder.path_in_expression (LangItem::Kind::RESULT_OK), std::move (pattern_item))); @@ -99,13 +70,19 @@ ok_case (Builder &builder) MatchCase err_case (Builder &builder) { + // TODO: We need to handle the case where there is an enclosing `try {}` + // block, as that will create an additional block label that we can break to. + // This allows try blocks to use the question mark operator without having the + // offending statement early return from the enclosing function + // FIXME: How to mark that there is an enclosing block label? + auto val = builder.identifier_pattern ("err"); auto patterns = std::vector<std::unique_ptr<Pattern>> (); patterns.emplace_back (std::move (val)); auto pattern_item = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (patterns))); + new TupleStructItemsNoRest (std::move (patterns))); auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( builder.path_in_expression (LangItem::Kind::RESULT_ERR), std::move (pattern_item))); @@ -154,14 +131,5 @@ DesugarQuestionMark::desugar (ErrorPropagationExpr &expr) expr.get_locus ())); } -void -DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr) -{ - auto original = static_cast<ErrorPropagationExpr &> (*ptr); - auto desugared = desugar (original); - - ptr = std::move (desugared); -} - } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-question-mark.h b/gcc/rust/ast/rust-desugar-question-mark.h index e4c513f..542c52b 100644 --- a/gcc/rust/ast/rust-desugar-question-mark.h +++ b/gcc/rust/ast/rust-desugar-question-mark.h @@ -19,9 +19,7 @@ #ifndef RUST_DESUGAR_QUESTION_MARK #define RUST_DESUGAR_QUESTION_MARK -#include "rust-ast-visitor.h" #include "rust-expr.h" -#include "rust-stmt.h" namespace Rust { namespace AST { @@ -56,21 +54,15 @@ namespace AST { // } // } // ``` -class DesugarQuestionMark : public DefaultASTVisitor +class DesugarQuestionMark { - using DefaultASTVisitor::visit; - public: - DesugarQuestionMark (); - void go (AST::Crate &); + static void go (std::unique_ptr<Expr> &ptr); private: - void desugar_and_replace (std::unique_ptr<Expr> &ptr); - std::unique_ptr<Expr> desugar (ErrorPropagationExpr &); + DesugarQuestionMark (); - void visit (AST::ExprStmt &) override; - void visit (AST::CallExpr &) override; - void visit (AST::LetStmt &) override; + std::unique_ptr<Expr> desugar (ErrorPropagationExpr &); }; } // namespace AST diff --git a/gcc/rust/ast/rust-desugar-try-block.cc b/gcc/rust/ast/rust-desugar-try-block.cc new file mode 100644 index 0000000..07f06aa --- /dev/null +++ b/gcc/rust/ast/rust-desugar-try-block.cc @@ -0,0 +1,62 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-try-block.h" +#include "rust-ast-builder.h" +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +DesugarTryBlock::DesugarTryBlock () {} + +void +DesugarTryBlock::go (std::unique_ptr<Expr> &ptr) +{ + rust_assert (ptr->get_expr_kind () == Expr::Kind::Try); + + auto original = static_cast<TryExpr &> (*ptr); + auto desugared = DesugarTryBlock ().desugar (original); + + ptr = std::move (desugared); +} + +std::unique_ptr<Expr> +DesugarTryBlock::desugar (TryExpr &expr) +{ + auto builder = Builder (expr.get_locus ()); + auto &block = expr.get_block_expr (); + + if (block.has_statements ()) + rust_sorry_at (expr.get_locus (), + "cannot desugar try-blocks with statements"); + + auto tail_expr = builder.tuple (); + + if (block.has_tail_expr ()) + tail_expr = block.get_tail_expr ().clone_expr (); + + // Wrap in Try::from_ok call + auto from_ok = builder.path_in_expression (LangItem::Kind::TRY_FROM_OK); + auto call = builder.call (ptrify (from_ok), std::move (tail_expr)); + + return builder.block (std::move (call)); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-try-block.h b/gcc/rust/ast/rust-desugar-try-block.h new file mode 100644 index 0000000..bfd0463 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-try-block.h @@ -0,0 +1,42 @@ +// 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/>. + +#ifndef RUST_DESUGAR_TRY_BLOCK +#define RUST_DESUGAR_TRY_BLOCK + +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +// FIXME: Add documentation +class DesugarTryBlock +{ +public: + static void go (std::unique_ptr<Expr> &ptr); + +private: + DesugarTryBlock (); + + std::unique_ptr<Expr> desugar (TryExpr &); +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_TRY_BLOCK diff --git a/gcc/rust/ast/rust-desugar-while-let.cc b/gcc/rust/ast/rust-desugar-while-let.cc new file mode 100644 index 0000000..5eadc59 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-while-let.cc @@ -0,0 +1,104 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-while-let.h" +#include "rust-ast.h" +#include "rust-hir-map.h" +#include "rust-path.h" +#include "rust-pattern.h" +#include "rust-stmt.h" +#include "rust-expr.h" +#include "rust-ast-builder.h" + +namespace Rust { +namespace AST { + +DesugarWhileLet::DesugarWhileLet () {} + +MatchCase +DesugarWhileLet::DesugarCtx::make_break_arm () +{ + auto arm = builder.match_arm (builder.wildcard ()); + + auto break_expr + = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc)); + + return MatchCase (std::move (arm), std::move (break_expr)); +} + +MatchCase +DesugarWhileLet::DesugarCtx::make_continue_arm ( + std::unique_ptr<Pattern> &&pattern, std::unique_ptr<BlockExpr> &&body) +{ + auto arm = builder.match_arm (std::move (pattern)); + + return MatchCase (std::move (arm), std::move (body)); +} + +std::unique_ptr<Expr> +DesugarWhileLet::desugar (WhileLetLoopExpr &expr) +{ + rust_assert (expr.get_patterns ().size () == 1); + + auto pattern = expr.get_patterns ()[0]->clone_pattern (); + auto body = expr.get_loop_block ().clone_block_expr (); + auto scrutinee = expr.get_scrutinee_expr ().clone_expr (); + + auto ctx = DesugarCtx (expr.get_locus ()); + + // _ => break, + auto break_arm = ctx.make_break_arm (); + + // <pattern> => <body>, + auto continue_arm + = ctx.make_continue_arm (std::move (pattern), std::move (body)); + + // match <scrutinee> { + // <continue_arm> + // <break_arm> + // } + auto match_expr + = ctx.builder.match (std::move (scrutinee), + {std::move (continue_arm), std::move (break_arm)}); + + auto loop_stmts = std::vector<std::unique_ptr<Stmt>> (); + loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_expr))); + + // loop { + // <match_expr> + // } + return ctx.builder.loop (std::move (loop_stmts)); +} + +void +DesugarWhileLet::go (std::unique_ptr<Expr> &ptr) +{ + rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop); + + auto &loop = static_cast<BaseLoopExpr &> (*ptr); + + rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::WhileLet); + + auto &while_let = static_cast<WhileLetLoopExpr &> (loop); + auto desugared = DesugarWhileLet ().desugar (while_let); + + ptr = std::move (desugared); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-while-let.h b/gcc/rust/ast/rust-desugar-while-let.h new file mode 100644 index 0000000..60e0693 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-while-let.h @@ -0,0 +1,71 @@ +// 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/>. + +#ifndef RUST_DESUGAR_WHILE_LET_H +#define RUST_DESUGAR_WHILE_LET_H + +#include "rust-ast-builder.h" +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +// Desugar while-let into a set of other AST nodes. The desugar is of the +// following form: +// +// ``` +// whilet let <pat> = <expr> <body> +// ``` +// +// becomes: +// +// ``` +// loop { +// match <expr> { +// <pat> => <body>, +// _ => break +// } +// } +// ``` +class DesugarWhileLet +{ +public: + static void go (std::unique_ptr<Expr> &ptr); + +private: + DesugarWhileLet (); + + struct DesugarCtx + { + DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {} + + Builder builder; + location_t loc; + + MatchCase make_break_arm (); + MatchCase make_continue_arm (std::unique_ptr<Pattern> &&pattern, + std::unique_ptr<BlockExpr> &&body); + }; + + std::unique_ptr<Expr> desugar (WhileLetLoopExpr &expr); +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_WHILE_LET_H diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index cff09fe..3c36238 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1,6 +1,7 @@ #ifndef RUST_AST_EXPR_H #define RUST_AST_EXPR_H +#include "optional.h" #include "rust-ast.h" #include "rust-common.h" #include "rust-path.h" @@ -31,11 +32,6 @@ public: {} // Returns whether the LoopLabel is in an error state. - bool is_error () const { return label.is_error (); } - - // Creates an error state LoopLabel. - static LoopLabel error () { return LoopLabel (Lifetime::error ()); } - location_t get_locus () const { return locus; } Lifetime &get_lifetime () { return label; } @@ -187,9 +183,13 @@ public: AttrInputMacro (AttrInputMacro &&oth) : macro (std::move (oth.macro)) {} - void operator= (const AttrInputMacro &oth); + AttrInputMacro &operator= (const AttrInputMacro &oth); - void operator= (AttrInputMacro &&oth) { macro = std::move (oth.macro); } + AttrInputMacro &operator= (AttrInputMacro &&oth) + { + macro = std::move (oth.macro); + return *this; + } std::string as_string () const override; @@ -249,40 +249,60 @@ protected: } }; -// more generic meta item "path = lit" form -class MetaItemPathLit : public MetaItem +// more generic meta item "path = expr" form +class MetaItemPathExpr : public MetaItem { SimplePath path; - LiteralExpr lit; + std::unique_ptr<Expr> expr; public: - MetaItemPathLit (SimplePath path, LiteralExpr lit_expr) - : path (std::move (path)), lit (std::move (lit_expr)) + MetaItemPathExpr (SimplePath path, std::unique_ptr<Expr> expr) + : path (std::move (path)), expr (std::move (expr)) + {} + + MetaItemPathExpr (const MetaItemPathExpr &other) + : MetaItem (other), path (other.path), expr (other.expr->clone_expr ()) {} + MetaItemPathExpr (MetaItemPathExpr &&) = default; + + MetaItemPathExpr &operator= (MetaItemPathExpr &&) = default; + + MetaItemPathExpr operator= (const MetaItemPathExpr &other) + { + MetaItem::operator= (other); + path = other.path; + expr = other.expr->clone_expr (); + return *this; + } + SimplePath get_path () const { return path; } SimplePath &get_path () { return path; } - LiteralExpr get_literal () const { return lit; } + Expr &get_expr () { return *expr; } - LiteralExpr &get_literal () { return lit; } + std::unique_ptr<Expr> &get_expr_ptr () { return expr; } std::string as_string () const override { - return path.as_string () + " = " + lit.as_string (); + return path.as_string () + " = " + expr->as_string (); } MetaItem::ItemKind get_item_kind () const override { - return MetaItem::ItemKind::PathLit; + return MetaItem::ItemKind::PathExpr; } - // There are two Locations in MetaItemPathLit (path and lit_expr), + // There are two Locations in MetaItemPathExpr (path and expr), // we have no idea use which of them, just simply return UNKNOWN_LOCATION // now. // Maybe we will figure out when we really need the location in the future. - location_t get_locus () const override { return UNKNOWN_LOCATION; } + location_t get_locus () const override + { + rust_unreachable (); + return UNKNOWN_LOCATION; + } void accept_vis (ASTVisitor &vis) override; @@ -294,9 +314,9 @@ public: protected: // Use covariance to implement clone function as returning this type - MetaItemPathLit *clone_meta_item_inner_impl () const override + MetaItemPathExpr *clone_meta_item_inner_impl () const override { - return new MetaItemPathLit (*this); + return new MetaItemPathExpr (*this); } }; @@ -400,6 +420,14 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_borrowed_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + bool has_borrow_expr () const { return main_or_left_expr != nullptr; } + bool get_is_mut () const { return mutability == Mutability::Mut; } Mutability get_mutability () const { return mutability; } @@ -439,6 +467,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_dereferenced_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Dereference; } protected: @@ -472,6 +506,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_propagating_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::ErrorPropagation; @@ -520,6 +560,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_negated_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Negation; } protected: @@ -849,6 +895,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_casted_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + // TODO: is this better? Or is a "vis_block" better? TypeNoBounds &get_type_to_cast_to () { @@ -856,6 +908,12 @@ public: return *type_to_convert_to; } + std::unique_ptr<TypeNoBounds> &get_type_to_cast_to_ptr () + { + rust_assert (type_to_convert_to != nullptr); + return type_to_convert_to; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; } protected: @@ -1165,11 +1223,11 @@ protected: // Value array elements class ArrayElemsValues : public ArrayElems { - std::vector<std::unique_ptr<Expr> > values; + std::vector<std::unique_ptr<Expr>> values; location_t locus; public: - ArrayElemsValues (std::vector<std::unique_ptr<Expr> > elems, location_t locus) + ArrayElemsValues (std::vector<std::unique_ptr<Expr>> elems, location_t locus) : ArrayElems (), values (std::move (elems)), locus (locus) {} @@ -1197,14 +1255,16 @@ public: std::string as_string () const override; + location_t get_locus () const { return locus; } + void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Expr> > &get_values () const + const std::vector<std::unique_ptr<Expr>> &get_values () const { return values; } - std::vector<std::unique_ptr<Expr> > &get_values () { return values; } + std::vector<std::unique_ptr<Expr>> &get_values () { return values; } size_t get_num_values () const { return values.size (); } @@ -1219,6 +1279,8 @@ protected: class ArrayElemsCopied : public ArrayElems { std::unique_ptr<Expr> elem_to_copy; + + // TODO: This should be replaced by a ConstExpr std::unique_ptr<Expr> num_copies; location_t locus; @@ -1251,6 +1313,8 @@ public: std::string as_string () const override; + location_t get_locus () const { return locus; } + void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? @@ -1260,6 +1324,12 @@ public: return *elem_to_copy; } + std::unique_ptr<Expr> &get_elem_to_copy_ptr () + { + rust_assert (elem_to_copy != nullptr); + return elem_to_copy; + } + // TODO: is this better? Or is a "vis_block" better? Expr &get_num_copies () { @@ -1267,6 +1337,12 @@ public: return *num_copies; } + std::unique_ptr<Expr> &get_num_copies_ptr () + { + rust_assert (num_copies != nullptr); + return num_copies; + } + protected: ArrayElemsCopied *clone_array_elems_impl () const override { @@ -1446,6 +1522,12 @@ public: return *array_expr; } + std::unique_ptr<Expr> &get_array_expr_ptr () + { + rust_assert (array_expr != nullptr); + return array_expr; + } + // TODO: is this better? Or is a "vis_block" better? Expr &get_index_expr () { @@ -1453,6 +1535,12 @@ public: return *index_expr; } + std::unique_ptr<Expr> &get_index_expr_ptr () + { + rust_assert (index_expr != nullptr); + return index_expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -1477,7 +1565,7 @@ class TupleExpr : public ExprWithoutBlock { std::vector<Attribute> outer_attrs; std::vector<Attribute> inner_attrs; - std::vector<std::unique_ptr<Expr> > tuple_elems; + std::vector<std::unique_ptr<Expr>> tuple_elems; location_t locus; // TODO: find another way to store this to save memory? @@ -1497,7 +1585,7 @@ public: outer_attrs = std::move (new_attrs); } - TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements, + TupleExpr (std::vector<std::unique_ptr<Expr>> tuple_elements, std::vector<Attribute> inner_attribs, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), @@ -1548,14 +1636,11 @@ public: bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const - { - return tuple_elems; - } - std::vector<std::unique_ptr<Expr> > &get_tuple_elems () + const std::vector<std::unique_ptr<Expr>> &get_tuple_elems () const { return tuple_elems; } + std::vector<std::unique_ptr<Expr>> &get_tuple_elems () { return tuple_elems; } bool is_unit () const { return tuple_elems.size () == 0; } @@ -1580,6 +1665,7 @@ class TupleIndexExpr : public ExprWithoutBlock TupleIndex tuple_index; location_t locus; + bool to_strip; // i.e. pair.0 @@ -1591,13 +1677,15 @@ public: TupleIndexExpr (std::unique_ptr<Expr> tuple_expr, TupleIndex index, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), - tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus) + tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus), + to_strip (false) {} // Copy constructor requires a clone for tuple_expr TupleIndexExpr (TupleIndexExpr const &other) : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), - tuple_index (other.tuple_index), locus (other.locus) + tuple_index (other.tuple_index), locus (other.locus), + to_strip (other.to_strip) { // guard to prevent null dereference (only required if error state) if (other.tuple_expr != nullptr) @@ -1611,6 +1699,7 @@ public: tuple_index = other.tuple_index; locus = other.locus; outer_attrs = other.outer_attrs; + to_strip = other.to_strip; // guard to prevent null dereference (only required if error state) if (other.tuple_expr != nullptr) @@ -1630,8 +1719,8 @@ public: void accept_vis (ASTVisitor &vis) override; // Invalid if tuple expr is null, so base stripping on that. - void mark_for_strip () override { tuple_expr = nullptr; } - bool is_marked_for_strip () const override { return tuple_expr == nullptr; } + void mark_for_strip () override { to_strip = true; } + bool is_marked_for_strip () const override { return to_strip; } // TODO: is this better? Or is a "vis_block" better? Expr &get_tuple_expr () @@ -1640,6 +1729,12 @@ public: return *tuple_expr; } + std::unique_ptr<Expr> &get_tuple_expr_ptr () + { + rust_assert (tuple_expr != nullptr); + return tuple_expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -1780,12 +1875,20 @@ public: std::string as_string () const; + location_t get_locus () const { return locus; } + // TODO: is this better? Or is a "vis_block" better? Expr &get_base_struct () { rust_assert (base_struct != nullptr); return *base_struct; } + + std::unique_ptr<Expr> &get_base_struct_ptr () + { + rust_assert (base_struct != nullptr); + return base_struct; + } }; /* Base AST node for a single struct expression field (in struct instance @@ -1902,6 +2005,12 @@ public: rust_assert (value != nullptr); return *value; } + + std::unique_ptr<Expr> &get_value_ptr () + { + rust_assert (value != nullptr); + return value; + } }; // Identifier and value variant of StructExprField AST node @@ -1977,7 +2086,7 @@ protected: class StructExprStructFields : public StructExprStruct { // std::vector<StructExprField> fields; - std::vector<std::unique_ptr<StructExprField> > fields; + std::vector<std::unique_ptr<StructExprField>> fields; // bool has_struct_base; StructBase struct_base; @@ -1990,8 +2099,8 @@ public: // Constructor for StructExprStructFields when no struct base is used StructExprStructFields ( PathInExpression struct_path, - std::vector<std::unique_ptr<StructExprField> > expr_fields, - location_t locus, StructBase base_struct = StructBase::error (), + std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus, + StructBase base_struct = StructBase::error (), std::vector<Attribute> inner_attribs = std::vector<Attribute> (), std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : StructExprStruct (std::move (struct_path), std::move (inner_attribs), @@ -2028,11 +2137,11 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector<std::unique_ptr<StructExprField> > &get_fields () + std::vector<std::unique_ptr<StructExprField>> &get_fields () { return fields; } - const std::vector<std::unique_ptr<StructExprField> > &get_fields () const + const std::vector<std::unique_ptr<StructExprField>> &get_fields () const { return fields; } @@ -2089,7 +2198,7 @@ class CallExpr : public ExprWithoutBlock { std::vector<Attribute> outer_attrs; std::unique_ptr<Expr> function; - std::vector<std::unique_ptr<Expr> > params; + std::vector<std::unique_ptr<Expr>> params; location_t locus; public: @@ -2098,7 +2207,7 @@ public: std::string as_string () const override; CallExpr (std::unique_ptr<Expr> function_expr, - std::vector<std::unique_ptr<Expr> > function_params, + std::vector<std::unique_ptr<Expr>> function_params, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), function (std::move (function_expr)), @@ -2155,11 +2264,11 @@ public: bool is_marked_for_strip () const override { return function == nullptr; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Expr> > &get_params () const + const std::vector<std::unique_ptr<Expr>> &get_params () const { return params; } - std::vector<std::unique_ptr<Expr> > &get_params () { return params; } + std::vector<std::unique_ptr<Expr>> &get_params () { return params; } // TODO: is this better? Or is a "vis_block" better? Expr &get_function_expr () @@ -2195,7 +2304,7 @@ class MethodCallExpr : public ExprWithoutBlock std::vector<Attribute> outer_attrs; std::unique_ptr<Expr> receiver; PathExprSegment method_name; - std::vector<std::unique_ptr<Expr> > params; + std::vector<std::unique_ptr<Expr>> params; location_t locus; public: @@ -2203,7 +2312,7 @@ public: MethodCallExpr (std::unique_ptr<Expr> call_receiver, PathExprSegment method_path, - std::vector<std::unique_ptr<Expr> > method_params, + std::vector<std::unique_ptr<Expr>> method_params, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), receiver (std::move (call_receiver)), @@ -2259,11 +2368,11 @@ public: bool is_marked_for_strip () const override { return receiver == nullptr; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Expr> > &get_params () const + const std::vector<std::unique_ptr<Expr>> &get_params () const { return params; } - std::vector<std::unique_ptr<Expr> > &get_params () { return params; } + std::vector<std::unique_ptr<Expr>> &get_params () { return params; } // TODO: is this better? Or is a "vis_block" better? Expr &get_receiver_expr () @@ -2272,6 +2381,12 @@ public: return *receiver; } + std::unique_ptr<Expr> &get_receiver_expr_ptr () + { + rust_assert (receiver != nullptr); + return receiver; + } + const PathExprSegment &get_method_name () const { return method_name; } PathExprSegment &get_method_name () { return method_name; } @@ -2360,6 +2475,12 @@ public: return *receiver; } + std::unique_ptr<Expr> &get_receiver_expr_ptr () + { + rust_assert (receiver != nullptr); + return receiver; + } + Identifier get_field_name () const { return field; } const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } @@ -2459,6 +2580,12 @@ public: return *pattern; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (pattern != nullptr); + return pattern; + } + Type &get_type () { rust_assert (has_type_given ()); @@ -2509,6 +2636,9 @@ public: bool get_has_move () const { return has_move; } Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; } + + virtual Expr &get_definition_expr () = 0; + virtual std::unique_ptr<Expr> &get_definition_expr_ptr () = 0; }; // Represents a non-type-specified closure expression AST node @@ -2568,12 +2698,18 @@ public: return closure_inner == nullptr; } - Expr &get_definition_expr () + Expr &get_definition_expr () override { rust_assert (closure_inner != nullptr); return *closure_inner; } + std::unique_ptr<Expr> &get_definition_expr_ptr () override + { + rust_assert (closure_inner != nullptr); + return closure_inner; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2588,9 +2724,9 @@ class BlockExpr : public ExprWithBlock { std::vector<Attribute> outer_attrs; std::vector<Attribute> inner_attrs; - std::vector<std::unique_ptr<Stmt> > statements; + std::vector<std::unique_ptr<Stmt>> statements; std::unique_ptr<Expr> expr; - LoopLabel label; + tl::optional<LoopLabel> label; location_t start_locus; location_t end_locus; bool marked_for_strip = false; @@ -2604,11 +2740,12 @@ public: // Returns whether the block contains a final expression. bool has_tail_expr () const { return expr != nullptr; } - BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements, + BlockExpr (std::vector<std::unique_ptr<Stmt>> block_statements, std::unique_ptr<Expr> block_expr, std::vector<Attribute> inner_attribs, - std::vector<Attribute> outer_attribs, LoopLabel label, - location_t start_locus, location_t end_locus) + std::vector<Attribute> outer_attribs, + tl::optional<LoopLabel> label, location_t start_locus, + location_t end_locus) : outer_attrs (std::move (outer_attribs)), inner_attrs (std::move (inner_attribs)), statements (std::move (block_statements)), expr (std::move (block_expr)), @@ -2682,11 +2819,11 @@ public: const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } - const std::vector<std::unique_ptr<Stmt> > &get_statements () const + const std::vector<std::unique_ptr<Stmt>> &get_statements () const { return statements; } - std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; } + std::vector<std::unique_ptr<Stmt>> &get_statements () { return statements; } // TODO: is this better? Or is a "vis_block" better? Expr &get_tail_expr () @@ -2727,8 +2864,8 @@ public: outer_attrs = std::move (new_attrs); } - bool has_label () { return !label.is_error (); } - LoopLabel &get_label () { return label; } + bool has_label () { return label.has_value (); } + LoopLabel &get_label () { return label.value (); } Expr::Kind get_expr_kind () const override { return Expr::Kind::Block; } @@ -2748,13 +2885,163 @@ protected: } }; +class AnonConst : public ExprWithBlock +{ +public: + enum class Kind + { + Explicit, + DeferredInference, + }; + + AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION) + : ExprWithBlock (), locus (locus), kind (Kind::Explicit), + expr (std::move (expr)) + { + rust_assert (this->expr.value ()); + } + + AnonConst (location_t locus = UNKNOWN_LOCATION) + : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference), + expr (tl::nullopt) + {} + + AnonConst (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + kind = other.kind; + + if (other.expr) + expr = other.expr.value ()->clone_expr (); + } + + AnonConst operator= (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + kind = other.kind; + + if (other.expr) + expr = other.expr.value ()->clone_expr (); + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; } + + location_t get_locus () const override { return locus; } + + Expr &get_inner_expr () + { + rust_assert (expr.has_value ()); + return *expr.value (); + } + + std::unique_ptr<Expr> &get_inner_expr_ptr () + { + rust_assert (expr.has_value ()); + return expr.value (); + } + + NodeId get_node_id () const override { return node_id; } + + /* FIXME: AnonConst are always "internal" and should not have outer attributes + * - is that true? Or should we instead call + * expr->get_outer_attrs()/expr->set_outer_attrs() */ + + std::vector<Attribute> &get_outer_attrs () override + { + static auto attrs = std::vector<Attribute> (); + return attrs; + } + + void set_outer_attrs (std::vector<Attribute>) override {} + + /* FIXME: Likewise for mark_for_strip() ? */ + void mark_for_strip () override {} + bool is_marked_for_strip () const override { return false; } + + void accept_vis (ASTVisitor &vis) override; + + bool is_deferred () const { return kind == Kind::DeferredInference; } + +private: + location_t locus; + Kind kind; + tl::optional<std::unique_ptr<Expr>> expr; + + AnonConst *clone_expr_with_block_impl () const override + { + return new AnonConst (*this); + } +}; + +class ConstBlock : public ExprWithBlock +{ +public: + ConstBlock (AnonConst &&expr, location_t locus = UNKNOWN_LOCATION, + std::vector<Attribute> &&outer_attrs = {}) + : ExprWithBlock (), expr (std::move (expr)), + outer_attrs (std::move (outer_attrs)), locus (locus) + {} + + ConstBlock (const ConstBlock &other) + : ExprWithBlock (other), expr (other.expr), outer_attrs (other.outer_attrs), + locus (other.locus) + {} + + ConstBlock operator= (const ConstBlock &other) + { + expr = other.expr; + node_id = other.node_id; + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstBlock; } + + AnonConst &get_const_expr () { return expr; } + + void accept_vis (ASTVisitor &vis) override; + + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + location_t get_locus () const override { return locus; } + + bool is_marked_for_strip () const override { return marked_for_strip; } + void mark_for_strip () override { marked_for_strip = true; } + +private: + AnonConst expr; + + std::vector<Attribute> outer_attrs; + location_t locus; + bool marked_for_strip = false; + + ConstBlock *clone_expr_with_block_impl () const override + { + return new ConstBlock (*this); + } +}; + // Represents a type-specified closure expression AST node class ClosureExprInnerTyped : public ClosureExpr { // TODO: spec says typenobounds std::unique_ptr<Type> return_type; - std::unique_ptr<BlockExpr> - expr; // only used because may be polymorphic in future + std::unique_ptr<Expr> expr; // only used because may be polymorphic in future public: std::string as_string () const override; @@ -2778,7 +3065,7 @@ public: { // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) - expr = other.expr->clone_block_expr (); + expr = other.expr->clone_expr (); if (other.return_type != nullptr) return_type = other.return_type->clone_type (); } @@ -2793,7 +3080,7 @@ public: // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) - expr = other.expr->clone_block_expr (); + expr = other.expr->clone_expr (); else expr = nullptr; if (other.return_type != nullptr) @@ -2816,12 +3103,19 @@ public: bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - BlockExpr &get_definition_block () + Expr &get_definition_expr () override { rust_assert (expr != nullptr); return *expr; } + std::unique_ptr<Expr> &get_definition_expr_ptr () override + { + rust_assert (expr != nullptr); + + return expr; + } + // TODO: is this better? Or is a "vis_block" better? Type &get_return_type () { @@ -2848,7 +3142,7 @@ protected: class ContinueExpr : public ExprWithoutBlock { std::vector<Attribute> outer_attrs; - Lifetime label; + tl::optional<Lifetime> label; location_t locus; // TODO: find another way to store this to save memory? @@ -2858,11 +3152,11 @@ public: std::string as_string () const override; // Returns true if the continue expr has a label. - bool has_label () const { return !label.is_error (); } + bool has_label () const { return label.has_value (); } // Constructor for a ContinueExpr with a label. - ContinueExpr (Lifetime label, std::vector<Attribute> outer_attribs, - location_t locus) + ContinueExpr (tl::optional<Lifetime> label, + std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), label (std::move (label)), locus (locus) {} @@ -2883,7 +3177,11 @@ public: outer_attrs = std::move (new_attrs); } - Lifetime &get_label () { return label; } + Lifetime &get_label_unchecked () { return label.value (); } + const Lifetime &get_label_unchecked () const { return label.value (); } + + tl::optional<Lifetime> &get_label () { return label; } + const tl::optional<Lifetime> &get_label () const { return label; } Expr::Kind get_expr_kind () const override { return Expr::Kind::Continue; } @@ -2901,7 +3199,7 @@ protected: class BreakExpr : public ExprWithoutBlock { std::vector<Attribute> outer_attrs; - LoopLabel label; + tl::optional<LoopLabel> label; std::unique_ptr<Expr> break_expr; location_t locus; @@ -2912,14 +3210,15 @@ public: std::string as_string () const override; // Returns whether the break expression has a label or not. - bool has_label () const { return !label.is_error (); } + bool has_label () const { return label.has_value (); } /* Returns whether the break expression has an expression used in the break or * not. */ bool has_break_expr () const { return break_expr != nullptr; } // Constructor for a break expression - BreakExpr (LoopLabel break_label, std::unique_ptr<Expr> expr_in_break, + BreakExpr (tl::optional<LoopLabel> break_label, + std::unique_ptr<Expr> expr_in_break, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), label (std::move (break_label)), break_expr (std::move (expr_in_break)), locus (locus) @@ -2973,6 +3272,12 @@ public: return *break_expr; } + std::unique_ptr<Expr> &get_break_expr_ptr () + { + rust_assert (has_break_expr ()); + return break_expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -2981,7 +3286,11 @@ public: outer_attrs = std::move (new_attrs); } - LoopLabel &get_label () { return label; } + LoopLabel &get_label_unchecked () { return label.value (); } + const LoopLabel &get_label_unchecked () const { return label.value (); } + + tl::optional<LoopLabel> &get_label () { return label; } + const tl::optional<LoopLabel> &get_label () const { return label; } Expr::Kind get_expr_kind () const override { return Expr::Kind::Break; } @@ -2999,6 +3308,10 @@ class RangeExpr : public ExprWithoutBlock { location_t locus; + // Some visitors still check for attributes on RangeExprs, and they will need + // to be supported in the future - so keep that for now + std::vector<Attribute> empty_attributes = {}; + protected: // outer attributes not allowed before range expressions RangeExpr (location_t locus) : locus (locus) {} @@ -3008,15 +3321,11 @@ public: std::vector<Attribute> &get_outer_attrs () override final { - // RangeExpr cannot have any outer attributes - rust_assert (false); + return empty_attributes; } // should never be called - error if called - void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override - { - rust_assert (false); - } + void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override {} Expr::Kind get_expr_kind () const override { return Expr::Kind::Range; } }; @@ -3096,6 +3405,18 @@ public: return *to; } + std::unique_ptr<Expr> &get_from_expr_ptr () + { + rust_assert (from != nullptr); + return from; + } + + std::unique_ptr<Expr> &get_to_expr_ptr () + { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3157,6 +3478,12 @@ public: return *from; } + std::unique_ptr<Expr> &get_from_expr_ptr () + { + rust_assert (from != nullptr); + return from; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3219,6 +3546,12 @@ public: return *to; } + std::unique_ptr<Expr> &get_to_expr_ptr () + { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3332,6 +3665,18 @@ public: return *to; } + std::unique_ptr<Expr> &get_from_expr_ptr () + { + rust_assert (from != nullptr); + return from; + } + + std::unique_ptr<Expr> &get_to_expr_ptr () + { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3394,6 +3739,12 @@ public: return *to; } + std::unique_ptr<Expr> &get_to_expr_ptr () + { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3467,6 +3818,12 @@ public: return *expr; } + std::unique_ptr<Expr> &get_boxed_expr_ptr () + { + rust_assert (expr != nullptr); + return expr; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Box; } protected: @@ -3548,6 +3905,12 @@ public: return *return_expr; } + std::unique_ptr<Expr> &get_returned_expr_ptr () + { + rust_assert (return_expr != nullptr); + return return_expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -3567,6 +3930,83 @@ protected: } }; +// Try expression AST node representation +class TryExpr : public ExprWithBlock +{ + std::vector<Attribute> outer_attrs; + std::unique_ptr<BlockExpr> block_expr; + location_t locus; + + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + +public: + std::string as_string () const override; + + // Constructor for ReturnExpr. + TryExpr (std::unique_ptr<BlockExpr> block_expr, + std::vector<Attribute> outer_attribs, location_t locus) + : outer_attrs (std::move (outer_attribs)), + block_expr (std::move (block_expr)), locus (locus) + { + rust_assert (this->block_expr); + } + + // Copy constructor with clone + TryExpr (TryExpr const &other) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + block_expr (other.block_expr->clone_block_expr ()), locus (other.locus), + marked_for_strip (other.marked_for_strip) + {} + + // Overloaded assignment operator to clone return_expr pointer + TryExpr &operator= (TryExpr const &other) + { + ExprWithBlock::operator= (other); + locus = other.locus; + marked_for_strip = other.marked_for_strip; + outer_attrs = other.outer_attrs; + + block_expr = other.block_expr->clone_block_expr (); + + return *this; + } + + // move constructors + TryExpr (TryExpr &&other) = default; + TryExpr &operator= (TryExpr &&other) = default; + + location_t get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + + // TODO: is this better? Or is a "vis_block" better? + BlockExpr &get_block_expr () { return *block_expr; } + std::unique_ptr<BlockExpr> &get_block_expr_ptr () { return block_expr; } + + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Try; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TryExpr *clone_expr_with_block_impl () const override + { + return new TryExpr (*this); + } +}; + // Forward decl - defined in rust-macro.h class MacroInvocation; @@ -3632,6 +4072,12 @@ public: return *expr; } + std::unique_ptr<BlockExpr> &get_block_expr_ptr () + { + rust_assert (expr != nullptr); + return expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -3657,7 +4103,7 @@ class BaseLoopExpr : public ExprWithBlock protected: // protected to allow subclasses better use of them std::vector<Attribute> outer_attrs; - LoopLabel loop_label; + tl::optional<LoopLabel> loop_label; std::unique_ptr<BlockExpr> loop_block; private: @@ -3666,7 +4112,7 @@ private: protected: // Constructor for BaseLoopExpr BaseLoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : outer_attrs (std::move (outer_attribs)), @@ -3706,9 +4152,10 @@ protected: BaseLoopExpr &operator= (BaseLoopExpr &&other) = default; public: - bool has_loop_label () const { return !loop_label.is_error (); } + bool has_loop_label () const { return loop_label.has_value (); } - LoopLabel &get_loop_label () { return loop_label; } + LoopLabel &get_loop_label () { return loop_label.value (); } + const LoopLabel &get_loop_label () const { return loop_label.value (); } location_t get_locus () const override final { return locus; } @@ -3723,6 +4170,12 @@ public: return *loop_block; } + std::unique_ptr<BlockExpr> &get_loop_block_ptr () + { + rust_assert (loop_block != nullptr); + return loop_block; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -3752,7 +4205,7 @@ public: // Constructor for LoopExpr LoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label), std::move (outer_attribs)) @@ -3785,7 +4238,7 @@ public: // Constructor for while loop with loop label WhileLoopExpr (std::unique_ptr<Expr> loop_condition, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label), @@ -3823,6 +4276,12 @@ public: return *condition; } + std::unique_ptr<Expr> &get_predicate_expr_ptr () + { + rust_assert (condition != nullptr); + return condition; + } + BaseLoopExpr::Kind get_loop_kind () const override { return BaseLoopExpr::Kind::While; @@ -3841,17 +4300,17 @@ protected: class WhileLetLoopExpr : public BaseLoopExpr { // MatchArmPatterns patterns; - std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined + std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined std::unique_ptr<Expr> scrutinee; public: std::string as_string () const override; // Constructor with a loop label - WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, + WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns, std::unique_ptr<Expr> scrutinee, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label), @@ -3901,12 +4360,18 @@ public: return *scrutinee; } + std::unique_ptr<Expr> &get_scrutinee_expr_ptr () + { + rust_assert (scrutinee != nullptr); + return scrutinee; + } + // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Pattern> > &get_patterns () const + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { return match_arm_patterns; } - std::vector<std::unique_ptr<Pattern> > &get_patterns () + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return match_arm_patterns; } @@ -3938,7 +4403,7 @@ public: ForLoopExpr (std::unique_ptr<Pattern> loop_pattern, std::unique_ptr<Expr> iterator_expr, std::unique_ptr<BlockExpr> loop_body, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (loop_body), locus, std::move (loop_label), std::move (outer_attribs)), @@ -3978,6 +4443,12 @@ public: return *iterator_expr; } + std::unique_ptr<Expr> &get_iterator_expr_ptr () + { + rust_assert (iterator_expr != nullptr); + return iterator_expr; + } + // TODO: is this better? Or is a "vis_block" better? Pattern &get_pattern () { @@ -3985,6 +4456,12 @@ public: return *pattern; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (pattern != nullptr); + return pattern; + } + BaseLoopExpr::Kind get_loop_kind () const override { return BaseLoopExpr::Kind::For; @@ -4189,7 +4666,7 @@ protected: class IfLetExpr : public ExprWithBlock { std::vector<Attribute> outer_attrs; - std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined + std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined std::unique_ptr<Expr> value; std::unique_ptr<BlockExpr> if_block; location_t locus; @@ -4197,7 +4674,7 @@ class IfLetExpr : public ExprWithBlock public: std::string as_string () const override; - IfLetExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, + IfLetExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns, std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, std::vector<Attribute> outer_attrs, location_t locus) : outer_attrs (std::move (outer_attrs)), @@ -4291,11 +4768,11 @@ public: } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Pattern> > &get_patterns () const + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { return match_arm_patterns; } - std::vector<std::unique_ptr<Pattern> > &get_patterns () + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return match_arm_patterns; } @@ -4335,11 +4812,11 @@ class IfLetExprConseqElse : public IfLetExpr public: std::string as_string () const override; - IfLetExprConseqElse ( - std::vector<std::unique_ptr<Pattern> > match_arm_patterns, - std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, - std::unique_ptr<ExprWithBlock> else_block, - std::vector<Attribute> outer_attrs, location_t locus) + IfLetExprConseqElse (std::vector<std::unique_ptr<Pattern>> match_arm_patterns, + std::unique_ptr<Expr> value, + std::unique_ptr<BlockExpr> if_block, + std::unique_ptr<ExprWithBlock> else_block, + std::vector<Attribute> outer_attrs, location_t locus) : IfLetExpr (std::move (match_arm_patterns), std::move (value), std::move (if_block), std::move (outer_attrs), locus), else_block (std::move (else_block)) @@ -4392,7 +4869,7 @@ struct MatchArm private: std::vector<Attribute> outer_attrs; // MatchArmPatterns patterns; - std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined + std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined // bool has_match_arm_guard; // inlined from MatchArmGuard @@ -4405,7 +4882,7 @@ public: bool has_match_arm_guard () const { return guard_expr != nullptr; } // Constructor for match arm with a guard expression - MatchArm (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, + MatchArm (std::vector<std::unique_ptr<Pattern>> match_arm_patterns, location_t locus, std::unique_ptr<Expr> guard_expr = nullptr, std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : outer_attrs (std::move (outer_attrs)), @@ -4457,7 +4934,7 @@ public: static MatchArm create_error () { location_t locus = UNDEF_LOCATION; - return MatchArm (std::vector<std::unique_ptr<Pattern> > (), locus); + return MatchArm (std::vector<std::unique_ptr<Pattern>> (), locus); } std::string as_string () const; @@ -4479,11 +4956,11 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - const std::vector<std::unique_ptr<Pattern> > &get_patterns () const + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { return match_arm_patterns; } - std::vector<std::unique_ptr<Pattern> > &get_patterns () + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return match_arm_patterns; } @@ -4637,6 +5114,12 @@ public: return *branch_value; } + std::unique_ptr<Expr> &get_scrutinee_expr_ptr () + { + rust_assert (branch_value != nullptr); + return branch_value; + } + const std::vector<MatchCase> &get_match_cases () const { return match_arms; } std::vector<MatchCase> &get_match_cases () { return match_arms; } @@ -4830,29 +5313,6 @@ enum class InlineAsmOption MAY_UNWIND = 1 << 8, }; -struct AnonConst -{ - NodeId id; - std::unique_ptr<Expr> expr; - AnonConst (NodeId id, std::unique_ptr<Expr> expr) - : id (id), expr (std::move (expr)) - { - rust_assert (this->expr != nullptr); - } - AnonConst (const AnonConst &other) - { - id = other.id; - expr = other.expr->clone_expr (); - } - - AnonConst operator= (const AnonConst &other) - { - id = other.id; - expr = other.expr->clone_expr (); - return *this; - } -}; - struct InlineAsmRegOrRegClass { enum Type @@ -4879,6 +5339,27 @@ struct InlineAsmRegOrRegClass location_t locus; }; +struct LlvmOperand +{ + std::string constraint; + std::unique_ptr<Expr> expr; + + LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr) + : constraint (constraint), expr (std::move (expr)) + {} + + LlvmOperand (const LlvmOperand &other) + : constraint (other.constraint), expr (other.expr->clone_expr ()) + {} + LlvmOperand &operator= (const LlvmOperand &other) + { + constraint = other.constraint; + expr = other.expr->clone_expr (); + + return *this; + } +}; + class InlineAsmOperand { public: @@ -5241,6 +5722,8 @@ struct InlineAsmTemplatePiece struct TupleClobber { + TupleClobber (std::string symbol, location_t loc) : symbol (symbol), loc (loc) + {} // as gccrs still doesn't contain a symbol class I have put them as strings std::string symbol; location_t loc; @@ -5252,6 +5735,7 @@ struct TupleTemplateStr location_t loc; std::string symbol; + location_t get_locus () { return loc; } TupleTemplateStr (location_t loc, const std::string &symbol) : loc (loc), symbol (symbol) {} @@ -5260,6 +5744,20 @@ struct TupleTemplateStr // Inline Assembly Node class InlineAsm : public ExprWithoutBlock { +public: + enum class Option + { + PURE = 1 << 0, + NOMEM = 1 << 1, + READONLY = 1 << 2, + PRESERVES_FLAGS = 1 << 3, + NORETURN = 1 << 4, + NOSTACK = 1 << 5, + ATT_SYNTAX = 1 << 6, + RAW = 1 << 7, + MAY_UNWIND = 1 << 8, + }; + private: location_t locus; // TODO: Not sure how outer_attrs plays with InlineAsm, I put it here in order @@ -5283,7 +5781,7 @@ public: std::map<std::string, int> named_args; std::set<int> reg_args; std::vector<TupleClobber> clobber_abi; - std::set<InlineAsmOption> options; + std::set<InlineAsm::Option> options; std::vector<location_t> line_spans; @@ -5314,7 +5812,7 @@ public: std::vector<TupleClobber> get_clobber_abi () { return clobber_abi; } - std::set<InlineAsmOption> get_options () { return options; } + std::set<InlineAsm::Option> get_options () { return options; } InlineAsm *clone_expr_without_block_impl () const override { @@ -5322,6 +5820,111 @@ public: } Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; } + + static std::string option_to_string (Option option) + { + switch (option) + { + case Option::PURE: + return "pure"; + case Option::NOMEM: + return "nomem"; + case Option::READONLY: + return "readonly"; + case Option::PRESERVES_FLAGS: + return "preserves_flags"; + case Option::NORETURN: + return "noreturn"; + case Option::NOSTACK: + return "nostack"; + case Option::ATT_SYNTAX: + return "att_syntax"; + case Option::RAW: + return "raw"; + case Option::MAY_UNWIND: + return "may_unwind"; + default: + rust_unreachable (); + } + } +}; + +class LlvmInlineAsm : public ExprWithoutBlock +{ + // llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile"); + // Asm, Outputs, Inputs, Clobbers, Options, + +public: + enum class Dialect + { + Att, + Intel, + }; + +private: + location_t locus; + std::vector<Attribute> outer_attrs; + std::vector<LlvmOperand> inputs; + std::vector<LlvmOperand> outputs; + std::vector<TupleTemplateStr> templates; + std::vector<TupleClobber> clobbers; + bool volatility; + bool align_stack; + Dialect dialect; + +public: + LlvmInlineAsm (location_t locus) : locus (locus) {} + + Dialect get_dialect () { return dialect; } + + location_t get_locus () const override { return locus; } + + void mark_for_strip () override {} + + bool is_marked_for_strip () const override { return false; } + + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void accept_vis (ASTVisitor &vis) override; + + std::string as_string () const override { return "InlineAsm AST Node"; } + + void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; } + + LlvmInlineAsm *clone_expr_without_block_impl () const override + { + return new LlvmInlineAsm (*this); + } + + std::vector<TupleTemplateStr> &get_templates () { return templates; } + const std::vector<TupleTemplateStr> &get_templates () const + { + return templates; + } + + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::LlvmInlineAsm; + } + + void set_align_stack (bool align_stack) { this->align_stack = align_stack; } + bool is_stack_aligned () { return align_stack; } + + void set_volatile (bool volatility) { this->volatility = volatility; } + bool is_volatile () { return volatility; } + + void set_dialect (Dialect dialect) { this->dialect = dialect; } + + void set_inputs (std::vector<LlvmOperand> operands) { inputs = operands; } + void set_outputs (std::vector<LlvmOperand> operands) { outputs = operands; } + + std::vector<LlvmOperand> &get_inputs () { return inputs; } + const std::vector<LlvmOperand> &get_inputs () const { return inputs; } + std::vector<LlvmOperand> &get_outputs () { return outputs; } + const std::vector<LlvmOperand> &get_outputs () const { return outputs; } + + std::vector<TupleClobber> &get_clobbers () { return clobbers; } + const std::vector<TupleClobber> &get_clobbers () const { return clobbers; } }; } // namespace AST diff --git a/gcc/rust/ast/rust-expression-yeast.cc b/gcc/rust/ast/rust-expression-yeast.cc new file mode 100644 index 0000000..7626abc --- /dev/null +++ b/gcc/rust/ast/rust-expression-yeast.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-expression-yeast.h" +#include "rust-ast-visitor.h" +#include "rust-desugar-question-mark.h" +#include "rust-desugar-try-block.h" +#include "rust-desugar-for-loops.h" +#include "rust-desugar-while-let.h" +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +void +ExpressionYeast::go (AST::Crate &crate) +{ + PointerVisitor::visit (crate); +} + +void +ExpressionYeast::dispatch_loops (std::unique_ptr<Expr> &loop_expr) +{ + auto &loop = static_cast<BaseLoopExpr &> (*loop_expr.get ()); + + switch (loop.get_loop_kind ()) + { + case BaseLoopExpr::Kind::For: + DesugarForLoops::go (loop_expr); + break; + case BaseLoopExpr::Kind::WhileLet: + DesugarWhileLet::go (loop_expr); + break; + default: + break; + } +} + +void +ExpressionYeast::reseat (std::unique_ptr<Expr> &expr) +{ + switch (expr->get_expr_kind ()) + { + case Expr::Kind::ErrorPropagation: + DesugarQuestionMark::go (expr); + break; + case Expr::Kind::Try: + DesugarTryBlock::go (expr); + break; + case Expr::Kind::Loop: + dispatch_loops (expr); + break; + + default: + break; + } + + visit (expr); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-expression-yeast.h b/gcc/rust/ast/rust-expression-yeast.h new file mode 100644 index 0000000..3f64b1d --- /dev/null +++ b/gcc/rust/ast/rust-expression-yeast.h @@ -0,0 +1,49 @@ +// 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/>. + +#ifndef RUST_EXPRESSION_YEAST +#define RUST_EXPRESSION_YEAST + +#include "rust-ast-pointer-visitor.h" +#include "rust-ast.h" +#include "rust-desugar-question-mark.h" + +namespace Rust { +namespace AST { + +// This visitor takes care of all the expression desugars: try-blocks, +// error-propagation, etc. +class ExpressionYeast : public AST::PointerVisitor +{ + using AST::PointerVisitor::reseat; + using AST::PointerVisitor::visit; + +public: + void go (AST::Crate &); + +private: + // Dispatch to the proper desugar + void reseat (std::unique_ptr<Expr> &expr) override; + + void dispatch_loops (std::unique_ptr<Expr> &loop_expr); +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_EXPRESSION_YEAST diff --git a/gcc/rust/ast/rust-fmt.cc b/gcc/rust/ast/rust-fmt.cc index a29c820..21f4f03 100644 --- a/gcc/rust/ast/rust-fmt.cc +++ b/gcc/rust/ast/rust-fmt.cc @@ -32,41 +32,11 @@ Pieces Pieces::collect (const std::string &to_parse, bool append_newline, ffi::ParseMode parse_mode) { - auto handle - = ffi::collect_pieces (to_parse.c_str (), append_newline, parse_mode); - - // this performs multiple copies, can we avoid them maybe? - // TODO: Instead of just creating a vec of, basically, `ffi::Piece`s, we - // should transform them into the proper C++ type which we can work with. so - // transform all the strings into C++ strings? all the Option<T> into - // tl::optional<T>? - auto pieces_vector = std::vector<ffi::Piece> (handle.piece_slice.base_ptr, - handle.piece_slice.base_ptr - + handle.piece_slice.len); - - return Pieces (handle, std::move (pieces_vector)); -} - -Pieces::~Pieces () { ffi::destroy_pieces (handle); } - -Pieces::Pieces (const Pieces &other) : pieces_vector (other.pieces_vector) -{ - handle = ffi::clone_pieces (other.handle); + Pieces ret (to_parse, ffi::FFIVec<ffi::Piece> ()); + ret.data->second = ffi::collect_pieces (ffi::RustHamster (ret.data->first), + append_newline, parse_mode); + return ret; } -Pieces & -Pieces::operator= (const Pieces &other) -{ - handle = ffi::clone_pieces (other.handle); - pieces_vector = other.pieces_vector; - - return *this; -} - -Pieces::Pieces (Pieces &&other) - : pieces_vector (std::move (other.pieces_vector)), - handle (clone_pieces (other.handle)) -{} - } // namespace Fmt } // namespace Rust diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h index a54faec..13dc7be 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -20,20 +20,174 @@ #define RUST_FMT_H #include "rust-system.h" +#include "optional.h" -// FIXME: How to encode Option? +// PR122498 "rust-enabled bootstrap is broken after r16-4897" +#pragma GCC diagnostic warning "-Warray-bounds" namespace Rust { namespace Fmt { namespace ffi { +extern "C" { + +unsigned char *rust_ffi_alloc (size_t count, size_t elem_size, size_t align); + +void rust_ffi_dealloc (unsigned char *data, size_t count, size_t elem_size, + size_t align); + +} // extern "C" + +template <typename T> class FFIVec +{ + T *data; + size_t len; + size_t cap; + +public: + FFIVec () : data ((T *) alignof (T)), len (0), cap (0) {} + + FFIVec (const FFIVec &) = delete; + FFIVec &operator= (const FFIVec &) = delete; + + FFIVec (FFIVec &&other) : data (other.data), len (other.len), cap (other.cap) + { + other.data = (T *) alignof (T); + other.len = 0; + other.cap = 0; + } + + FFIVec &operator= (FFIVec &&other) + { + this->~FFIVec (); + new (this) FFIVec (std::move (other)); + return *this; + } + + ~FFIVec () + { + // T can't be zero-sized + if (cap) + rust_ffi_dealloc ((unsigned char *) data, cap, sizeof (T), alignof (T)); + } + + size_t size () const { return len; } + + const T &operator[] (size_t idx) const + { + rust_assert (idx <= len); + return data[idx]; + } + + T *begin () { return data; } + const T *begin () const { return data; } + T *end () { return data + len; } + const T *end () const { return data + len; } +}; + +// https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md +template <typename T, + typename = + typename std::enable_if<std::is_standard_layout<T>::value>::type> +class FFIOpt +{ +public: + template <typename U> + FFIOpt (U &&val) : some{Some::KIND, std::forward<U> (val)} + {} + + FFIOpt () : none{None::KIND} {} + + FFIOpt (const FFIOpt &other) + { + if (other.has_value ()) + new (&some) Some{Some::KIND, other.some.val}; + else + new (&none) None{None::KIND}; + } + + FFIOpt (FFIOpt &&other) + { + if (other.has_value ()) + new (&some) Some{Some::KIND, std::move (other.some.val)}; + else + new (&none) None{None::KIND}; + } + + ~FFIOpt () + { + if (has_value ()) + some.~Some (); + else + none.~None (); + } + + FFIOpt &operator= (const FFIOpt &other) + { + this->~FFIOpt (); + new (this) FFIOpt (other); + return *this; + } + + FFIOpt &operator= (FFIOpt &&other) + { + this->~FFIOpt (); + new (this) FFIOpt (std::move (other)); + return *this; + } + + tl::optional<std::reference_wrapper<T>> get_opt () + { + if (has_value ()) + return std::ref (some.val); + else + return tl::nullopt; + } + + tl::optional<std::reference_wrapper<const T>> get_opt () const + { + if (has_value ()) + return std::ref (some.val); + else + return tl::nullopt; + } + + bool has_value () const { return some.kind == Some::KIND; } + + operator bool () const { return has_value (); } + +private: + struct Some + { + static constexpr uint8_t KIND = 0; + uint8_t kind; + T val; + }; + + struct None + { + static constexpr uint8_t KIND = 1; + uint8_t kind; + }; + + union + { + Some some; + None none; + }; +}; + struct RustHamster { const char *ptr; size_t len; std::string to_string () const; + + explicit RustHamster (const std::string &str) + : ptr (str.data ()), len (str.size ()) + {} }; /// Enum of alignments which are supported. @@ -166,33 +320,33 @@ struct Count struct FormatSpec { /// Optionally specified character to fill alignment with. - const uint32_t *fill; + FFIOpt<uint32_t> fill; /// Span of the optionally specified fill character. - const InnerSpan *fill_span; + FFIOpt<InnerSpan> fill_span; /// Optionally specified alignment. Alignment align; /// The `+` or `-` flag. - const Sign *sign; + FFIOpt<Sign> sign; /// The `#` flag. bool alternate; /// The `0` flag. bool zero_pad; /// The `x` or `X` flag. (Only for `Debug`.) - const DebugHex *debug_hex; + FFIOpt<DebugHex> debug_hex; /// The integer precision to use. Count precision; /// The span of the precision formatting flag (for diagnostics). - const InnerSpan *precision_span; + FFIOpt<InnerSpan> precision_span; /// The string width requested for the resulting format. Count width; /// The span of the width formatting flag (for diagnostics). - const InnerSpan *width_span; + FFIOpt<InnerSpan> width_span; /// The descriptor string representing the name of the format desired for /// this argument, this can be empty or any number of characters, although /// it is required to be one word. RustHamster ty; /// The span of the descriptor string (for diagnostics). - const InnerSpan *ty_span; + FFIOpt<InnerSpan> ty_span; }; /// Representation of an argument specification. @@ -238,26 +392,6 @@ struct Piece }; }; -struct PieceSlice -{ - const Piece *base_ptr; - size_t len; - size_t cap; -}; - -struct RustString -{ - const unsigned char *ptr; - size_t len; - size_t cap; -}; - -struct FormatArgsHandle -{ - PieceSlice piece_slice; - RustString rust_string; -}; - enum ParseMode { Format = 0, @@ -266,13 +400,10 @@ enum ParseMode extern "C" { -FormatArgsHandle -collect_pieces (const char *input, bool append_newline, ParseMode parse_mode); +FFIVec<Piece> collect_pieces (RustHamster input, bool append_newline, + ParseMode parse_mode); -FormatArgsHandle -clone_pieces (const FormatArgsHandle &); - -void destroy_pieces (FormatArgsHandle); +FFIVec<Piece> clone_pieces (const FFIVec<Piece> &); } // extern "C" @@ -282,33 +413,20 @@ struct Pieces { static Pieces collect (const std::string &to_parse, bool append_newline, ffi::ParseMode parse_mode); - ~Pieces (); - - Pieces (const Pieces &other); - Pieces &operator= (const Pieces &other); - Pieces (Pieces &&other); - - const std::vector<ffi::Piece> &get_pieces () const { return pieces_vector; } - - // { - // slice = clone_pieces (&other.slice); - // to_parse = other.to_parse; - - // return *this; - // } + const ffi::FFIVec<ffi::Piece> &get_pieces () const { return data->second; } private: - Pieces (ffi::FormatArgsHandle handle, std::vector<ffi::Piece> &&pieces_vector) - : pieces_vector (std::move (pieces_vector)), handle (handle) + Pieces (std::string str, ffi::FFIVec<ffi::Piece> pieces) + : data ( + std::make_shared<decltype (data)::element_type> (std::move (str), + std::move (pieces))) {} - std::vector<ffi::Piece> pieces_vector; - - // this memory is held for FFI reasons - it needs to be released and cloned - // precisely, so try to not access it/modify it if possible. you should - // instead work with `pieces_vector` - ffi::FormatArgsHandle handle; + // makes copying simpler + // also, we'd need to keep the parsed string in a shared_ptr anyways + // since we store pointers into the parsed string + std::shared_ptr<std::pair<std::string, ffi::FFIVec<ffi::Piece>>> data; }; } // namespace Fmt diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 8eb0cc5..3e3735c 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -51,21 +51,12 @@ class TypePath; // A type generic parameter (as opposed to a lifetime generic parameter) class TypeParam : public GenericParam { - // bool has_outer_attribute; - // std::unique_ptr<Attribute> outer_attr; AST::AttrVec outer_attrs; - Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound>> - type_param_bounds; // inlined form - - // bool has_type; + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; std::unique_ptr<Type> type; - location_t locus; + bool was_impl_trait; public: Identifier get_type_representation () const { return type_representation; } @@ -85,18 +76,19 @@ public: std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds = std::vector<std::unique_ptr<TypeParamBound>> (), std::unique_ptr<Type> type = nullptr, - AST::AttrVec outer_attrs = {}) + AST::AttrVec outer_attrs = {}, bool was_impl_trait = false) : GenericParam (Analysis::Mappings::get ().get_next_node_id ()), outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), - type (std::move (type)), locus (locus) + type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait) {} // Copy constructor uses clone TypeParam (TypeParam const &other) : GenericParam (other.node_id), outer_attrs (other.outer_attrs), - type_representation (other.type_representation), locus (other.locus) + type_representation (other.type_representation), locus (other.locus), + was_impl_trait (other.was_impl_trait) { // guard to prevent null pointer dereference if (other.type != nullptr) @@ -114,6 +106,7 @@ public: outer_attrs = other.outer_attrs; locus = other.locus; node_id = other.node_id; + was_impl_trait = other.was_impl_trait; // guard to prevent null pointer dereference if (other.type != nullptr) @@ -153,17 +146,19 @@ public: return type; } - // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds () { return type_param_bounds; } + const std::vector<std::unique_ptr<TypeParamBound>> & get_type_param_bounds () const { return type_param_bounds; } + bool from_impl_trait () const { return was_impl_trait; } + protected: // Clone function implementation as virtual method TypeParam *clone_generic_param_impl () const override @@ -434,13 +429,14 @@ class SelfParam : public Param bool has_ref; bool is_mut; // bool has_lifetime; // only possible if also ref - Lifetime lifetime; + tl::optional<Lifetime> lifetime; // bool has_type; // only possible if not ref std::unique_ptr<Type> type; // Unrestricted constructor used for error state - SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type) + SelfParam (tl::optional<Lifetime> lifetime, bool has_ref, bool is_mut, + Type *type) : Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut), lifetime (std::move (lifetime)), type (type) {} @@ -453,7 +449,7 @@ public: bool has_type () const { return type != nullptr; } // Returns whether the self-param has a valid lifetime. - bool has_lifetime () const { return !lifetime.is_error (); } + bool has_lifetime () const { return lifetime.has_value (); } // Returns whether the self-param is in an error state. bool is_error () const @@ -472,11 +468,11 @@ public: // Type-based self parameter (not ref, no lifetime) SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus) : Param ({}, locus), has_ref (false), is_mut (is_mut), - lifetime (Lifetime::error ()), type (std::move (type)) + lifetime (tl::nullopt), type (std::move (type)) {} // Lifetime-based self parameter (is ref, no type) - SelfParam (Lifetime lifetime, bool is_mut, location_t locus) + SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus) : Param ({}, locus), has_ref (true), is_mut (is_mut), lifetime (std::move (lifetime)) {} @@ -522,8 +518,8 @@ public: bool get_has_ref () const { return has_ref; }; bool get_is_mut () const { return is_mut; } - Lifetime get_lifetime () const { return lifetime; } - Lifetime &get_lifetime () { return lifetime; } + Lifetime get_lifetime () const { return lifetime.value (); } + Lifetime &get_lifetime () { return lifetime.value (); } NodeId get_node_id () const { return node_id; } @@ -635,6 +631,12 @@ public: return *param_name; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (param_name != nullptr); + return param_name; + } + const Pattern &get_pattern () const { rust_assert (param_name != nullptr); @@ -718,6 +720,12 @@ public: return *param_name; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (param_name != nullptr); + return param_name; + } + bool has_name () const { return param_name != nullptr; } // TODO: is this better? Or is a "vis_block" better? @@ -1330,7 +1338,7 @@ class Function : public VisItem, public AssociatedItem, public ExternalItem WhereClause where_clause; tl::optional<std::unique_ptr<BlockExpr>> function_body; location_t locus; - bool is_default; + bool has_default; bool is_external_function; public: @@ -1355,6 +1363,8 @@ public: bool has_body () const { return function_body.has_value (); } + bool is_default () const { return has_default; } + // Mega-constructor with all possible fields Function (Identifier function_name, FunctionQualifiers qualifiers, std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -1362,7 +1372,7 @@ public: std::unique_ptr<Type> return_type, WhereClause where_clause, tl::optional<std::unique_ptr<BlockExpr>> function_body, Visibility vis, std::vector<Attribute> outer_attrs, - location_t locus, bool is_default = false, + location_t locus, bool has_default = false, bool is_external_function = false) : VisItem (std::move (vis), std::move (outer_attrs)), ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)), @@ -1372,7 +1382,7 @@ public: return_type (std::move (return_type)), where_clause (std::move (where_clause)), function_body (std::move (function_body)), locus (locus), - is_default (is_default), is_external_function (is_external_function) + has_default (has_default), is_external_function (is_external_function) {} // TODO: add constructor with less fields @@ -1569,6 +1579,9 @@ public: location_t get_locus () const override final { return locus; } + // needed to override AssociatedItem::get_node_id + NodeId get_node_id () const override final { return VisItem::get_node_id (); } + void accept_vis (ASTVisitor &vis) override; // Invalid if existing type is null, so base stripping on that. @@ -1597,6 +1610,12 @@ public: return *existing_type; } + std::unique_ptr<Type> &get_type_aliased_ptr () + { + rust_assert (existing_type != nullptr); + return existing_type; + } + Identifier get_new_type_name () const { return new_type_name; } Item::Kind get_item_kind () const override { return Item::Kind::TypeAlias; } @@ -2452,7 +2471,7 @@ class ConstantItem : public VisItem, public AssociatedItem // either has an identifier or "_" - maybe handle in identifier? // bool identifier_is_underscore; // if no identifier declared, identifier will be "_" - std::string identifier; + Identifier identifier; std::unique_ptr<Type> type; std::unique_ptr<Expr> const_expr; @@ -2462,7 +2481,7 @@ class ConstantItem : public VisItem, public AssociatedItem public: std::string as_string () const override; - ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type, + ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type, std::unique_ptr<Expr> const_expr, std::vector<Attribute> outer_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -2470,7 +2489,7 @@ public: const_expr (std::move (const_expr)), locus (locus) {} - ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type, + ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type, std::vector<Attribute> outer_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), identifier (std::move (ident)), type (std::move (type)), @@ -2513,13 +2532,16 @@ public: /* Returns whether constant item is an "unnamed" (wildcard underscore used * as identifier) constant. */ - bool is_unnamed () const { return identifier == "_"; } + bool is_unnamed () const { return identifier.as_string () == "_"; } location_t get_locus () const override final { return locus; } + // needed to override AssociatedItem::get_node_id + NodeId get_node_id () const override final { return VisItem::get_node_id (); } + void accept_vis (ASTVisitor &vis) override; - // Invalid if type or expression are null, so base stripping on that. + // Invalid if type and expression are null, so base stripping on that. void mark_for_strip () override { type = nullptr; @@ -2530,7 +2552,7 @@ public: return type == nullptr && const_expr == nullptr; } - bool has_expr () { return const_expr != nullptr; } + bool has_expr () const { return const_expr != nullptr; } // TODO: is this better? Or is a "vis_block" better? Expr &get_expr () @@ -2558,7 +2580,7 @@ public: return type; } - std::string get_identifier () const { return identifier; } + const Identifier &get_identifier () const { return identifier; } Item::Kind get_item_kind () const override { @@ -2697,123 +2719,6 @@ protected: } }; -// Constant item within traits -class TraitItemConst : public TraitItem -{ - std::vector<Attribute> outer_attrs; - Identifier name; - std::unique_ptr<Type> type; - - // bool has_expression; - std::unique_ptr<Expr> expr; - -public: - // Whether the constant item has an associated expression. - bool has_expression () const { return expr != nullptr; } - - TraitItemConst (Identifier name, std::unique_ptr<Type> type, - std::unique_ptr<Expr> expr, - std::vector<Attribute> outer_attrs, location_t locus) - : TraitItem (locus), outer_attrs (std::move (outer_attrs)), - name (std::move (name)), type (std::move (type)), expr (std::move (expr)) - {} - - // Copy constructor with clones - TraitItemConst (TraitItemConst const &other) - : TraitItem (other.locus), outer_attrs (other.outer_attrs), - name (other.name) - { - node_id = other.node_id; - - // guard to prevent null dereference - if (other.expr != nullptr) - expr = other.expr->clone_expr (); - - // guard to prevent null dereference (only for error state) - if (other.type != nullptr) - type = other.type->clone_type (); - } - - // Overloaded assignment operator to clone - TraitItemConst &operator= (TraitItemConst const &other) - { - TraitItem::operator= (other); - outer_attrs = other.outer_attrs; - name = other.name; - locus = other.locus; - node_id = other.node_id; - - // guard to prevent null dereference - if (other.expr != nullptr) - expr = other.expr->clone_expr (); - else - expr = nullptr; - - // guard to prevent null dereference (only for error state) - if (other.type != nullptr) - type = other.type->clone_type (); - else - type = nullptr; - - return *this; - } - - // move constructors - TraitItemConst (TraitItemConst &&other) = default; - TraitItemConst &operator= (TraitItemConst &&other) = default; - - std::string as_string () const override; - - location_t get_locus () const override { return locus; } - - void accept_vis (ASTVisitor &vis) override; - - // Invalid if type is null, so base stripping on that. - void mark_for_strip () override { type = nullptr; } - bool is_marked_for_strip () const override { return type == nullptr; } - - // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } - - bool has_expr () const { return expr != nullptr; } - - // TODO: is this better? Or is a "vis_block" better? - Expr &get_expr () - { - rust_assert (has_expr ()); - return *expr; - } - - std::unique_ptr<Expr> &get_expr_ptr () - { - rust_assert (has_expr ()); - return expr; - } - - // TODO: is this better? Or is a "vis_block" better? - Type &get_type () - { - rust_assert (type != nullptr); - return *type; - } - - std::unique_ptr<Type> &get_type_ptr () - { - rust_assert (type != nullptr); - return type; - } - - Identifier get_identifier () const { return name; } - -protected: - // Clone function implementation as (not pure) virtual method - TraitItemConst *clone_associated_item_impl () const override - { - return new TraitItemConst (*this); - } -}; - // Type items within traits class TraitItemType : public TraitItem { @@ -2821,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 @@ -2844,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 ()); @@ -2858,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 ()); @@ -2881,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 fc01e57..71de8f0 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -27,6 +27,11 @@ #include "rust-macro-builtins.h" namespace Rust { + +// forward declarations for AttributeParser +class MacroInvocLexer; +template <typename ManagedTokenSource> class Parser; + namespace AST { class MacroFragSpec @@ -756,22 +761,16 @@ private: std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs; protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_pattern_impl () const final override { return clone_macro_invocation_impl (); } - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_expr_without_block_impl () const final override { return clone_macro_invocation_impl (); } - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_type_no_bounds_impl () const final override { return clone_macro_invocation_impl (); @@ -788,6 +787,20 @@ public: return new MacroInvocation (*this); } + std::unique_ptr<MacroInvocation> reconstruct_macro_invocation () const + { + return nullptr; + // return reconstruct (this, + // &MacroInvocation::reconstruct_macro_invocation_impl); + } + + MacroInvocation *reconstruct_impl () const override + { + return new MacroInvocation (kind, builtin_kind, invoc_data, outer_attrs, + locus, is_semi_coloned, + reconstruct_vec (pending_eager_invocs)); + } + void add_semicolon () override { is_semi_coloned = true; } Pattern::Kind get_pattern_kind () override @@ -980,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 @@ -1108,16 +1125,14 @@ struct AttributeParser { private: // TODO: might as well rewrite to use lexer tokens - std::vector<std::unique_ptr<Token>> token_stream; - int stream_pos; + std::unique_ptr<MacroInvocLexer> lexer; + std::unique_ptr<Parser<MacroInvocLexer>> parser; public: AttributeParser (std::vector<std::unique_ptr<Token>> token_stream, - int stream_start_pos = 0) - : token_stream (std::move (token_stream)), stream_pos (stream_start_pos) - {} + int stream_start_pos = 0); - ~AttributeParser () = default; + ~AttributeParser (); std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq (); @@ -1126,24 +1141,10 @@ private: std::unique_ptr<MetaItemInner> parse_meta_item_inner (); // Returns whether token can end a meta item. bool is_end_meta_item_tok (TokenId id) const; - // Parses a simple path. - SimplePath parse_simple_path (); - // Parses a segment of a simple path (but not scope resolution operator). - SimplePathSegment parse_simple_path_segment (); // Parses a MetaItemLitExpr. std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit (); - // Parses a literal. - Literal parse_literal (); // Parses a meta item that begins with a simple path. std::unique_ptr<MetaItem> parse_path_meta_item (); - - // TODO: should this be const? - std::unique_ptr<Token> &peek_token (int i = 0) - { - return token_stream[stream_pos + i]; - } - - void skip_token (int i = 0) { stream_pos += 1 + i; } }; } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 69627be8..068e364 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -119,7 +119,7 @@ ConstGenericParam::as_string () const str += "const " + name.as_string () + ": " + type->as_string (); if (has_default_value ()) - str += " = " + get_default_value ().as_string (); + str += " = " + get_default_value_unchecked ().as_string (); return str; } @@ -167,14 +167,13 @@ Path::convert_to_simple_path (bool with_opening_scope_resolution) const for (const auto &segment : segments) { // return empty path if doesn't meet simple path segment requirements - if (segment.is_error () || segment.has_generic_args () - || segment.as_string () == "Self") + if (segment.is_error () || segment.has_generic_args ()) return SimplePath::create_empty (); // create segment and add to vector std::string segment_str = segment.as_string (); - simple_segments.push_back ( - SimplePathSegment (std::move (segment_str), segment.get_locus ())); + simple_segments.emplace_back (std::move (segment_str), + segment.get_locus ()); } // kind of a HACK to get locus depending on opening scope resolution @@ -258,14 +257,35 @@ TypePath::as_simple_path () const // create segment and add to vector std::string segment_str = segment->as_string (); - simple_segments.push_back ( - SimplePathSegment (std::move (segment_str), segment->get_locus ())); + simple_segments.emplace_back (std::move (segment_str), + segment->get_locus ()); } return SimplePath (std::move (simple_segments), has_opening_scope_resolution, locus); } +std::string +TypePath::make_debug_string () const +{ + rust_assert (!segments.empty ()); + + std::string output; + + for (const auto &segment : segments) + { + if (segment != nullptr && !segment->is_lang_item () + && !segment->is_error ()) + { + if (!output.empty () || has_opening_scope_resolution_op ()) + output.append ("::"); + output.append (segment->get_ident_segment ().as_string ()); + } + } + + return output; +} + // hopefully definition here will prevent circular dependency issue TraitBound * TypePath::to_trait_bound (bool in_parens) const diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 805be8e..be04882 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -167,17 +167,11 @@ public: */ enum class Kind { - Error, Const, // A const value Type, // A type argument (not discernable during parsing) Either, // Either a type or a const value, cleared up during resolving }; - static GenericArg create_error () - { - return GenericArg (nullptr, nullptr, {""}, Kind::Error, UNDEF_LOCATION); - } - static GenericArg create_const (std::unique_ptr<Expr> expression) { auto locus = expression->get_locus (); @@ -222,8 +216,6 @@ public: GenericArg (GenericArg &&other) = default; GenericArg &operator= (GenericArg &&other) = default; - bool is_error () const { return kind == Kind::Error; } - Kind get_kind () const { return kind; } location_t get_locus () const { return locus; } @@ -239,8 +231,6 @@ public: break; case Kind::Either: break; - case Kind::Error: - rust_unreachable (); } } @@ -283,8 +273,6 @@ public: { switch (get_kind ()) { - case Kind::Error: - rust_unreachable (); case Kind::Either: return "Ambiguous: " + path.as_string (); case Kind::Const: @@ -355,15 +343,15 @@ class ConstGenericParam : public GenericParam /** * Default value for the const generic parameter */ - GenericArg default_value; + tl::optional<GenericArg> default_value; AST::AttrVec outer_attrs; location_t locus; public: ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type, - GenericArg default_value, AST::AttrVec outer_attrs, - location_t locus) + tl::optional<GenericArg> default_value, + AST::AttrVec outer_attrs, location_t locus) : name (name), type (std::move (type)), default_value (std::move (default_value)), outer_attrs (outer_attrs), locus (locus) @@ -376,7 +364,7 @@ public: {} bool has_type () const { return type != nullptr; } - bool has_default_value () const { return !default_value.is_error (); } + bool has_default_value () const { return default_value.has_value (); } const Identifier &get_name () const { return name; } @@ -389,17 +377,31 @@ public: return *type; } - GenericArg &get_default_value () + std::unique_ptr<AST::Type> &get_type_ptr () + { + rust_assert (has_type ()); + + return type; + } + + GenericArg &get_default_value_unchecked () { rust_assert (has_default_value ()); - return default_value; + return default_value.value (); } - const GenericArg &get_default_value () const + const GenericArg &get_default_value_unchecked () const { rust_assert (has_default_value ()); + return default_value.value (); + } + + tl::optional<GenericArg> &get_default_value () { return default_value; } + + const tl::optional<GenericArg> &get_default_value () const + { return default_value; } @@ -453,9 +455,7 @@ public: generic_args.clear (); generic_args.reserve (other.generic_args.size ()); for (const auto &arg : other.generic_args) - { - generic_args.push_back (GenericArg (arg)); - } + generic_args.emplace_back (arg); } ~GenericArgs () = default; @@ -470,9 +470,7 @@ public: generic_args.clear (); generic_args.reserve (other.generic_args.size ()); for (const auto &arg : other.generic_args) - { - generic_args.push_back (GenericArg (arg)); - } + generic_args.emplace_back (arg); return *this; } @@ -791,6 +789,11 @@ public: { return new TypePathSegment (*this); } + virtual TypePathSegment *reconstruct_impl () const + { + return new TypePathSegment (lang_item, ident_segment, + has_separating_scope_resolution, locus); + } public: virtual ~TypePathSegment () {} @@ -802,6 +805,11 @@ public: { return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ()); } + // Unique pointer custom reconstruct function + std::unique_ptr<TypePathSegment> reconstruct () const + { + return reconstruct_base (this); + } TypePathSegment (PathIdentSegment ident_segment, bool has_separating_scope_resolution, location_t locus) @@ -826,6 +834,15 @@ public: node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + // General constructor + TypePathSegment (tl::optional<LangItem::Kind> lang_item, + tl::optional<PathIdentSegment> ident_segment, + bool has_separating_scope_resolution, location_t locus) + : lang_item (lang_item), ident_segment (ident_segment), locus (locus), + has_separating_scope_resolution (has_separating_scope_resolution), + node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} + TypePathSegment (TypePathSegment const &other) : lang_item (other.lang_item), ident_segment (other.ident_segment), locus (other.locus), @@ -980,11 +997,7 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - GenericArgs &get_generic_args () - { - rust_assert (has_generic_args ()); - return generic_args; - } + GenericArgs &get_generic_args () { return generic_args; } // Use covariance to override base class method TypePathSegmentGeneric *clone_type_path_segment_impl () const override @@ -1161,6 +1174,11 @@ protected: { return new TypePath (*this); } + TypePath *reconstruct_impl () const override + { + return new TypePath (reconstruct_vec (segments), locus, + has_opening_scope_resolution); + } public: /* Returns whether the TypePath has an opening scope resolution operator @@ -1227,6 +1245,8 @@ public: std::string as_string () const override; + std::string make_debug_string () const; + /* Converts TypePath to SimplePath if possible (i.e. no generic or function * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const; @@ -1235,7 +1255,7 @@ public: TraitBound *to_trait_bound (bool in_parens) const override; location_t get_locus () const override final { return locus; } - NodeId get_node_id () const { return node_id; } + NodeId get_node_id () const override { return node_id; } void mark_for_strip () override {} bool is_marked_for_strip () const override { return false; } @@ -1450,6 +1470,12 @@ protected: { return new QualifiedPathInType (*this); } + QualifiedPathInType *reconstruct_impl () const override + { + return new QualifiedPathInType (path_type, + associated_segment->reconstruct (), + reconstruct_vec (segments), locus); + } public: QualifiedPathInType ( diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index fc7b610..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 @@ -65,8 +65,8 @@ IdentifierPattern::as_string () const str += variable_ident.as_string (); - if (has_pattern_to_bind ()) - str += " @ " + to_bind->as_string (); + if (has_subpattern ()) + str += " @ " + subpattern->as_string (); return str; } @@ -186,8 +186,8 @@ StructPatternElements::as_string () const str += "\n " + field->as_string (); } - str += "\n Etc: "; - if (has_struct_pattern_etc) + str += "\n Has rest: "; + if (has_rest_pattern) str += "true"; else str += "false"; @@ -212,7 +212,7 @@ StructPattern::as_string () const } std::string -TupleStructItemsNoRange::as_string () const +TupleStructItemsNoRest::as_string () const { std::string str; @@ -223,7 +223,7 @@ TupleStructItemsNoRange::as_string () const } std::string -TupleStructItemsRange::as_string () const +TupleStructItemsHasRest::as_string () const { std::string str ("\n Lower patterns: "); @@ -264,7 +264,7 @@ TupleStructPattern::as_string () const } std::string -TuplePatternItemsMultiple::as_string () const +TuplePatternItemsNoRest::as_string () const { std::string str; @@ -275,7 +275,7 @@ TuplePatternItemsMultiple::as_string () const } std::string -TuplePatternItemsRanged::as_string () const +TuplePatternItemsHasRest::as_string () const { std::string str; @@ -327,17 +327,53 @@ GroupedExpr::as_string () const } std::string -SlicePattern::as_string () const +SlicePatternItemsNoRest::as_string () const { - std::string str ("SlicePattern: "); + std::string str; - for (const auto &pattern : items) + for (const auto &pattern : patterns) str += "\n " + pattern->as_string (); return str; } std::string +SlicePatternItemsHasRest::as_string () const +{ + std::string str; + + str += "\n Lower patterns: "; + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + str += "\n " + lower->as_string (); + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + str += "\n " + upper->as_string (); + } + + return str; +} + +std::string +SlicePattern::as_string () const +{ + return "SlicePattern: " + items->as_string (); +} + +std::string AltPattern::as_string () const { std::string str ("AltPattern: "); @@ -367,13 +403,25 @@ GroupedExpr::accept_vis (ASTVisitor &vis) } void +SlicePatternItemsNoRest::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +SlicePatternItemsHasRest::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void SlicePattern::accept_vis (ASTVisitor &vis) { vis.visit (*this); } void -TuplePatternItemsRanged::accept_vis (ASTVisitor &vis) +TuplePatternItemsHasRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -385,7 +433,7 @@ TuplePattern::accept_vis (ASTVisitor &vis) } void -TuplePatternItemsMultiple::accept_vis (ASTVisitor &vis) +TuplePatternItemsNoRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -469,13 +517,13 @@ StructPattern::accept_vis (ASTVisitor &vis) } void -TupleStructItemsNoRange::accept_vis (ASTVisitor &vis) +TupleStructItemsNoRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } void -TupleStructItemsRange::accept_vis (ASTVisitor &vis) +TupleStructItemsHasRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 69dbd98..3b1bd1c 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -20,6 +20,7 @@ #define RUST_AST_PATTERN_H #include "rust-ast.h" +#include "rust-path.h" namespace Rust { namespace AST { @@ -29,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; @@ -36,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; } @@ -74,7 +93,7 @@ class IdentifierPattern : public Pattern bool is_mut; // bool has_pattern; - std::unique_ptr<Pattern> to_bind; + std::unique_ptr<Pattern> subpattern; location_t locus; NodeId node_id; @@ -82,22 +101,22 @@ public: std::string as_string () const override; // Returns whether the IdentifierPattern has a pattern to bind. - bool has_pattern_to_bind () const { return to_bind != nullptr; } + bool has_subpattern () const { return subpattern != nullptr; } // Constructor IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false, bool is_mut = false, - std::unique_ptr<Pattern> to_bind = nullptr) + std::unique_ptr<Pattern> subpattern = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), - is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} IdentifierPattern (NodeId node_id, Identifier ident, location_t locus, bool is_ref = false, bool is_mut = false, - std::unique_ptr<Pattern> to_bind = nullptr) + std::unique_ptr<Pattern> subpattern = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), - is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus), node_id (node_id) {} @@ -107,8 +126,8 @@ public: is_mut (other.is_mut), locus (other.locus), node_id (other.node_id) { // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); } // Overload assignment operator to use clone @@ -121,10 +140,10 @@ public: node_id = other.node_id; // fix to prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); else - to_bind = nullptr; + subpattern = nullptr; return *this; } @@ -137,11 +156,16 @@ public: void accept_vis (ASTVisitor &vis) override; - // TODO: is this better? Or is a "vis_pattern" better? - Pattern &get_pattern_to_bind () + Pattern &get_subpattern () { - rust_assert (has_pattern_to_bind ()); - return *to_bind; + rust_assert (has_subpattern ()); + return *subpattern; + } + + std::unique_ptr<Pattern> &get_subpattern_ptr () + { + rust_assert (has_subpattern ()); + return subpattern; } Identifier get_ident () const { return variable_ident; } @@ -375,8 +399,7 @@ enum class RangeKind EXCLUDED, }; -RangeKind -tokenid_to_rangekind (TokenId id); +RangeKind tokenid_to_rangekind (TokenId id); // AST node for matching within a certain range (range pattern) class RangePattern : public Pattern { @@ -520,6 +543,12 @@ public: return *pattern; } + std::unique_ptr<Pattern> &get_referenced_pattern_ptr () + { + rust_assert (pattern != nullptr); + return pattern; + } + bool is_double_reference () const { return has_two_amps; } bool get_is_mut () const { return is_mut; } @@ -683,6 +712,12 @@ public: return *tuple_pattern; } + std::unique_ptr<Pattern> &get_index_pattern_ptr () + { + rust_assert (tuple_pattern != nullptr); + return tuple_pattern; + } + ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; } protected: @@ -763,6 +798,12 @@ public: return *ident_pattern; } + std::unique_ptr<Pattern> &get_ident_pattern_ptr () + { + rust_assert (ident_pattern != nullptr); + return ident_pattern; + } + ItemType get_item_type () const override final { return ItemType::IDENT_PAT; } protected: @@ -820,7 +861,7 @@ class StructPatternElements // bool has_struct_pattern_fields; std::vector<std::unique_ptr<StructPatternField>> fields; - bool has_struct_pattern_etc; + bool has_rest_pattern; std::vector<Attribute> struct_pattern_etc_attrs; // StructPatternEtc etc; @@ -836,29 +877,29 @@ public: * no etc). */ bool is_empty () const { - return !has_struct_pattern_fields () && !has_struct_pattern_etc; + return !has_struct_pattern_fields () && !has_rest_pattern; } - bool has_etc () const { return has_struct_pattern_etc; } + bool has_rest () const { return has_rest_pattern; } // Constructor for StructPatternElements with both (potentially) StructPatternElements ( std::vector<std::unique_ptr<StructPatternField>> fields, std::vector<Attribute> etc_attrs) - : fields (std::move (fields)), has_struct_pattern_etc (true), + : fields (std::move (fields)), has_rest_pattern (true), struct_pattern_etc_attrs (std::move (etc_attrs)) {} // Constructor for StructPatternElements with no StructPatternEtc StructPatternElements ( std::vector<std::unique_ptr<StructPatternField>> fields) - : fields (std::move (fields)), has_struct_pattern_etc (false), + : fields (std::move (fields)), has_rest_pattern (false), struct_pattern_etc_attrs () {} // Copy constructor with vector clone StructPatternElements (StructPatternElements const &other) - : has_struct_pattern_etc (other.has_struct_pattern_etc), + : has_rest_pattern (other.has_rest_pattern), struct_pattern_etc_attrs (other.struct_pattern_etc_attrs) { fields.reserve (other.fields.size ()); @@ -870,7 +911,7 @@ public: StructPatternElements &operator= (StructPatternElements const &other) { struct_pattern_etc_attrs = other.struct_pattern_etc_attrs; - has_struct_pattern_etc = other.has_struct_pattern_etc; + has_rest_pattern = other.has_rest_pattern; fields.clear (); fields.reserve (other.fields.size ()); @@ -915,7 +956,7 @@ public: void strip_etc () { - has_struct_pattern_etc = false; + has_rest_pattern = false; struct_pattern_etc_attrs.clear (); struct_pattern_etc_attrs.shrink_to_fit (); } @@ -950,7 +991,7 @@ public: * is empty). */ bool has_struct_pattern_elems () const { return !elems.is_empty (); } - location_t get_locus () const override { return path.get_locus (); } + location_t get_locus () const override { return locus; } void accept_vis (ASTVisitor &vis) override; @@ -977,49 +1018,62 @@ protected: } }; -// Base abstract class for patterns used in TupleStructPattern -class TupleStructItems +// Base abstract class for TupleStructItems, TuplePatternItems & +// SlicePatternItems +class PatternItems { public: enum ItemType { - RANGE, - NO_RANGE + NO_REST, + HAS_REST, }; - virtual ~TupleStructItems () {} + virtual ~PatternItems () {} // TODO: should this store location data? // Unique pointer custom clone function - std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const + std::unique_ptr<PatternItems> clone_pattern_items () const { - return std::unique_ptr<TupleStructItems> (clone_tuple_struct_items_impl ()); + return std::unique_ptr<PatternItems> (clone_pattern_items_impl ()); } virtual std::string as_string () const = 0; - + virtual ItemType get_item_type () const = 0; virtual void accept_vis (ASTVisitor &vis) = 0; - virtual ItemType get_item_type () const = 0; +protected: + virtual PatternItems *clone_pattern_items_impl () const = 0; +}; + +// Base abstract class for patterns used in TupleStructPattern +class TupleStructItems : public PatternItems +{ +public: + // Unique pointer custom clone function + std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const + { + return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ()); + } protected: // pure virtual clone implementation - virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0; + virtual TupleStructItems *clone_pattern_items_impl () const = 0; }; // Class for non-ranged tuple struct pattern patterns -class TupleStructItemsNoRange : public TupleStructItems +class TupleStructItemsNoRest : public TupleStructItems { std::vector<std::unique_ptr<Pattern>> patterns; public: - TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns) + TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) : patterns (std::move (patterns)) {} // Copy constructor with vector clone - TupleStructItemsNoRange (TupleStructItemsNoRange const &other) + TupleStructItemsNoRest (TupleStructItemsNoRest const &other) { patterns.reserve (other.patterns.size ()); for (const auto &e : other.patterns) @@ -1027,7 +1081,7 @@ public: } // Overloaded assignment operator with vector clone - TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other) + TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other) { patterns.clear (); patterns.reserve (other.patterns.size ()); @@ -1038,9 +1092,8 @@ public: } // move constructors - TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default; - TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other) - = default; + TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default; + TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default; std::string as_string () const override; @@ -1053,32 +1106,32 @@ public: return patterns; } - ItemType get_item_type () const override final { return ItemType::NO_RANGE; } + ItemType get_item_type () const override final { return ItemType::NO_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override + TupleStructItemsNoRest *clone_pattern_items_impl () const override { - return new TupleStructItemsNoRange (*this); + return new TupleStructItemsNoRest (*this); } }; // Class for ranged tuple struct pattern patterns -class TupleStructItemsRange : public TupleStructItems +class TupleStructItemsHasRest : public TupleStructItems { std::vector<std::unique_ptr<Pattern>> lower_patterns; std::vector<std::unique_ptr<Pattern>> upper_patterns; public: - TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) + TupleStructItemsHasRest (std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} // Copy constructor with vector clone - TupleStructItemsRange (TupleStructItemsRange const &other) + TupleStructItemsHasRest (TupleStructItemsHasRest const &other) { lower_patterns.reserve (other.lower_patterns.size ()); for (const auto &e : other.lower_patterns) @@ -1090,7 +1143,7 @@ public: } // Overloaded assignment operator to clone - TupleStructItemsRange &operator= (TupleStructItemsRange const &other) + TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other) { lower_patterns.clear (); lower_patterns.reserve (other.lower_patterns.size ()); @@ -1106,8 +1159,9 @@ public: } // move constructors - TupleStructItemsRange (TupleStructItemsRange &&other) = default; - TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default; + TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default; + TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other) + = default; std::string as_string () const override; @@ -1133,14 +1187,14 @@ public: return upper_patterns; } - ItemType get_item_type () const override final { return ItemType::RANGE; } + ItemType get_item_type () const override final { return ItemType::HAS_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleStructItemsRange *clone_tuple_struct_items_impl () const override + TupleStructItemsHasRest *clone_pattern_items_impl () const override { - return new TupleStructItemsRange (*this); + return new TupleStructItemsHasRest (*this); } }; @@ -1223,49 +1277,32 @@ protected: }; // Base abstract class representing TuplePattern patterns -class TuplePatternItems +class TuplePatternItems : public PatternItems { public: - enum TuplePatternItemType - { - MULTIPLE, - RANGED, - }; - - virtual ~TuplePatternItems () {} - - // TODO: should this store location data? - // Unique pointer custom clone function std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const { - return std::unique_ptr<TuplePatternItems> ( - clone_tuple_pattern_items_impl ()); + return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ()); } - virtual std::string as_string () const = 0; - - virtual void accept_vis (ASTVisitor &vis) = 0; - - virtual TuplePatternItemType get_pattern_type () const = 0; - protected: // pure virtual clone implementation - virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0; + virtual TuplePatternItems *clone_pattern_items_impl () const = 0; }; -// Class representing TuplePattern patterns where there are multiple patterns -class TuplePatternItemsMultiple : public TuplePatternItems +// Class representing TuplePattern patterns which contains no rest pattern +class TuplePatternItemsNoRest : public TuplePatternItems { std::vector<std::unique_ptr<Pattern>> patterns; public: - TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns) + TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) : patterns (std::move (patterns)) {} // Copy constructor with vector clone - TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other) + TuplePatternItemsNoRest (TuplePatternItemsNoRest const &other) { patterns.reserve (other.patterns.size ()); for (const auto &e : other.patterns) @@ -1273,7 +1310,7 @@ public: } // Overloaded assignment operator to vector clone - TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other) + TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other) { patterns.clear (); patterns.reserve (other.patterns.size ()); @@ -1284,8 +1321,8 @@ public: } // move constructors - TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default; - TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other) + TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default; + TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other) = default; std::string as_string () const override; @@ -1299,35 +1336,33 @@ public: return patterns; } - TuplePatternItemType get_pattern_type () const override - { - return TuplePatternItemType::MULTIPLE; - } + ItemType get_item_type () const override { return ItemType::NO_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override + TuplePatternItemsNoRest *clone_pattern_items_impl () const override { - return new TuplePatternItemsMultiple (*this); + return new TuplePatternItemsNoRest (*this); } }; -// Class representing TuplePattern patterns where there are a range of patterns -class TuplePatternItemsRanged : public TuplePatternItems +// Class representing TuplePattern patterns which contains a rest pattern +class TuplePatternItemsHasRest : public TuplePatternItems { std::vector<std::unique_ptr<Pattern>> lower_patterns; std::vector<std::unique_ptr<Pattern>> upper_patterns; public: - TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) + TuplePatternItemsHasRest ( + std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} // Copy constructor with vector clone - TuplePatternItemsRanged (TuplePatternItemsRanged const &other) + TuplePatternItemsHasRest (TuplePatternItemsHasRest const &other) { lower_patterns.reserve (other.lower_patterns.size ()); for (const auto &e : other.lower_patterns) @@ -1339,7 +1374,7 @@ public: } // Overloaded assignment operator to clone - TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other) + TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other) { lower_patterns.clear (); lower_patterns.reserve (other.lower_patterns.size ()); @@ -1355,8 +1390,8 @@ public: } // move constructors - TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default; - TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other) + TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default; + TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other) = default; std::string as_string () const override; @@ -1383,17 +1418,14 @@ public: return upper_patterns; } - TuplePatternItemType get_pattern_type () const override - { - return TuplePatternItemType::RANGED; - } + ItemType get_item_type () const override { return ItemType::HAS_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override + TuplePatternItemsHasRest *clone_pattern_items_impl () const override { - return new TuplePatternItemsRanged (*this); + return new TuplePatternItemsHasRest (*this); } }; @@ -1510,6 +1542,12 @@ public: return *pattern_in_parens; } + std::unique_ptr<Pattern> &get_pattern_in_parens_ptr () + { + rust_assert (pattern_in_parens != nullptr); + return pattern_in_parens; + } + NodeId get_node_id () const override { return node_id; } Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Grouped; } @@ -1523,41 +1561,194 @@ protected: } }; +// Base abstract class representing patterns in a SlicePattern +class SlicePatternItems : public PatternItems +{ +public: + // Unique pointer custom clone function + std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const + { + return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ()); + } + +protected: + // pure virtual clone implementation + virtual SlicePatternItems *clone_pattern_items_impl () const = 0; +}; + +// Class representing the patterns in a SlicePattern without `..` +class SlicePatternItemsNoRest : public SlicePatternItems +{ + std::vector<std::unique_ptr<Pattern>> patterns; + +public: + SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other) + { + patterns.clear (); + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default; + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; } + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const + { + return patterns; + } + + ItemType get_item_type () const override { return ItemType::NO_REST; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsNoRest *clone_pattern_items_impl () const override + { + return new SlicePatternItemsNoRest (*this); + } +}; + +// Class representing the patterns in a SlicePattern that contains a `..` +class SlicePatternItemsHasRest : public SlicePatternItems +{ + std::vector<std::unique_ptr<Pattern>> lower_patterns; + std::vector<std::unique_ptr<Pattern>> upper_patterns; + +public: + SlicePatternItemsHasRest ( + std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other) + { + lower_patterns.clear (); + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.clear (); + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default; + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () + { + return lower_patterns; + } + const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const + { + return lower_patterns; + } + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () + { + return upper_patterns; + } + const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const + { + return upper_patterns; + } + + ItemType get_item_type () const override { return ItemType::HAS_REST; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsHasRest *clone_pattern_items_impl () const override + { + return new SlicePatternItemsHasRest (*this); + } +}; + // AST node representing patterns that can match slices and arrays class SlicePattern : public Pattern { - std::vector<std::unique_ptr<Pattern>> items; + std::unique_ptr<SlicePatternItems> items; location_t locus; NodeId node_id; public: std::string as_string () const override; - SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus) + SlicePattern (std::unique_ptr<SlicePatternItems> items, location_t locus) : items (std::move (items)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} - // Copy constructor with vector clone + // Copy constructor requires clone SlicePattern (SlicePattern const &other) : locus (other.locus) { + // guard to prevent null dereference + rust_assert (other.items != nullptr); + node_id = other.node_id; - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); + items = other.items->clone_slice_pattern_items (); } - // Overloaded assignment operator to vector clone + // Overloaded assignment operator to clone SlicePattern &operator= (SlicePattern const &other) { locus = other.locus; node_id = other.node_id; - items.clear (); - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); + // guard to prevent null dereference + rust_assert (other.items != nullptr); + items = other.items->clone_slice_pattern_items (); return *this; } @@ -1570,10 +1761,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::vector<std::unique_ptr<Pattern>> &get_items () { return items; } - const std::vector<std::unique_ptr<Pattern>> &get_items () const + SlicePatternItems &get_items () { - return items; + rust_assert (items != nullptr); + return *items; } NodeId get_node_id () const override { return node_id; } diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index f843a79..5fb00ef 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -201,6 +201,12 @@ public: return *variables_pattern; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (variables_pattern != nullptr); + return variables_pattern; + } + Type &get_type () { rust_assert (has_type ()); diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 20e0232..38a3474 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -19,7 +19,9 @@ #ifndef RUST_AST_TYPE_H #define RUST_AST_TYPE_H +#include "optional.h" #include "rust-ast.h" +#include "rust-expr.h" #include "rust-path.h" namespace Rust { @@ -73,6 +75,13 @@ public: type_path (std::move (type_path)), locus (locus) {} + TraitBound (TraitBound const &other) + : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens), + opening_question_mark (other.opening_question_mark), + for_lifetimes (other.for_lifetimes), type_path (other.type_path), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } @@ -99,6 +108,11 @@ protected: return new TraitBound (node_id, type_path, locus, in_parens, opening_question_mark, for_lifetimes); } + TraitBound *reconstruct_impl () const override + { + return new TraitBound (type_path, locus, in_parens, opening_question_mark, + for_lifetimes); + } }; // definition moved to rust-ast.h @@ -120,6 +134,10 @@ protected: { return new ImplTraitType (*this); } + ImplTraitType *reconstruct_impl () const override + { + return new ImplTraitType (reconstruct_vec (type_param_bounds), locus); + } public: ImplTraitType ( @@ -129,7 +147,8 @@ public: {} // copy constructor with vector clone - ImplTraitType (ImplTraitType const &other) : locus (other.locus) + ImplTraitType (ImplTraitType const &other) + : Type (other.node_id), locus (other.locus) { type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -158,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; @@ -184,6 +202,11 @@ protected: { return new TraitObjectType (*this); } + TraitObjectType *reconstruct_impl () const override + { + return new TraitObjectType (reconstruct_vec (type_param_bounds), locus, + has_dyn); + } public: TraitObjectType ( @@ -195,7 +218,7 @@ public: // copy constructor with vector clone TraitObjectType (TraitObjectType const &other) - : has_dyn (other.has_dyn), locus (other.locus) + : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus) { type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -226,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; @@ -251,6 +273,10 @@ protected: { return new ParenthesisedType (*this); } + ParenthesisedType *reconstruct_impl () const override + { + return new ParenthesisedType (type_in_parens->reconstruct (), locus); + } public: // Constructor uses Type pointer for polymorphism @@ -305,33 +331,35 @@ public: // Impl trait with a single bound? Poor reference material here. class ImplTraitTypeOneBound : public TypeNoBounds { - TraitBound trait_bound; + std::unique_ptr<TypeParamBound> trait_bound; location_t locus; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override - { - return new ImplTraitTypeOneBound (*this); - } - public: - ImplTraitTypeOneBound (TraitBound trait_bound, location_t locus) + ImplTraitTypeOneBound (std::unique_ptr<TypeParamBound> trait_bound, + location_t locus) : trait_bound (std::move (trait_bound)), locus (locus) {} + ImplTraitTypeOneBound (ImplTraitTypeOneBound const &other) + : trait_bound (other.trait_bound->clone_type_param_bound ()), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; - // TODO: would a "vis_type" be better? - TraitBound &get_trait_bound () + std::unique_ptr<TypeParamBound> &get_trait_bound () { return trait_bound; } + + TypeNoBounds *clone_type_no_bounds_impl () const override { - // TODO: check to ensure invariants are met? - return trait_bound; + return new ImplTraitTypeOneBound (*this); + } + TypeNoBounds *reconstruct_impl () const override + { + return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus); } }; @@ -350,6 +378,10 @@ protected: { return new TraitObjectTypeOneBound (*this); } + TraitObjectTypeOneBound *reconstruct_impl () const override + { + return new TraitObjectTypeOneBound (trait_bound, locus, has_dyn); + } public: TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus, @@ -429,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 { @@ -443,6 +474,10 @@ protected: { return new TupleType (*this); } + TupleType *reconstruct_impl () const override + { + return new TupleType (reconstruct_vec (elems), locus); + } }; /* A type with no values, representing the result of computations that never @@ -459,6 +494,10 @@ protected: { return new NeverType (*this); } + NeverType *reconstruct_impl () const override + { + return new NeverType (locus); + } public: NeverType (location_t locus) : locus (locus) {} @@ -529,6 +568,15 @@ public: return *type; } + std::unique_ptr<TypeNoBounds> &get_type_pointed_to_ptr () + { + rust_assert (type != nullptr); + return type; + } + + // Getter for direct access to the type unique_ptr + std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -536,13 +584,17 @@ protected: { return new RawPointerType (*this); } + RawPointerType *reconstruct_impl () const override + { + return new RawPointerType (pointer_type, type->reconstruct (), locus); + } }; // A type pointing to memory owned by another value class ReferenceType : public TypeNoBounds { // bool has_lifetime; // TODO: handle in lifetime or something? - Lifetime lifetime; + tl::optional<Lifetime> lifetime; bool has_mut; std::unique_ptr<TypeNoBounds> type; @@ -553,11 +605,12 @@ public: bool is_mut () const { return has_mut; } // Returns whether the reference has a lifetime. - bool has_lifetime () const { return !lifetime.is_error (); } + bool has_lifetime () const { return lifetime.has_value (); } // Constructor ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds, - location_t locus, Lifetime lifetime = Lifetime::elided ()) + location_t locus, + tl::optional<Lifetime> lifetime = Lifetime::elided ()) : lifetime (std::move (lifetime)), has_mut (is_mut), type (std::move (type_no_bounds)), locus (locus) {} @@ -596,12 +649,22 @@ public: return *type; } + std::unique_ptr<TypeNoBounds> &get_type_referenced_ptr () + { + rust_assert (type != nullptr); + return type; + } + bool get_has_mut () const { return has_mut; } - Lifetime &get_lifetime () { return lifetime; } + Lifetime &get_lifetime () { return lifetime.value (); } + const Lifetime &get_lifetime () const { return lifetime.value (); } TypeNoBounds &get_base_type () { return *type; } + // Getter for direct access to the type unique_ptr + std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -609,33 +672,42 @@ protected: { return new ReferenceType (*this); } + ReferenceType *reconstruct_impl () const override + { + return new ReferenceType (has_mut, type->reconstruct (), locus, + // TODO: Improve this - it's ugly! + has_lifetime () ? tl::make_optional<Lifetime> ( + lifetime->get_lifetime_type (), + lifetime->get_lifetime_name (), + lifetime->get_locus ()) + : tl::nullopt); + } }; // A fixed-size sequence of elements of a specified type class ArrayType : public TypeNoBounds { std::unique_ptr<Type> elem_type; - std::unique_ptr<Expr> size; + AnonConst size; location_t locus; public: // Constructor requires pointers for polymorphism - ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size, - location_t locus) + ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t locus) : elem_type (std::move (type)), size (std::move (array_size)), locus (locus) {} // Copy constructor requires deep copies of both unique pointers ArrayType (ArrayType const &other) - : elem_type (other.elem_type->clone_type ()), - size (other.size->clone_expr ()), locus (other.locus) + : elem_type (other.elem_type->clone_type ()), size (other.size), + locus (other.locus) {} // Overload assignment operator to deep copy pointers ArrayType &operator= (ArrayType const &other) { elem_type = other.elem_type->clone_type (); - size = other.size->clone_expr (); + size = other.size; locus = other.locus; return *this; } @@ -657,13 +729,22 @@ public: return *elem_type; } + std::unique_ptr<Type> &get_elem_type_ptr () + { + rust_assert (elem_type != nullptr); + return elem_type; + } + // TODO: would a "vis_expr" be better? - Expr &get_size_expr () + AnonConst &get_size_expr () { - rust_assert (size != nullptr); - return *size; + // rust_assert (size != nullptr); + + return size; } + std::unique_ptr<Type> &get_element_type () { return elem_type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -671,6 +752,12 @@ protected: { return new ArrayType (*this); } + ArrayType *reconstruct_impl () const override + { + return new ArrayType (elem_type->reconstruct (), + size /* FIXME: This should be `reconstruct_expr()` */, + locus); + } }; /* A dynamically-sized type representing a "view" into a sequence of elements of @@ -717,13 +804,20 @@ public: return *elem_type; } + // Getter for direct access to the elem_type unique_ptr + std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; } + protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ SliceType *clone_type_no_bounds_impl () const override { return new SliceType (*this); } + SliceType *reconstruct_impl () const override + { + return new SliceType (elem_type->reconstruct (), locus); + } }; /* Type used in generic arguments to explicitly request type inference (wildcard @@ -734,13 +828,21 @@ class InferredType : public TypeNoBounds // e.g. Vec<_> = whatever protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ InferredType *clone_type_no_bounds_impl () const override { + // This goes through the copy constructor return new InferredType (*this); } + InferredType *reconstruct_impl () const override + { + // This goes through the base constructor which calls the base + // TypeNoBounds constructor, which allocates a new NodeId + return new InferredType (locus); + } + public: InferredType (location_t locus) : locus (locus) {} @@ -899,7 +1001,7 @@ public: return_type (std::move (type)), locus (locus) { if (!variadic_attrs.empty ()) - is_variadic = true; + _is_variadic = true; } // Copy constructor with clone @@ -957,11 +1059,29 @@ public: return *return_type; } + std::unique_ptr<TypeNoBounds> &get_return_type_ptr () + { + rust_assert (has_return_type ()); + return return_type; + } + FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; } + BareFunctionType *reconstruct_impl () const override + { + std::unique_ptr<TypeNoBounds> ret_type = nullptr; + if (return_type != nullptr) + ret_type = return_type->reconstruct (); + + return new BareFunctionType ( + for_lifetimes, function_qualifiers, params, + /* FIXME: Should params be reconstruct() as well? */ + _is_variadic, variadic_attrs, std::move (ret_type), locus); + } + protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ BareFunctionType *clone_type_no_bounds_impl () const override { return new BareFunctionType (*this); @@ -978,13 +1098,13 @@ class MacroInvocation; * function item type? * closure expression types? * primitive types (bool, int, float, char, str (the slice)) - * Although supposedly TypePaths are used to reference these types (including - * primitives) */ + * Although supposedly TypePaths are used to reference these types + * (including primitives) */ /* FIXME: Incomplete spec references: - * anonymous type parameters, aka "impl Trait in argument position" - impl then - * trait bounds abstract return types, aka "impl Trait in return position" - - * impl then trait bounds */ + * anonymous type parameters, aka "impl Trait in argument position" - impl + * then trait bounds abstract return types, aka "impl Trait in return + * position" - impl then trait bounds */ } // namespace AST } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-asm.cc b/gcc/rust/backend/rust-compile-asm.cc index 22498bc..b7143a8 100644 --- a/gcc/rust/backend/rust-compile-asm.cc +++ b/gcc/rust/backend/rust-compile-asm.cc @@ -1,5 +1,7 @@ #include "rust-compile-asm.h" #include "rust-compile-expr.h" +#include "rust-system.h" + namespace Rust { namespace Compile { @@ -72,57 +74,94 @@ CompileAsm::asm_construct_string_tree (HIR::InlineAsm &expr) return Backend::string_constant_expression (result); } +tl::optional<std::reference_wrapper<HIR::Expr>> +get_out_expr (HIR::InlineAsmOperand &operand) +{ + switch (operand.get_register_type ()) + { + case HIR::InlineAsmOperand::RegisterType::Out: + return *operand.get_out ().expr; + case HIR::InlineAsmOperand::RegisterType::InOut: + return *operand.get_in_out ().expr; + case HIR::InlineAsmOperand::RegisterType::SplitInOut: + return *operand.get_split_in_out ().out_expr; + case HIR::InlineAsmOperand::RegisterType::Const: + case HIR::InlineAsmOperand::RegisterType::Sym: + case HIR::InlineAsmOperand::RegisterType::Label: + case HIR::InlineAsmOperand::RegisterType::In: + break; + } + return tl::nullopt; +} + tree CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr) { // TODO: Do i need to do this? tree head = NULL_TREE; - for (auto &output : expr.get_operands ()) + for (auto &operand : expr.get_operands ()) { - if (output.get_register_type () - == AST::InlineAsmOperand::RegisterType::Out) - { - auto out = output.get_out (); - - tree out_tree = CompileExpr::Compile (*out.expr, this->ctx); - // expects a tree list - // TODO: This assumes that the output is a register - std::string expr_name = "=r"; - auto name = build_string (expr_name.size () + 1, expr_name.c_str ()); - head - = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name), - out_tree)); - - /*Backend::debug (head);*/ - /*head = chainon (head, out_tree);*/ - } + tl::optional<std::reference_wrapper<HIR::Expr>> out_expr + = get_out_expr (operand); + if (!out_expr.has_value ()) + continue; + + tree out_tree = CompileExpr::Compile (*out_expr, this->ctx); + // expects a tree list + // TODO: This assumes that the output is a register + std::string expr_name = "=r"; + auto name = build_string (expr_name.size () + 1, expr_name.c_str ()); + head = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name), + out_tree)); + + /*Backend::debug (head);*/ + /*head = chainon (head, out_tree);*/ } return head; } +tl::optional<std::reference_wrapper<HIR::Expr>> +get_in_expr (HIR::InlineAsmOperand &operand) +{ + switch (operand.get_register_type ()) + { + case HIR::InlineAsmOperand::RegisterType::In: + return *operand.get_in ().expr; + case HIR::InlineAsmOperand::RegisterType::InOut: + return *operand.get_in_out ().expr; + case HIR::InlineAsmOperand::RegisterType::SplitInOut: + return *operand.get_split_in_out ().in_expr; + case HIR::InlineAsmOperand::RegisterType::Const: + case HIR::InlineAsmOperand::RegisterType::Sym: + case HIR::InlineAsmOperand::RegisterType::Label: + case HIR::InlineAsmOperand::RegisterType::Out: + break; + } + return tl::nullopt; +} + tree CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr) { // TODO: Do i need to do this? tree head = NULL_TREE; - for (auto &input : expr.get_operands ()) + for (auto &operand : expr.get_operands ()) { - if (input.get_register_type () == AST::InlineAsmOperand::RegisterType::In) - { - auto in = input.get_in (); - - tree in_tree = CompileExpr::Compile (*in.expr, this->ctx); - // expects a tree list - // TODO: This assumes that the input is a register - std::string expr_name = "r"; - auto name = build_string (expr_name.size () + 1, expr_name.c_str ()); - head - = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name), - in_tree)); - - /*head = chainon (head, out_tree);*/ - } + tl::optional<std::reference_wrapper<HIR::Expr>> in_expr + = get_in_expr (operand); + if (!in_expr.has_value ()) + continue; + + tree in_tree = CompileExpr::Compile (*in_expr, this->ctx); + // expects a tree list + // TODO: This assumes that the input is a register + std::string expr_name = "r"; + auto name = build_string (expr_name.size () + 1, expr_name.c_str ()); + head = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name), + in_tree)); + + /*head = chainon (head, out_tree);*/ } return head; } @@ -141,5 +180,57 @@ CompileAsm::asm_construct_label_tree (HIR::InlineAsm &expr) return NULL_TREE; } +CompileLlvmAsm::CompileLlvmAsm (Context *ctx) : HIRCompileBase (ctx) {} + +tree +CompileLlvmAsm::construct_operands (std::vector<HIR::LlvmOperand> operands) +{ + tree head = NULL_TREE; + for (auto &operand : operands) + { + tree t = CompileExpr::Compile (*operand.expr, this->ctx); + auto name = build_string (operand.constraint.size () + 1, + operand.constraint.c_str ()); + head = chainon (head, + build_tree_list (build_tree_list (NULL_TREE, name), t)); + } + return head; +} + +tree +CompileLlvmAsm::construct_clobbers (std::vector<AST::TupleClobber> clobbers) +{ + tree head = NULL_TREE; + for (auto &clobber : clobbers) + { + auto name + = build_string (clobber.symbol.size () + 1, clobber.symbol.c_str ()); + head = chainon (head, build_tree_list (NULL_TREE, name)); + } + return head; +} + +tree +CompileLlvmAsm::tree_codegen_asm (HIR::LlvmInlineAsm &expr) +{ + tree ret = make_node (ASM_EXPR); + TREE_TYPE (ret) = void_type_node; + SET_EXPR_LOCATION (ret, expr.get_locus ()); + ASM_VOLATILE_P (ret) = expr.options.is_volatile; + + std::stringstream ss; + for (const auto &template_str : expr.templates) + { + ss << template_str.symbol << "\n"; + } + + ASM_STRING (ret) = Backend::string_constant_expression (ss.str ()); + ASM_INPUTS (ret) = construct_operands (expr.inputs); + ASM_OUTPUTS (ret) = construct_operands (expr.outputs); + ASM_CLOBBERS (ret) = construct_clobbers (expr.get_clobbers ()); + + return ret; +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-asm.h b/gcc/rust/backend/rust-compile-asm.h index 4abd24e..22be94a 100644 --- a/gcc/rust/backend/rust-compile-asm.h +++ b/gcc/rust/backend/rust-compile-asm.h @@ -56,6 +56,20 @@ public: tree tree_codegen_asm (HIR::InlineAsm &); }; + +class CompileLlvmAsm : private HIRCompileBase +{ +private: + tree construct_operands (std::vector<HIR::LlvmOperand> operands); + + tree construct_clobbers (std::vector<AST::TupleClobber>); + +public: + CompileLlvmAsm (Context *ctx); + + tree tree_codegen_asm (HIR::LlvmInlineAsm &); +}; + } // namespace Compile } // namespace Rust #endif // RUST_COMPILE_ASM diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index fdbca7f..d1db58e 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -32,6 +32,7 @@ #include "rust-type-util.h" #include "rust-compile-implitem.h" #include "rust-attribute-values.h" +#include "rust-attributes.h" #include "rust-immutable-name-resolution-context.h" #include "fold-const.h" @@ -251,25 +252,21 @@ void HIRCompileBase::handle_link_section_attribute_on_fndecl ( tree fndecl, const AST::Attribute &attr) { - if (!attr.has_attr_input ()) + auto msg_str = Analysis::Attributes::extract_string_literal (attr); + + if (!msg_str.has_value ()) { rust_error_at (attr.get_locus (), - "%<link_section%> expects exactly one argment"); + "malformed %<link_section%> attribute input"); return; } - rust_assert (attr.get_attr_input ().get_attr_input_type () - == AST::AttrInput::AttrInputType::LITERAL); - - auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &msg_str = literal.get_literal ().as_string (); - if (decl_section_name (fndecl)) { rust_warning_at (attr.get_locus (), 0, "section name redefined"); } - set_decl_section_name (fndecl, msg_str.c_str ()); + set_decl_section_name (fndecl, msg_str->c_str ()); } void @@ -416,13 +413,10 @@ HIRCompileBase::handle_must_use_attribute_on_fndecl (tree fndecl, if (attr.has_attr_input ()) { - rust_assert (attr.get_attr_input ().get_attr_input_type () - == AST::AttrInput::AttrInputType::LITERAL); + auto msg_str = Analysis::Attributes::extract_string_literal (attr); + rust_assert (msg_str.has_value ()); - auto &literal - = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &msg_str = literal.get_literal ().as_string (); - tree message = build_string (msg_str.size (), msg_str.c_str ()); + tree message = build_string (msg_str->size (), msg_str->c_str ()); value = tree_cons (nodiscard, message, NULL_TREE); } @@ -549,7 +543,7 @@ HIRCompileBase::mark_addressable (tree exp, location_t locus) } tree -HIRCompileBase::address_expression (tree expr, location_t location) +HIRCompileBase::address_expression (tree expr, location_t location, tree ptrty) { if (expr == error_mark_node) return error_mark_node; @@ -557,7 +551,10 @@ HIRCompileBase::address_expression (tree expr, location_t location) if (!mark_addressable (expr, location)) return error_mark_node; - return build_fold_addr_expr_loc (location, expr); + if (ptrty == NULL || ptrty == error_mark_node) + ptrty = build_pointer_type (TREE_TYPE (expr)); + + return build_fold_addr_expr_with_type_loc (location, expr, ptrty); } tree @@ -573,6 +570,25 @@ HIRCompileBase::compile_constant_expr ( } tree +HIRCompileBase::query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty, + HIR::Expr &const_value_expr) +{ + HIRCompileBase c (ctx); + + ctx->push_const_context (); + + HirId expr_id = const_value_expr.get_mappings ().get_hirid (); + location_t locus = const_value_expr.get_locus (); + tree capacity_expr = HIRCompileBase::compile_constant_expr ( + ctx, expr_id, expr_ty, expr_ty, Resolver::CanonicalPath::create_empty (), + const_value_expr, locus, locus); + + ctx->pop_const_context (); + + return fold_expr (capacity_expr); +} + +tree HIRCompileBase::indirect_expression (tree expr, location_t locus) { if (expr == error_mark_node) @@ -663,7 +679,8 @@ get_abi (const AST::AttrVec &outer_attrs, tree HIRCompileBase::compile_function ( - const std::string &fn_name, HIR::SelfParam &self_param, + bool is_root_item, const std::string &fn_name, + tl::optional<HIR::SelfParam> &self_param, std::vector<HIR::FunctionParam> &function_params, const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility, AST::AttrVec &outer_attrs, location_t locus, HIR::BlockExpr *function_body, @@ -673,8 +690,12 @@ HIRCompileBase::compile_function ( std::string ir_symbol_name = canonical_path.get () + fntype->subst_as_string (); + rust_debug_loc (locus, "--> Compiling [%s] - %s", ir_symbol_name.c_str (), + fntype->get_name ().c_str ()); + // we don't mangle the main fn since we haven't implemented the main shim - bool is_main_fn = fn_name.compare ("main") == 0; + bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item + && canonical_path.size () <= 2; if (is_main_fn) { rust_assert (!main_identifier_node); @@ -683,14 +704,9 @@ HIRCompileBase::compile_function ( } std::string asm_name = fn_name; - auto &mappings = Analysis::Mappings::get (); - - if (flag_name_resolution_2_0) - ir_symbol_name = mappings.get_current_crate_name () + "::" + ir_symbol_name; - unsigned int flags = 0; tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, - "" /* asm_name */, flags, locus); + tl::nullopt /* asm_name */, flags, locus); setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (), visibility, qualifiers, outer_attrs); @@ -710,24 +726,24 @@ HIRCompileBase::compile_function ( // setup the params TyTy::BaseType *tyret = fntype->get_return_type (); std::vector<Bvariable *> param_vars; - if (!self_param.is_error ()) + if (self_param) { rust_assert (fntype->is_method ()); TyTy::BaseType *self_tyty_lookup = fntype->get_self_type (); tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); Bvariable *compiled_self_param - = CompileSelfParam::compile (ctx, fndecl, self_param, self_type, - self_param.get_locus ()); + = CompileSelfParam::compile (ctx, fndecl, self_param.value (), + self_type, self_param->get_locus ()); param_vars.push_back (compiled_self_param); - ctx->insert_var_decl (self_param.get_mappings ().get_hirid (), + ctx->insert_var_decl (self_param->get_mappings ().get_hirid (), compiled_self_param); } // offset from + 1 for the TyTy::FnType being used when this is a method to // skip over Self on the FnType - bool is_method = !self_param.is_error (); + bool is_method = self_param.has_value (); size_t i = is_method ? 1 : 0; for (auto &referenced_param : function_params) { @@ -808,11 +824,12 @@ HIRCompileBase::compile_constant_item ( // machineary that we already have. This means the best approach is to // make a _fake_ function with a block so it can hold onto temps then // use our constexpr code to fold it completely or error_mark_node - Backend::typed_identifier receiver; + Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION); tree compiled_fn_type = Backend::function_type ( receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, NULL, locus); - tree fndecl = Backend::function (compiled_fn_type, ident, "", 0, locus); + tree fndecl + = Backend::function (compiled_fn_type, ident, tl::nullopt, 0, locus); TREE_READONLY (fndecl) = 1; tree enclosing_scope = NULL_TREE; diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index 4b4f8b0..3bf26af 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -29,7 +29,8 @@ class HIRCompileBase public: virtual ~HIRCompileBase () {} - static tree address_expression (tree expr, location_t locus); + static tree address_expression (tree expr, location_t locus, + tree ptrty = NULL_TREE); static tree compile_constant_expr ( Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type, @@ -37,6 +38,9 @@ public: const Resolver::CanonicalPath &canonical_path, HIR::Expr &const_value_expr, location_t locus, location_t expr_locus); + static tree query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty, + HIR::Expr &const_value_expr); + protected: HIRCompileBase (Context *ctx) : ctx (ctx) {} @@ -52,7 +56,7 @@ protected: TyTy::BaseType *expected, location_t lvalue_locus, location_t rvalue_locus); - tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual, + tree coerce_to_dyn_object (tree compiled_ref, TyTy::BaseType *actual, const TyTy::DynamicObjectType *ty, location_t locus); @@ -102,7 +106,8 @@ protected: HIR::Expr &const_value_expr, location_t locus, location_t expr_locus); - tree compile_function (const std::string &fn_name, HIR::SelfParam &self_param, + tree compile_function (bool is_root_item, const std::string &fn_name, + tl::optional<HIR::SelfParam> &self_param, std::vector<HIR::FunctionParam> &function_params, const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility, AST::AttrVec &outer_attrs, diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc index f844a27..03c36d2 100644 --- a/gcc/rust/backend/rust-compile-block.cc +++ b/gcc/rust/backend/rust-compile-block.cc @@ -19,6 +19,7 @@ #include "rust-compile-block.h" #include "rust-compile-stmt.h" #include "rust-compile-expr.h" +#include "rust-hir-expr.h" namespace Rust { namespace Compile { diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h index 37e3980..f84bace 100644 --- a/gcc/rust/backend/rust-compile-block.h +++ b/gcc/rust/backend/rust-compile-block.h @@ -20,6 +20,7 @@ #define RUST_COMPILE_BLOCK #include "rust-compile-base.h" +#include "rust-hir-expr.h" #include "rust-hir-visitor.h" namespace Rust { @@ -83,6 +84,8 @@ public: void visit (HIR::MethodCallExpr &) override {} void visit (HIR::FieldAccessExpr &) override {} void visit (HIR::BlockExpr &) override {} + void visit (HIR::AnonConst &) override {} + void visit (HIR::ConstBlock &) override {} void visit (HIR::ContinueExpr &) override {} void visit (HIR::BreakExpr &) override {} void visit (HIR::RangeFromToExpr &) override {} @@ -100,6 +103,8 @@ public: void visit (HIR::AwaitExpr &) override {} void visit (HIR::AsyncBlockExpr &) override {} void visit (HIR::InlineAsm &) override {} + void visit (HIR::LlvmInlineAsm &) override {} + void visit (HIR::OffsetOf &) override {} private: CompileConditionalBlocks (Context *ctx, Bvariable *result) @@ -137,6 +142,12 @@ public: translated = CompileBlock::compile (expr, ctx, result); } + void visit (HIR::ConstBlock &expr) override + { + rust_unreachable (); + // translated = CompileExpr::compile (expr, ctx, result); + } + // Empty visit for unused Expression HIR nodes. void visit (HIR::PathInExpression &) override {} void visit (HIR::QualifiedPathInExpression &) override {} @@ -182,6 +193,9 @@ public: void visit (HIR::AwaitExpr &) override {} void visit (HIR::AsyncBlockExpr &) override {} void visit (HIR::InlineAsm &) override {} + void visit (HIR::LlvmInlineAsm &) override {} + void visit (HIR::OffsetOf &) override {} + void visit (HIR::AnonConst &) override {} private: CompileExprWithBlock (Context *ctx, Bvariable *result) diff --git a/gcc/rust/backend/rust-compile-context.cc b/gcc/rust/backend/rust-compile-context.cc index 86f0894..349d492 100644 --- a/gcc/rust/backend/rust-compile-context.cc +++ b/gcc/rust/backend/rust-compile-context.cc @@ -22,9 +22,18 @@ namespace Rust { namespace Compile { +Context * +Context::get () +{ + static Context *instance; + if (instance == nullptr) + instance = new Context (); + + return instance; +} + Context::Context () - : resolver (Resolver::Resolver::get ()), - tyctx (Resolver::TypeCheckContext::get ()), + : tyctx (Resolver::TypeCheckContext::get ()), mappings (Analysis::Mappings::get ()), mangler (Mangler ()) { setup_builtins (); @@ -70,7 +79,8 @@ Context::type_hasher (tree type) hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type))); break; - case ARRAY_TYPE: { + case ARRAY_TYPE: + { if (TYPE_DOMAIN (type)) hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type))); if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) @@ -81,7 +91,8 @@ Context::type_hasher (tree type) } break; - case INTEGER_TYPE: { + case INTEGER_TYPE: + { tree t = TYPE_MAX_VALUE (type); if (!t) t = TYPE_MIN_VALUE (type); @@ -91,7 +102,8 @@ Context::type_hasher (tree type) } case REAL_TYPE: - case FIXED_POINT_TYPE: { + case FIXED_POINT_TYPE: + { unsigned prec = TYPE_PRECISION (type); hstate.add_object (prec); break; @@ -103,7 +115,8 @@ Context::type_hasher (tree type) case RECORD_TYPE: case UNION_TYPE: - case QUAL_UNION_TYPE: { + case QUAL_UNION_TYPE: + { for (tree t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) { hashval_t name_hash = IDENTIFIER_HASH_VALUE (DECL_NAME (t)); @@ -118,7 +131,8 @@ Context::type_hasher (tree type) break; case REFERENCE_TYPE: - case POINTER_TYPE: { + case POINTER_TYPE: + { hashval_t type_hash = type_hasher (TREE_TYPE (type)); hstate.add_object (type_hash); } diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index ce81a1d..e98bbc2 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -34,6 +34,10 @@ namespace Compile { struct fncontext { + fncontext (tree fndecl, ::Bvariable *ret_addr, TyTy::BaseType *retty) + : fndecl (fndecl), ret_addr (ret_addr), retty (retty) + {} + tree fndecl; ::Bvariable *ret_addr; TyTy::BaseType *retty; @@ -49,7 +53,7 @@ struct CustomDeriveInfo class Context { public: - Context (); + static Context *get (); void setup_builtins (); @@ -90,7 +94,6 @@ public: return type; } - Resolver::Resolver *get_resolver () { return resolver; } Resolver::TypeCheckContext *get_tyctx () { return tyctx; } Analysis::Mappings &get_mappings () { return mappings; } @@ -155,7 +158,7 @@ public: if (it == mono_fns.end ()) mono_fns[dId] = {}; - mono_fns[dId].push_back ({ref, fn}); + mono_fns[dId].emplace_back (ref, fn); } void insert_closure_decl (const TyTy::ClosureType *ref, tree fn) @@ -165,7 +168,7 @@ public: if (it == mono_closure_fns.end ()) mono_closure_fns[dId] = {}; - mono_closure_fns[dId].push_back ({ref, fn}); + mono_closure_fns[dId].emplace_back (ref, fn); } tree lookup_closure_decl (const TyTy::ClosureType *ref) @@ -280,7 +283,7 @@ public: void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty) { - fn_stack.push_back (fncontext{fn, ret_addr, retty}); + fn_stack.emplace_back (fn, ret_addr, retty); } void pop_fn () { fn_stack.pop_back (); } @@ -319,7 +322,13 @@ public: void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); } - Bvariable *peek_loop_context () { return loop_value_stack.back (); } + bool have_loop_context () const { return !loop_value_stack.empty (); } + + Bvariable *peek_loop_context () + { + rust_assert (!loop_value_stack.empty ()); + return loop_value_stack.back (); + } Bvariable *pop_loop_context () { @@ -333,7 +342,11 @@ public: loop_begin_labels.push_back (label); } - tree peek_loop_begin_label () { return loop_begin_labels.back (); } + tree peek_loop_begin_label () + { + rust_assert (!loop_begin_labels.empty ()); + return loop_begin_labels.back (); + } tree pop_loop_begin_label () { @@ -391,7 +404,8 @@ public: } private: - Resolver::Resolver *resolver; + Context (); + Resolver::TypeCheckContext *tyctx; Analysis::Mappings &mappings; Mangler mangler; diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index e4ab9f0..9a9c315 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -17,6 +17,8 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-expr.h" +#include "rust-backend.h" +#include "rust-compile-type.h" #include "rust-compile-struct-field-expr.h" #include "rust-compile-pattern.h" #include "rust-compile-resolve-path.h" @@ -30,8 +32,11 @@ #include "realmpfr.h" #include "convert.h" #include "print-tree.h" +#include "rust-hir-expr.h" #include "rust-system.h" +#include "rust-tree.h" #include "rust-tyty.h" +#include "tree-core.h" namespace Rust { namespace Compile { @@ -170,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); @@ -209,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); @@ -368,6 +373,38 @@ CompileExpr::visit (HIR::InlineAsm &expr) } void +CompileExpr::visit (HIR::LlvmInlineAsm &expr) +{ + CompileLlvmAsm asm_codegen (ctx); + ctx->add_statement (asm_codegen.tree_codegen_asm (expr)); +} + +void +CompileExpr::visit (HIR::OffsetOf &expr) +{ + TyTy::BaseType *type = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_type ().get_mappings ().get_hirid (), &type)) + { + translated = error_mark_node; + return; + } + + auto compiled_ty = TyTyResolveCompile::compile (ctx, type); + + rust_assert (TREE_CODE (compiled_ty) == RECORD_TYPE); + + // Create an identifier node for the field + auto field_id = Backend::get_identifier_node (expr.get_field ().as_string ()); + + // And now look it up and get its value for `byte_position` + auto field = Backend::lookup_field (compiled_ty, field_id); + auto field_value = TREE_VALUE (field); + + translated = byte_position (field_value); +} + +void CompileExpr::visit (HIR::IfExprConseqElse &expr) { TyTy::BaseType *if_type = nullptr; @@ -434,6 +471,18 @@ CompileExpr::visit (HIR::BlockExpr &expr) } void +CompileExpr::visit (HIR::AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +CompileExpr::visit (HIR::ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void CompileExpr::visit (HIR::UnsafeBlockExpr &expr) { expr.get_block_expr ().accept_vis (*this); @@ -464,6 +513,8 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr) rust_error_at (struct_expr.get_locus (), "unknown type"); return; } + if (!tyty->is<TyTy::ADTType> ()) + return; // it must be an ADT rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT); @@ -662,6 +713,15 @@ void CompileExpr::visit (HIR::LoopExpr &expr) { TyTy::BaseType *block_tyty = nullptr; + fncontext fnctx = ctx->peek_fn (); + if (ctx->const_context_p () && !DECL_DECLARED_CONSTEXPR_P (fnctx.fndecl)) + { + rich_location r (line_table, expr.get_locus ()); + rust_error_at (r, ErrorCode::E0658, + "%<loop%> is not allowed in const context"); + return; + } + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &block_tyty)) { @@ -669,7 +729,6 @@ CompileExpr::visit (HIR::LoopExpr &expr) return; } - fncontext fnctx = ctx->peek_fn (); tree enclosing_scope = ctx->peek_enclosing_scope (); tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); @@ -694,7 +753,8 @@ CompileExpr::visit (HIR::LoopExpr &expr) loop_label.get_lifetime ().get_mappings ().get_hirid (), label); } - tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ()); + tree loop_begin_label + = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ()); tree loop_begin_label_decl = Backend::label_definition_statement (loop_begin_label); ctx->add_statement (loop_begin_label_decl); @@ -736,7 +796,8 @@ CompileExpr::visit (HIR::WhileLoopExpr &expr) start_location, end_location); ctx->push_block (loop_block); - tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ()); + tree loop_begin_label + = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ()); tree loop_begin_label_decl = Backend::label_definition_statement (loop_begin_label); ctx->add_statement (loop_begin_label_decl); @@ -767,6 +828,10 @@ CompileExpr::visit (HIR::BreakExpr &expr) { tree compiled_expr = CompileExpr::Compile (expr.get_expr (), ctx); + translated = error_mark_node; + if (!ctx->have_loop_context ()) + return; + Bvariable *loop_result_holder = ctx->peek_loop_context (); tree result_reference = Backend::var_expression (loop_result_holder, @@ -780,25 +845,16 @@ CompileExpr::visit (HIR::BreakExpr &expr) if (expr.has_label ()) { - NodeId resolved_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id - = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) - resolved_node_id = *id; - } - else + NodeId resolved_node_id; + if (auto id + = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) { - NodeId tmp = UNKNOWN_NODEID; - if (ctx->get_resolver ()->lookup_resolved_label ( - expr.get_label ().get_mappings ().get_nodeid (), &tmp)) - resolved_node_id = tmp; + resolved_node_id = *id; } - - if (resolved_node_id == UNKNOWN_NODEID) + else { rust_error_at ( expr.get_label ().get_locus (), @@ -839,29 +895,23 @@ CompileExpr::visit (HIR::BreakExpr &expr) void CompileExpr::visit (HIR::ContinueExpr &expr) { + translated = error_mark_node; + if (!ctx->have_loop_context ()) + return; + tree label = ctx->peek_loop_begin_label (); if (expr.has_label ()) { - NodeId resolved_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id - = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) - resolved_node_id = *id; - } - else + NodeId resolved_node_id; + if (auto id + = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) { - NodeId tmp = UNKNOWN_NODEID; - - if (ctx->get_resolver ()->lookup_resolved_label ( - expr.get_label ().get_mappings ().get_nodeid (), &tmp)) - resolved_node_id = tmp; + resolved_node_id = *id; } - - if (resolved_node_id == UNKNOWN_NODEID) + else { rust_error_at ( expr.get_label ().get_locus (), @@ -905,7 +955,8 @@ CompileExpr::visit (HIR::BorrowExpr &expr) &tyty)) return; - translated = address_expression (main_expr, expr.get_locus ()); + tree expected_type = TyTyResolveCompile::compile (ctx, tyty); + translated = address_expression (main_expr, expr.get_locus (), expected_type); } void @@ -1122,9 +1173,8 @@ CompileExpr::visit (HIR::MatchExpr &expr) // setup the end label so the cases can exit properly tree fndecl = fnctx.fndecl; location_t end_label_locus = expr.get_locus (); // FIXME - tree end_label - = Backend::label (fndecl, "" /* empty creates an artificial label */, - end_label_locus); + // tl::nullopt creates an artificial label + tree end_label = Backend::label (fndecl, tl::nullopt, end_label_locus); tree end_label_decl_statement = Backend::label_definition_statement (end_label); @@ -1317,6 +1367,28 @@ CompileExpr::visit (HIR::CallExpr &expr) }; auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx); + if (ctx->const_context_p ()) + { + if (!FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn_address))) + { + rust_error_at (expr.get_locus (), + "calls in constants are limited to constant " + "functions, tuple structs and tuple variants"); + return; + } + + if (TREE_CODE (fn_address) == ADDR_EXPR) + { + tree fndecl = TREE_OPERAND (fn_address, 0); + if (!DECL_DECLARED_CONSTEXPR_P (fndecl)) + { + rust_error_at (expr.get_locus (), + "calls in constants are limited to constant " + "functions, tuple structs and tuple variants"); + return; + } + } + } // is this a closure call? bool possible_trait_call @@ -1583,37 +1655,39 @@ CompileExpr::compile_integer_literal (const HIR::LiteralExpr &expr, const TyTy::BaseType *tyty) { rust_assert (expr.get_lit_type () == HIR::Literal::INT); - const auto literal_value = expr.get_literal (); - + const auto &literal_value = expr.get_literal (); tree type = TyTyResolveCompile::compile (ctx, tyty); + std::string s = literal_value.as_string (); + s.erase (std::remove (s.begin (), s.end (), '_'), s.end ()); + + int base = 0; mpz_t ival; - if (mpz_init_set_str (ival, literal_value.as_string ().c_str (), 10) != 0) + if (mpz_init_set_str (ival, s.c_str (), base) != 0) { - rust_error_at (expr.get_locus (), "bad number in literal"); + rust_error_at (expr.get_locus (), "failed to load number literal"); return error_mark_node; } + if (expr.is_negative ()) + mpz_neg (ival, ival); - mpz_t type_min; - mpz_t type_max; + mpz_t type_min, type_max; mpz_init (type_min); mpz_init (type_max); get_type_static_bounds (type, type_min, type_max); - if (expr.is_negative ()) - { - mpz_neg (ival, ival); - } if (mpz_cmp (ival, type_min) < 0 || mpz_cmp (ival, type_max) > 0) { rust_error_at (expr.get_locus (), "integer overflows the respective type %qs", tyty->get_name ().c_str ()); + mpz_clear (type_min); + mpz_clear (type_max); + mpz_clear (ival); return error_mark_node; } tree result = wide_int_to_tree (type, wi::from_mpz (type, ival, true)); - mpz_clear (type_min); mpz_clear (type_max); mpz_clear (ival); @@ -1638,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 @@ -1875,7 +1951,8 @@ CompileExpr::visit (HIR::ArrayExpr &expr) HIR::ArrayElems &elements = expr.get_internal_elements (); switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { HIR::ArrayElemsValues &elems = static_cast<HIR::ArrayElemsValues &> (elements); translated @@ -1935,13 +2012,25 @@ CompileExpr::array_copied_expr (location_t expr_locus, return error_mark_node; } - ctx->push_const_context (); - tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), ctx); - ctx->pop_const_context (); + auto capacity_ty = array_tyty.get_capacity (); - if (!TREE_CONSTANT (capacity_expr)) + // Check if capacity is a const type + if (capacity_ty->get_kind () != TyTy::TypeKind::CONST) { - rust_error_at (expr_locus, "non const num copies %qT", array_type); + rust_error_at (array_tyty.get_locus (), + "array capacity is not a const type"); + return error_mark_node; + } + + auto *capacity_const = capacity_ty->as_const_type (); + + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const); + auto cap_tree = capacity_value.get_value (); + if (error_operand_p (cap_tree) || !TREE_CONSTANT (cap_tree)) + { + rust_error_at (expr_locus, "non const num copies %qT", cap_tree); return error_mark_node; } @@ -1964,8 +2053,12 @@ CompileExpr::array_copied_expr (location_t expr_locus, if (ctx->const_context_p ()) { size_t idx = 0; + std::vector<unsigned long> indexes; std::vector<tree> constructor; + + indexes.reserve (len); + constructor.reserve (len); for (unsigned HOST_WIDE_INT i = 0; i < len; i++) { constructor.push_back (translated_expr); @@ -1990,9 +2083,9 @@ CompileExpr::array_copied_expr (location_t expr_locus, ctx->push_block (init_block); tree tmp; - tree stmts = Backend::array_initializer (fndecl, init_block, array_type, - capacity_expr, translated_expr, - &tmp, expr_locus); + tree stmts + = Backend::array_initializer (fndecl, init_block, array_type, cap_tree, + translated_expr, &tmp, expr_locus); ctx->add_statement (stmts); tree block = ctx->pop_block (); @@ -2020,7 +2113,8 @@ HIRCompileBase::resolve_adjustements ( return error_mark_node; case Resolver::Adjustment::AdjustmentType::IMM_REF: - case Resolver::Adjustment::AdjustmentType::MUT_REF: { + case Resolver::Adjustment::AdjustmentType::MUT_REF: + { if (!RS_DST_FLAG (TREE_TYPE (e))) { e = address_expression (e, locus); @@ -2139,11 +2233,10 @@ HIRCompileBase::resolve_unsized_dyn_adjustment ( tree rvalue = expression; location_t rvalue_locus = locus; - const TyTy::BaseType *actual = adjustment.get_actual (); - const TyTy::BaseType *expected = adjustment.get_expected (); + auto actual = adjustment.get_actual (); + auto expected = adjustment.get_expected (); - const TyTy::DynamicObjectType *dyn - = static_cast<const TyTy::DynamicObjectType *> (expected); + const auto dyn = static_cast<const TyTy::DynamicObjectType *> (expected); rust_debug ("resolve_unsized_dyn_adjustment actual={%s} dyn={%s}", actual->debug_str ().c_str (), dyn->debug_str ().c_str ()); @@ -2462,23 +2555,12 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, if (is_block_expr) { auto body_mappings = function_body.get_mappings (); - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ()); + auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ()); - rust_assert (candidate.has_value ()); - } - else - { - Resolver::Rib *rib = nullptr; - bool ok - = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), - &rib); - rust_assert (ok); - } + rust_assert (candidate.has_value ()); } tree enclosing_scope = NULL_TREE; @@ -2558,15 +2640,15 @@ CompileExpr::generate_closure_fntype (HIR::ClosureExpr &expr, TyTy::TypeBoundPredicateItem item = TyTy::TypeBoundPredicateItem::error (); if (predicate.get_name ().compare ("FnOnce") == 0) { - item = predicate.lookup_associated_item ("call_once"); + item = predicate.lookup_associated_item ("call_once").value (); } else if (predicate.get_name ().compare ("FnMut") == 0) { - item = predicate.lookup_associated_item ("call_mut"); + item = predicate.lookup_associated_item ("call_mut").value (); } else if (predicate.get_name ().compare ("Fn") == 0) { - item = predicate.lookup_associated_item ("call"); + item = predicate.lookup_associated_item ("call").value (); } else { diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index dc78dee..b8b4e8d 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -48,6 +48,8 @@ public: void visit (HIR::IfExpr &expr) override; void visit (HIR::IfExprConseqElse &expr) override; void visit (HIR::BlockExpr &expr) override; + void visit (HIR::AnonConst &expr) override; + void visit (HIR::ConstBlock &expr) override; void visit (HIR::UnsafeBlockExpr &expr) override; void visit (HIR::StructExprStruct &struct_expr) override; void visit (HIR::StructExprStructFields &struct_expr) override; @@ -69,6 +71,8 @@ public: void visit (HIR::RangeFromToInclExpr &expr) override; void visit (HIR::ClosureExpr &expr) override; void visit (HIR::InlineAsm &expr) override; + void visit (HIR::LlvmInlineAsm &expr) override; + void visit (HIR::OffsetOf &expr) override; // TODO void visit (HIR::ErrorPropagationExpr &) override {} diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index bacd1c0..a78f9ee 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -24,6 +24,8 @@ #include "rust-compile-type.h" #include "rust-diagnostics.h" #include "rust-hir-full-decls.h" +#include "rust-attributes.h" +#include "rust-attribute-values.h" namespace Rust { namespace Compile { @@ -34,16 +36,10 @@ class CompileExternItem : public HIRCompileBase, public: static tree compile (HIR::ExternalItem *item, Context *ctx, TyTy::BaseType *concrete = nullptr, - bool is_query_mode = false, location_t ref_locus = UNDEF_LOCATION) { CompileExternItem compiler (ctx, concrete, ref_locus); item->accept_vis (compiler); - - if (is_query_mode && compiler.reference == error_mark_node) - rust_internal_error_at (ref_locus, "failed to compile extern item: %s", - item->as_string ().c_str ()); - return compiler.reference; } @@ -63,8 +59,7 @@ public: rust_assert (ok); std::string name = item.get_item_name ().as_string (); - // FIXME this is assuming C ABI - std::string asm_name = name; + GGC::Ident asm_name = get_link_name (item); tree type = TyTyResolveCompile::compile (ctx, resolved_type); bool is_external = true; @@ -130,16 +125,7 @@ public: tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); std::string ir_symbol_name = function.get_item_name ().as_string (); - std::string asm_name = function.get_item_name ().as_string (); - if (fntype->get_abi () == ABI::RUST) - { - // then we need to get the canonical path of it and mangle it - auto canonical_path = ctx->get_mappings ().lookup_canonical_path ( - function.get_mappings ().get_nodeid ()); - - ir_symbol_name = canonical_path->get () + fntype->subst_as_string (); - asm_name = ctx->mangle_item (fntype, *canonical_path); - } + GGC::Ident asm_name = get_link_name (function); const unsigned int flags = Backend::function_is_declaration; tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, asm_name, @@ -164,6 +150,36 @@ private: ref_locus (ref_locus) {} + template <typename T> static GGC::Ident get_link_name (T &obj) + { + AST::Attribute *use_attr = nullptr; + + for (auto &attr : obj.get_outer_attrs ()) + { + if (attr.get_path ().as_string () == Values::Attributes::LINK_NAME) + { + // later attributes override earlier ones + // TODO: add warning -- should duplicate + // attributes be folded elsewhere? + use_attr = &attr; + } + } + + if (use_attr) + { + auto link_name + = Analysis::Attributes::extract_string_literal (*use_attr); + + if (!link_name.has_value ()) + rust_error_at (use_attr->get_locus (), + "malformed %<link_name%> attribute input"); + else + return *link_name; + } + + return obj.get_item_name (); + } + TyTy::BaseType *concrete; tree reference; location_t ref_locus; diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc index 71b3e8d..63df2f5 100644 --- a/gcc/rust/backend/rust-compile-implitem.cc +++ b/gcc/rust/backend/rust-compile-implitem.cc @@ -27,22 +27,11 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant) rust_assert (concrete != nullptr); TyTy::BaseType *resolved_type = concrete; - tl::optional<Resolver::CanonicalPath> canonical_path; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path = nr_ctx.values.to_canonical_path ( - constant.get_mappings ().get_nodeid ()); - } - else - { - canonical_path = ctx->get_mappings ().lookup_canonical_path ( - constant.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path); + Resolver::CanonicalPath canonical_path + = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ()); HIR::Expr &const_value_expr = constant.get_expr (); TyTy::BaseType *expr_type = nullptr; @@ -52,7 +41,7 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant) tree const_expr = compile_constant_item (constant.get_mappings ().get_hirid (), expr_type, - resolved_type, *canonical_path, const_value_expr, + resolved_type, canonical_path, const_value_expr, constant.get_locus (), const_value_expr.get_locus ()); ctx->push_const (const_expr); @@ -96,32 +85,21 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func) fntype->override_context (); } - tl::optional<Resolver::CanonicalPath> canonical_path; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.values.to_canonical_path (func.get_mappings ().get_nodeid ()); - } - else - { - canonical_path = ctx->get_mappings ().lookup_canonical_path ( - func.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path); + Resolver::CanonicalPath canonical_path + = nr_ctx.to_canonical_path (func.get_mappings ().get_nodeid ()); // FIXME: How do we get the proper visibility here? auto vis = HIR::Visibility (HIR::Visibility::VisType::PUBLIC); HIR::TraitFunctionDecl &function = func.get_decl (); tree fndecl - = compile_function (function.get_function_name ().as_string (), + = compile_function (false, function.get_function_name ().as_string (), function.get_self (), function.get_function_params (), function.get_qualifiers (), vis, func.get_outer_attrs (), func.get_locus (), - &func.get_block_expr (), *canonical_path, fntype); + &func.get_block_expr (), canonical_path, fntype); reference = address_expression (fndecl, ref_locus); } diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index d2ef989..2d18dbf 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -30,16 +30,10 @@ class CompileInherentImplItem : public CompileItem public: static tree Compile (HIR::ImplItem *item, Context *ctx, TyTy::BaseType *concrete = nullptr, - bool is_query_mode = false, location_t ref_locus = UNDEF_LOCATION) { CompileInherentImplItem compiler (ctx, concrete, ref_locus); item->accept_vis (compiler); - - if (is_query_mode && compiler.reference == error_mark_node) - rust_internal_error_at (ref_locus, "failed to compile impl item: %s", - item->as_string ().c_str ()); - return compiler.reference; } diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 4888e23..450a869 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -32,8 +32,7 @@ // declaration taken from "stringpool.h" // the get_identifier macro causes compilation issues -extern tree -get_identifier (const char *); +extern tree get_identifier (const char *); namespace Rust { namespace Compile { @@ -70,28 +69,19 @@ check_for_basic_integer_type (const std::string &intrinsic_str, return is_basic_integer; } -static tree -offset_handler (Context *ctx, TyTy::FnType *fntype); -static tree -sizeof_handler (Context *ctx, TyTy::FnType *fntype); -static tree -transmute_handler (Context *ctx, TyTy::FnType *fntype); -static tree -rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -uninit_handler (Context *ctx, TyTy::FnType *fntype); -static tree -move_val_init_handler (Context *ctx, TyTy::FnType *fntype); -static tree -assume_handler (Context *ctx, TyTy::FnType *fntype); -static tree -discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); -static tree -variant_count_handler (Context *ctx, TyTy::FnType *fntype); +static tree offset_handler (Context *ctx, TyTy::FnType *fntype); +static tree sizeof_handler (Context *ctx, TyTy::FnType *fntype); +static tree transmute_handler (Context *ctx, TyTy::FnType *fntype); +static tree rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op); +static tree wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); +static tree op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); +static tree uninit_handler (Context *ctx, TyTy::FnType *fntype); +static tree move_val_init_handler (Context *ctx, TyTy::FnType *fntype); +static tree assume_handler (Context *ctx, TyTy::FnType *fntype); +static tree discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); +static tree variant_count_handler (Context *ctx, TyTy::FnType *fntype); enum class Prefetch { @@ -99,8 +89,8 @@ enum class Prefetch Write }; -static tree -prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind); +static tree prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, + Prefetch kind); static inline tree rotate_left_handler (Context *ctx, TyTy::FnType *fntype) @@ -140,10 +130,10 @@ prefetch_write_data (Context *ctx, TyTy::FnType *fntype) return prefetch_data_handler (ctx, fntype, Prefetch::Write); } -static tree -atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering); -static tree -atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering); +static tree atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, + int ordering); +static tree atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, + int ordering); static inline std::function<tree (Context *, TyTy::FnType *)> atomic_store_handler (int ordering) @@ -161,8 +151,8 @@ atomic_load_handler (int ordering) }; } -static inline tree -unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); +static inline tree unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); const static std::function<tree (Context *, TyTy::FnType *)> unchecked_op_handler (tree_code op) @@ -172,8 +162,8 @@ unchecked_op_handler (tree_code op) }; } -static inline tree -copy_handler_inner (Context *ctx, TyTy::FnType *fntype, bool overlaps); +static inline tree copy_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool overlaps); const static std::function<tree (Context *, TyTy::FnType *)> copy_handler (bool overlaps) @@ -183,8 +173,8 @@ copy_handler (bool overlaps) }; } -static inline tree -expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely); +static inline tree expect_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool likely); const static std::function<tree (Context *, TyTy::FnType *)> expect_handler (bool likely) @@ -194,8 +184,8 @@ expect_handler (bool likely) }; } -static tree -try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api); +static tree try_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool is_new_api); const static std::function<tree (Context *, TyTy::FnType *)> try_handler (bool is_new_api) @@ -447,8 +437,8 @@ sizeof_handler (Context *ctx, TyTy::FnType *fntype) // get the template parameter type tree fn size_of<T>(); rust_assert (fntype->get_num_substitutions () == 1); auto ¶m_mapping = fntype->get_substs ().at (0); - const TyTy::ParamType *param_tyty = param_mapping.get_param_ty (); - TyTy::BaseType *resolved_tyty = param_tyty->resolve (); + const auto param_tyty = param_mapping.get_param_ty (); + auto resolved_tyty = param_tyty->resolve (); tree template_parameter_type = TyTyResolveCompile::compile (ctx, resolved_tyty); @@ -653,8 +643,8 @@ op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op) rust_assert (fntype->get_num_substitutions () == 1); auto ¶m_mapping = fntype->get_substs ().at (0); - const TyTy::ParamType *param_tyty = param_mapping.get_param_ty (); - TyTy::BaseType *resolved_tyty = param_tyty->resolve (); + const auto param_tyty = param_mapping.get_param_ty (); + auto resolved_tyty = param_tyty->resolve (); tree template_parameter_type = TyTyResolveCompile::compile (ctx, resolved_tyty); @@ -1089,8 +1079,8 @@ uninit_handler (Context *ctx, TyTy::FnType *fntype) // get the template parameter type tree fn uninit<T>(); rust_assert (fntype->get_num_substitutions () == 1); auto ¶m_mapping = fntype->get_substs ().at (0); - const TyTy::ParamType *param_tyty = param_mapping.get_param_ty (); - TyTy::BaseType *resolved_tyty = param_tyty->resolve (); + const auto param_tyty = param_mapping.get_param_ty (); + auto resolved_tyty = param_tyty->resolve (); tree template_parameter_type = TyTyResolveCompile::compile (ctx, resolved_tyty); @@ -1154,8 +1144,8 @@ move_val_init_handler (Context *ctx, TyTy::FnType *fntype) // get the template parameter type tree fn size_of<T>(); rust_assert (fntype->get_num_substitutions () == 1); auto ¶m_mapping = fntype->get_substs ().at (0); - const TyTy::ParamType *param_tyty = param_mapping.get_param_ty (); - TyTy::BaseType *resolved_tyty = param_tyty->resolve (); + auto param_tyty = param_mapping.get_param_ty (); + auto resolved_tyty = param_tyty->resolve (); tree template_parameter_type = TyTyResolveCompile::compile (ctx, resolved_tyty); diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 7ce9848..d908710 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -50,33 +50,21 @@ CompileItem::visit (HIR::StaticItem &var) tree type = TyTyResolveCompile::compile (ctx, resolved_type); - tl::optional<Resolver::CanonicalPath> canonical_path; + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.values.to_canonical_path (var.get_mappings ().get_nodeid ()); - } - else - { - canonical_path = ctx->get_mappings ().lookup_canonical_path ( - var.get_mappings ().get_nodeid ()); - } - - rust_assert (canonical_path.has_value ()); + Resolver::CanonicalPath canonical_path + = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ()); ctx->push_const_context (); tree value = compile_constant_item (var.get_mappings ().get_hirid (), expr_type, - resolved_type, *canonical_path, const_value_expr, + resolved_type, canonical_path, const_value_expr, var.get_locus (), const_value_expr.get_locus ()); ctx->pop_const_context (); - std::string name = canonical_path->get (); - std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path); + std::string name = canonical_path.get (); + std::string asm_name = ctx->mangle_item (resolved_type, canonical_path); bool is_external = false; bool is_hidden = false; @@ -115,23 +103,22 @@ CompileItem::visit (HIR::ConstantItem &constant) const_value_expr.get_mappings ().get_hirid (), &expr_type); rust_assert (ok); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + // canonical path Resolver::CanonicalPath canonical_path - = Resolver::CanonicalPath::create_empty (); - - if (flag_name_resolution_2_0) + = nr_ctx.to_canonical_path (mappings.get_nodeid ()); + if (constant_type->is<const TyTy::FnType> ()) { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + if (concrete == nullptr) + return; - canonical_path - = nr_ctx.values.to_canonical_path (mappings.get_nodeid ()).value (); - } - else - { - canonical_path = ctx->get_mappings () - .lookup_canonical_path (mappings.get_nodeid ()) - .value (); + 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 (); @@ -210,26 +197,11 @@ CompileItem::visit (HIR::Function &function) } } - Resolver::CanonicalPath canonical_path - = Resolver::CanonicalPath::create_empty (); - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - auto path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = path.value (); - } - else - { - auto path = ctx->get_mappings ().lookup_canonical_path ( - function.get_mappings ().get_nodeid ()); - - canonical_path = *path; - } + Resolver::CanonicalPath canonical_path + = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); const std::string asm_name = ctx->mangle_item (fntype, canonical_path); @@ -252,8 +224,12 @@ CompileItem::visit (HIR::Function &function) if (function.get_qualifiers ().is_const ()) ctx->push_const_context (); + auto lookup_root_item = ctx->get_mappings ().lookup_hir_item ( + function.get_mappings ().get_hirid ()); + bool is_root_item = lookup_root_item.has_value (); tree fndecl - = compile_function (function.get_function_name ().as_string (), + = compile_function (is_root_item, + function.get_function_name ().as_string (), function.get_self_param (), function.get_function_params (), function.get_qualifiers (), function.get_visibility (), @@ -296,5 +272,65 @@ CompileItem::visit (HIR::Module &module) CompileItem::compile (item.get (), ctx); } +void +CompileItem::visit (HIR::TupleStruct &tuple_struct_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + tuple_struct_decl.get_mappings ().get_hirid (), &lookup)) + { + rust_error_at (tuple_struct_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::Enum &enum_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (enum_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (enum_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::Union &union_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (union_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (union_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::StructStruct &struct_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (struct_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (struct_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index eccb040..56baaab 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -35,10 +35,6 @@ public: { CompileItem compiler (ctx, concrete, ref_locus); item->accept_vis (compiler); - - if (compiler.reference == error_mark_node) - rust_debug ("failed to compile item: %s", item->as_string ().c_str ()); - return compiler.reference; } @@ -48,9 +44,12 @@ public: void visit (HIR::ImplBlock &impl_block) override; void visit (HIR::ExternBlock &extern_block) override; void visit (HIR::Module &module) override; + void visit (HIR::TupleStruct &tuple_struct) override; + void visit (HIR::Enum &enum_decl) override; + void visit (HIR::Union &union_decl) override; + void visit (HIR::StructStruct &struct_decl) override; // Empty visit for unused Stmt HIR nodes. - void visit (HIR::TupleStruct &) override {} void visit (HIR::EnumItem &) override {} void visit (HIR::EnumItemTuple &) override {} void visit (HIR::EnumItemStruct &) override {} @@ -61,9 +60,6 @@ public: void visit (HIR::ExternCrate &) override {} void visit (HIR::UseDeclaration &) override {} void visit (HIR::TypeAlias &) override {} - void visit (HIR::StructStruct &) override {} - void visit (HIR::Enum &) override {} - void visit (HIR::Union &) override {} void visit (HIR::Trait &) override {} void visit (HIR::EmptyStmt &) override {} void visit (HIR::LetStmt &) override {} diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index e83717b..af5f453 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -22,6 +22,12 @@ #include "rust-constexpr.h" #include "rust-compile-type.h" #include "print-tree.h" +#include "rust-diagnostics.h" +#include "rust-hir-pattern-abstract.h" +#include "rust-hir-pattern.h" +#include "rust-system.h" +#include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Compile { @@ -81,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. @@ -107,17 +115,21 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, tree result = NULL_TREE; switch (bound.get_bound_type ()) { - case HIR::RangePatternBound::RangePatternBoundType::LITERAL: { + case HIR::RangePatternBound::RangePatternBoundType::LITERAL: + { auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (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); } break; - case HIR::RangePatternBound::RangePatternBoundType::PATH: { + case HIR::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound); result = ResolvePathRef::Compile (ref.get_path (), ctx); @@ -127,7 +139,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, } break; - case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: { + case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound); result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx); @@ -150,13 +163,39 @@ 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; tree check_lower = Backend::comparison_expression (ComparisonOperator::GREATER_OR_EQUAL, match_scrutinee_expr, lower, pattern.get_locus ()); tree check_upper - = Backend::comparison_expression (ComparisonOperator::LESS_OR_EQUAL, - match_scrutinee_expr, upper, + = Backend::comparison_expression (upper_cmp, match_scrutinee_expr, upper, pattern.get_locus ()); check_expr = Backend::arithmetic_or_logical_expression ( ArithmeticOrLogicalOperator::BITWISE_AND, check_lower, check_upper, @@ -204,6 +243,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) rust_assert (adt->number_of_variants () > 0); TyTy::VariantDef *variant = nullptr; + tree variant_accesser_expr = nullptr; if (adt->is_enum ()) { // lookup the variant @@ -218,9 +258,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) // find expected discriminant // // need to access qualifier the field, if we use QUAL_UNION_TYPE this - // // would be DECL_QUALIFIER i think. For now this will just access the - // // first record field and its respective qualifier because it will - // // always be set because this is all a big special union + // // would be DECL_QUALIFIER i think. HIR::Expr &discrim_expr = variant->get_discriminant (); tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); @@ -229,6 +267,14 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) = Backend::struct_field_expression (match_scrutinee_expr, 0, pattern.get_path ().get_locus ()); + // access variant data + tree scrutinee_union_expr + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_path ().get_locus ()); + variant_accesser_expr + = Backend::struct_field_expression (scrutinee_union_expr, variant_index, + pattern.get_path ().get_locus ()); + check_expr = Backend::comparison_expression (ComparisonOperator::EQUAL, scrutinee_expr_qualifier_expr, @@ -240,6 +286,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) else { variant = adt->get_variants ().at (0); + variant_accesser_expr = match_scrutinee_expr; check_expr = boolean_true_node; } @@ -248,13 +295,15 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO rust_unreachable (); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat &ident = static_cast<HIR::StructPatternFieldIdentPat &> (*field.get ()); @@ -263,11 +312,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) nullptr, &offs); rust_assert (ok); - // we may be offsetting by + 1 here since the first field in the - // record is always the discriminator - offs += adt->is_enum (); tree field_expr - = Backend::struct_field_expression (match_scrutinee_expr, offs, + = Backend::struct_field_expression (variant_accesser_expr, offs, ident.get_locus ()); tree check_expr_sub @@ -279,7 +325,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) } break; - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { // ident pattern always matches - do nothing } break; @@ -338,36 +385,38 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { - // TODO - rust_unreachable (); - } - break; + case HIR::TupleStructItems::HAS_REST: + { + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (items); + size_t num_patterns = items_has_rest.get_lower_patterns ().size () + + items_has_rest.get_upper_patterns ().size (); - case HIR::TupleStructItems::MULTIPLE: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); - - rust_assert (items_no_range.get_patterns ().size () - == variant->num_fields ()); + // enums cases shouldn't reach here + rust_assert (num_patterns <= variant->num_fields () + && (!adt->is_enum ())); size_t tuple_field_index = 0; - for (auto &pattern : items_no_range.get_patterns ()) + for (auto &pattern : items_has_rest.get_lower_patterns ()) { - // find payload union field of scrutinee - tree payload_ref - = Backend::struct_field_expression (match_scrutinee_expr, 1, - pattern->get_locus ()); - - tree variant_ref - = Backend::struct_field_expression (payload_ref, variant_index, + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, pattern->get_locus ()); - + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern->get_locus ()); + } + tuple_field_index = variant->num_fields () + - items_has_rest.get_upper_patterns ().size (); + for (auto &pattern : items_has_rest.get_upper_patterns ()) + { tree field_expr - = Backend::struct_field_expression (variant_ref, + = Backend::struct_field_expression (match_scrutinee_expr, tuple_field_index++, pattern->get_locus ()); - tree check_expr_sub = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx); check_expr = Backend::arithmetic_or_logical_expression ( @@ -376,6 +425,64 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) } } break; + + case HIR::TupleStructItems::NO_REST: + { + HIR::TupleStructItemsNoRest &items_no_range + = static_cast<HIR::TupleStructItemsNoRest &> (items); + + rust_assert (items_no_range.get_patterns ().size () + == variant->num_fields ()); + + if (adt->is_enum ()) + { + size_t tuple_field_index = 0; + for (auto &pattern : items_no_range.get_patterns ()) + { + // find payload union field of scrutinee + tree payload_ref + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern->get_locus ()); + + tree variant_ref + = Backend::struct_field_expression (payload_ref, + variant_index, + pattern->get_locus ()); + + tree field_expr + = Backend::struct_field_expression (variant_ref, + tuple_field_index++, + pattern->get_locus ()); + + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern, field_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern->get_locus ()); + } + } + else + { + // For non-enum TupleStructPatterns + size_t tuple_field_index = 0; + for (auto &pattern : items_no_range.get_patterns ()) + { + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pattern->get_locus ()); + + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern, field_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern->get_locus ()); + } + } + break; + } } } @@ -386,15 +493,59 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::RANGED: { - // TODO - gcc_unreachable (); + case HIR::TuplePatternItems::HAS_REST: + { + auto &items + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); + size_t tuple_field_index = 0; + + // lookup the type to find out number of fields + TyTy::BaseType *ty = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + pattern.get_mappings ().get_hirid (), &ty); + rust_assert (ok); + rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE); + + // compile check expr for lower patterns + for (auto &pat : items.get_lower_patterns ()) + { + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pat->get_locus ()); + + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pat->get_locus ()); + } + + // skip the fields that are not checked + tuple_field_index = static_cast<TyTy::TupleType &> (*ty).num_fields () + - items.get_upper_patterns ().size (); + + // compile check expr for upper patterns + for (auto &pat : items.get_upper_patterns ()) + { + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pat->get_locus ()); + + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pat->get_locus ()); + } } break; - case HIR::TuplePatternItems::MULTIPLE: { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + case HIR::TuplePatternItems::NO_REST: + { + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); size_t tuple_field_index = 0; for (auto &pat : items.get_patterns ()) @@ -414,6 +565,216 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) } } +void +CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern) +{ + if (pattern.has_subpattern ()) + { + check_expr = CompilePatternCheckExpr::Compile (pattern.get_subpattern (), + match_scrutinee_expr, ctx); + } + else + { + check_expr = boolean_true_node; + } +} + +void +CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) +{ + check_expr = boolean_true_node; + + // lookup the type + TyTy::BaseType *lookup = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (), + &lookup); + rust_assert (ok); + + // pattern must either be ArrayType or SliceType, should be already confirmed + // by type checking + rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY + || lookup->get_kind () == TyTy::TypeKind::SLICE + || lookup->get_kind () == TyTy::REF); + + // function ptr that points to either array_index_expression or + // slice_index_expression depending on the scrutinee's type + tree (*scrutinee_index_expr_func) (tree, tree, location_t) = nullptr; + + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + scrutinee_index_expr_func = Backend::array_index_expression; + break; + case TyTy::TypeKind::SLICE: + rust_sorry_at ( + pattern.get_locus (), + "SlicePattern matching against non-ref slices are not yet supported"); + break; + case TyTy::TypeKind::REF: + { + rust_assert (RS_DST_FLAG_P (TREE_TYPE (match_scrutinee_expr))); + scrutinee_index_expr_func = Backend::slice_index_expression; + tree size_field + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_locus ()); + + // for slices, generate a dynamic size comparison expression tree + // because size checking is done at runtime. + switch (pattern.get_items ().get_item_type ()) + { + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &items = static_cast<HIR::SlicePatternItemsNoRest &> ( + pattern.get_items ()); + check_expr = Backend::comparison_expression ( + ComparisonOperator::EQUAL, size_field, + build_int_cst (size_type_node, items.get_patterns ().size ()), + pattern.get_locus ()); + } + break; + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &items = static_cast<HIR::SlicePatternItemsHasRest &> ( + pattern.get_items ()); + auto pattern_min_cap = items.get_lower_patterns ().size () + + items.get_upper_patterns ().size (); + check_expr = Backend::comparison_expression ( + ComparisonOperator::GREATER_OR_EQUAL, size_field, + build_int_cst (size_type_node, pattern_min_cap), + pattern.get_locus ()); + } + break; + } + } + break; + default: + rust_unreachable (); + } + + rust_assert (scrutinee_index_expr_func != nullptr); + + // Generate tree to compare every element within array/slice + size_t element_index = 0; + switch (pattern.get_items ().get_item_type ()) + { + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, element_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + } + break; + } + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_lower_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, element_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + } + + // handle codegen for upper patterns differently for both types + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + { + // for array type scrutinee, we can simply get the capacity as a + // const and calculate how many elements to skip + auto array_ty = static_cast<TyTy::ArrayType *> (lookup); + auto capacity_ty = array_ty->get_capacity (); + + rust_assert (capacity_ty->get_kind () == TyTy::TypeKind::CONST); + auto *capacity_const = capacity_ty->as_const_type (); + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value + = *static_cast<TyTy::ConstValueType *> (capacity_const); + auto cap_tree = capacity_value.get_value (); + + rust_assert (!error_operand_p (cap_tree)); + + size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi (); + element_index = cap_wi - items.get_upper_patterns ().size (); + for (auto &pattern_member : items.get_upper_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, + index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, + element_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + } + } + break; + case TyTy::TypeKind::REF: + { + // for slice type scrutinee, size is dyanamic, so number of + // elements to skip is calculated during runtime + tree slice_size + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_locus ()); + tree upper_patterns_size = Backend::size_constant_expression ( + items.get_upper_patterns ().size ()); + tree index_tree = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::SUBTRACT, slice_size, + upper_patterns_size, pattern.get_locus ()); + for (auto &pattern_member : items.get_upper_patterns ()) + { + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, + index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, + element_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + index_tree = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::ADD, index_tree, + Backend::size_constant_expression (1), + pattern.get_locus ()); + } + } + break; + default: + rust_unreachable (); + } + } + break; + } +} + // setup the bindings void @@ -449,23 +810,54 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { - // TODO - rust_unreachable (); + case HIR::TupleStructItems::HAS_REST: + { + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (items); + size_t num_patterns = items_has_rest.get_lower_patterns ().size () + + items_has_rest.get_upper_patterns ().size (); + + // enums cases shouldn't reach here + rust_assert (num_patterns <= variant->num_fields () + && (!adt->is_enum ())); + + size_t tuple_field_index = 0; + for (auto &pattern : items_has_rest.get_lower_patterns ()) + { + tree binding + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pattern->get_locus ()); + + CompilePatternBindings::Compile (*pattern, binding, ctx); + } + + tuple_field_index = variant->num_fields () + - items_has_rest.get_upper_patterns ().size (); + + for (auto &pattern : items_has_rest.get_upper_patterns ()) + { + tree binding + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pattern->get_locus ()); + + CompilePatternBindings::Compile (*pattern, binding, ctx); + } } break; - case HIR::TupleStructItems::MULTIPLE: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); - - rust_assert (items_no_range.get_patterns ().size () + case HIR::TupleStructItems::NO_REST: + { + HIR::TupleStructItemsNoRest &items_no_rest + = static_cast<HIR::TupleStructItemsNoRest &> (items); + rust_assert (items_no_rest.get_patterns ().size () == variant->num_fields ()); if (adt->is_enum ()) { size_t tuple_field_index = 0; - for (auto &pattern : items_no_range.get_patterns ()) + for (auto &pattern : items_no_rest.get_patterns ()) { tree payload_accessor_union = Backend::struct_field_expression (match_scrutinee_expr, 1, @@ -487,12 +879,10 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) else { size_t tuple_field_index = 0; - for (auto &pattern : items_no_range.get_patterns ()) + for (auto &pattern : items_no_rest.get_patterns ()) { - tree variant_accessor = match_scrutinee_expr; - tree binding - = Backend::struct_field_expression (variant_accessor, + = Backend::struct_field_expression (match_scrutinee_expr, tuple_field_index++, pattern->get_locus ()); @@ -504,6 +894,71 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) } } +tree +CompilePatternBindings::make_struct_access (TyTy::ADTType *adt, + TyTy::VariantDef *variant, + const Identifier &ident, + int variant_index) +{ + size_t offs = 0; + auto ok = variant->lookup_field (ident.as_string (), nullptr, &offs); + rust_assert (ok); + + if (adt->is_enum ()) + { + tree payload_accessor_union + = Backend::struct_field_expression (match_scrutinee_expr, 1, + ident.get_locus ()); + + tree variant_accessor + = Backend::struct_field_expression (payload_accessor_union, + variant_index, ident.get_locus ()); + + return Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); + } + else + { + tree variant_accessor = match_scrutinee_expr; + + return Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); + } +} + +void +CompilePatternBindings::handle_struct_pattern_ident ( + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) +{ + HIR::StructPatternFieldIdent &ident + = static_cast<HIR::StructPatternFieldIdent &> (pat); + + auto identifier = ident.get_identifier (); + tree binding = make_struct_access (adt, variant, identifier, variant_index); + + ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), binding); +} + +void +CompilePatternBindings::handle_struct_pattern_ident_pat ( + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) +{ + auto &pattern = static_cast<HIR::StructPatternFieldIdentPat &> (pat); + + tree binding = make_struct_access (adt, variant, pattern.get_identifier (), + variant_index); + CompilePatternBindings::Compile (pattern.get_pattern (), binding, ctx); +} + +void +CompilePatternBindings::handle_struct_pattern_tuple_pat ( + HIR::StructPatternField &pat) +{ + rust_unreachable (); +} + void CompilePatternBindings::visit (HIR::StructPattern &pattern) { @@ -531,62 +986,23 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern) rust_assert (ok); } - rust_assert (variant->get_variant_type () - == TyTy::VariantDef::VariantType::STRUCT); + rust_assert ( + variant->get_variant_type () == TyTy::VariantDef::VariantType::STRUCT + || variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE); auto &struct_pattern_elems = pattern.get_struct_pattern_elems (); for (auto &field : struct_pattern_elems.get_struct_pattern_fields ()) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { - // TODO - rust_unreachable (); - } + case HIR::StructPatternField::ItemType::TUPLE_PAT: + handle_struct_pattern_tuple_pat (*field); break; - - case HIR::StructPatternField::ItemType::IDENT_PAT: { - // TODO - rust_unreachable (); - } + case HIR::StructPatternField::ItemType::IDENT_PAT: + handle_struct_pattern_ident_pat (*field, adt, variant, variant_index); break; - - case HIR::StructPatternField::ItemType::IDENT: { - HIR::StructPatternFieldIdent &ident - = static_cast<HIR::StructPatternFieldIdent &> (*field.get ()); - - size_t offs = 0; - ok = variant->lookup_field (ident.get_identifier ().as_string (), - nullptr, &offs); - rust_assert (ok); - - tree binding = error_mark_node; - if (adt->is_enum ()) - { - tree payload_accessor_union - = Backend::struct_field_expression (match_scrutinee_expr, 1, - ident.get_locus ()); - - tree variant_accessor - = Backend::struct_field_expression (payload_accessor_union, - variant_index, - ident.get_locus ()); - - binding - = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); - } - else - { - tree variant_accessor = match_scrutinee_expr; - binding - = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); - } - - ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), - binding); - } + case HIR::StructPatternField::ItemType::IDENT: + handle_struct_pattern_ident (*field, adt, variant, variant_index); break; } } @@ -605,6 +1021,12 @@ CompilePatternBindings::visit (HIR::ReferencePattern &pattern) void CompilePatternBindings::visit (HIR::IdentifierPattern &pattern) { + if (pattern.has_subpattern ()) + { + CompilePatternBindings::Compile (pattern.get_subpattern (), + match_scrutinee_expr, ctx); + } + if (!pattern.get_is_ref ()) { ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (), @@ -631,10 +1053,11 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::RANGED: { + case HIR::TuplePatternItems::ItemType::HAS_REST: + { size_t tuple_idx = 0; auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); auto &items_lower = items.get_lower_patterns (); auto &items_upper = items.get_upper_patterns (); @@ -674,10 +1097,11 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) return; } - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::NO_REST: + { size_t tuple_idx = 0; - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); for (auto &sub : items.get_patterns ()) { @@ -695,12 +1119,156 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) return; } - default: { + default: + { rust_unreachable (); } } } +void +CompilePatternBindings::visit (HIR::SlicePattern &pattern) +{ + // lookup the type + TyTy::BaseType *lookup = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (), + &lookup); + rust_assert (ok); + + rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY + || lookup->get_kind () == TyTy::TypeKind::SLICE + || lookup->get_kind () == TyTy::REF); + + // function ptr that points to either array_index_expression or + // slice_index_expression depending on the scrutinee's type + tree (*scrutinee_index_expr_func) (tree, tree, location_t) = nullptr; + + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + scrutinee_index_expr_func = Backend::array_index_expression; + break; + case TyTy::TypeKind::SLICE: + rust_sorry_at (pattern.get_locus (), + "SlicePattern matching against non-ref slices are " + "not yet supported"); + break; + case TyTy::TypeKind::REF: + scrutinee_index_expr_func = Backend::slice_index_expression; + break; + default: + rust_unreachable (); + } + + rust_assert (scrutinee_index_expr_func != nullptr); + + size_t element_index = 0; + + switch (pattern.get_items ().get_item_type ()) + { + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, element_expr, + ctx); + } + } + break; + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_lower_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, element_expr, + ctx); + } + + // handle codegen for upper patterns differently for both types + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + { + auto array_ty = static_cast<TyTy::ArrayType *> (lookup); + auto capacity_ty = array_ty->get_capacity (); + + rust_assert (capacity_ty->get_kind () == TyTy::TypeKind::CONST); + auto *capacity_const = capacity_ty->as_const_type (); + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value + = *static_cast<TyTy::ConstValueType *> (capacity_const); + auto cap_tree = capacity_value.get_value (); + + rust_assert (!error_operand_p (cap_tree)); + + size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi (); + element_index = cap_wi - items.get_upper_patterns ().size (); + for (auto &pattern_member : items.get_upper_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, + index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, + element_expr, ctx); + } + } + break; + case TyTy::TypeKind::SLICE: + rust_sorry_at (pattern.get_locus (), + "SlicePattern matching against non-ref slices are " + "not yet supported"); + break; + case TyTy::TypeKind::REF: + { + tree slice_size + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_locus ()); + tree upper_patterns_size = Backend::size_constant_expression ( + items.get_upper_patterns ().size ()); + tree index_tree = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::SUBTRACT, slice_size, + upper_patterns_size, pattern.get_locus ()); + for (auto &pattern_member : items.get_upper_patterns ()) + { + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, + index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, + element_expr, ctx); + index_tree = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::ADD, index_tree, + Backend::size_constant_expression (1), + pattern.get_locus ()); + } + } + break; + default: + rust_unreachable (); + } + } + break; + } +} + // void @@ -710,6 +1278,11 @@ CompilePatternLet::visit (HIR::IdentifierPattern &pattern) rust_assert ( ctx->lookup_var_decl (pattern.get_mappings ().get_hirid (), &var)); + if (pattern.get_is_ref ()) + { + init_expr = address_expression (init_expr, EXPR_LOCATION (init_expr)); + } + auto fnctx = ctx->peek_fn (); if (ty->is_unit ()) { @@ -721,6 +1294,11 @@ CompilePatternLet::visit (HIR::IdentifierPattern &pattern) } else { + if (pattern.has_subpattern ()) + { + CompilePatternLet::Compile (&pattern.get_subpattern (), init_expr, ty, + rval_locus, ctx); + } auto s = Backend::init_statement (fnctx.fndecl, var, init_expr); ctx->add_statement (s); } @@ -744,21 +1322,65 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) { rust_assert (pattern.has_tuple_pattern_items ()); - tree tuple_type = TyTyResolveCompile::compile (ctx, ty); + bool has_by_ref = false; + auto check_refs + = [] (const std::vector<std::unique_ptr<HIR::Pattern>> &patterns) { + for (const auto &sub : patterns) + { + switch (sub->get_pattern_type ()) + { + case HIR::Pattern::PatternType::IDENTIFIER: + { + auto id = static_cast<HIR::IdentifierPattern *> (sub.get ()); + if (id->get_is_ref ()) + return true; + break; + } + case HIR::Pattern::PatternType::REFERENCE: + return true; + default: + break; + } + } + return false; + }; + switch (pattern.get_items ().get_item_type ()) + { + case HIR::TuplePatternItems::ItemType::NO_REST: + { + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); + has_by_ref = check_refs (items.get_patterns ()); + break; + } + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + auto &items + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); + has_by_ref = check_refs (items.get_lower_patterns ()) + || check_refs (items.get_upper_patterns ()); + break; + } + default: + break; + } + + tree rhs_tuple_type = TYPE_MAIN_VARIANT (TREE_TYPE (init_expr)); tree init_stmt; Bvariable *tmp_var = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, - tuple_type, init_expr, false, + rhs_tuple_type, init_expr, has_by_ref, pattern.get_locus (), &init_stmt); tree access_expr = Backend::var_expression (tmp_var, pattern.get_locus ()); ctx->add_statement (init_stmt); switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::RANGED: { + case HIR::TuplePatternItems::ItemType::HAS_REST: + { size_t tuple_idx = 0; auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); auto &items_lower = items.get_lower_patterns (); auto &items_upper = items.get_upper_patterns (); @@ -799,10 +1421,11 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) return; } - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::NO_REST: + { size_t tuple_idx = 0; - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); for (auto &sub : items.get_patterns ()) { @@ -821,7 +1444,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) return; } - default: { + default: + { rust_unreachable (); } } diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index c7a62fc..233799e 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -17,7 +17,9 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-base.h" +#include "rust-hir-pattern.h" #include "rust-hir-visitor.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -43,12 +45,10 @@ public: void visit (HIR::StructPattern &) override; void visit (HIR::TupleStructPattern &) override; void visit (HIR::TuplePattern &) override; + void visit (HIR::IdentifierPattern &) override; + void visit (HIR::SlicePattern &) override; // Always succeeds - void visit (HIR::IdentifierPattern &) override - { - check_expr = boolean_true_node; - } void visit (HIR::WildcardPattern &) override { check_expr = boolean_true_node; @@ -56,7 +56,6 @@ public: // Empty visit for unused Pattern HIR nodes. void visit (HIR::QualifiedPathInExpression &) override {} - void visit (HIR::SlicePattern &) override {} CompilePatternCheckExpr (Context *ctx, tree match_scrutinee_expr) : HIRCompileBase (ctx), match_scrutinee_expr (match_scrutinee_expr), @@ -78,11 +77,25 @@ public: pattern.accept_vis (compiler); } + tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant, + const Identifier &ident, int variant_index); + + void handle_struct_pattern_ident (HIR::StructPatternField &pat, + TyTy::ADTType *adt, + TyTy::VariantDef *variant, + int variant_index); + void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat, + TyTy::ADTType *adt, + TyTy::VariantDef *variant, + int variant_index); + void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat); + void visit (HIR::StructPattern &pattern) override; void visit (HIR::TupleStructPattern &pattern) override; void visit (HIR::ReferencePattern &pattern) override; void visit (HIR::IdentifierPattern &) override; void visit (HIR::TuplePattern &pattern) override; + void visit (HIR::SlicePattern &) override; // Empty visit for unused Pattern HIR nodes. void visit (HIR::AltPattern &) override {} @@ -90,7 +103,6 @@ public: void visit (HIR::PathInExpression &) override {} void visit (HIR::QualifiedPathInExpression &) override {} void visit (HIR::RangePattern &) override {} - void visit (HIR::SlicePattern &) override {} void visit (HIR::WildcardPattern &) override {} protected: diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 115dd04..5f30662 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -97,15 +97,20 @@ ResolvePathRef::attempt_constructor_expression_lookup ( // this can only be for discriminant variants the others are built up // using call-expr or struct-init - rust_assert (variant->get_variant_type () - == TyTy::VariantDef::VariantType::NUM); + if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM) + { + rust_error_at (expr_locus, "variant expected constructor call"); + return error_mark_node; + } // we need the actual gcc type tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt); // make the ctor for the union HIR::Expr &discrim_expr = variant->get_discriminant (); + ctx->push_const_context (); tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); + ctx->pop_const_context (); tree folded_discrim_expr = fold_expr (discrim_expr_node); tree qualifier = folded_discrim_expr; @@ -127,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 @@ -184,18 +187,32 @@ 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) - return attempt_constructor_expression_lookup (lookup, ctx, mappings, - expr_locus); + resolved_item + = attempt_constructor_expression_lookup (lookup, ctx, mappings, + expr_locus); + + if (!error_operand_p (resolved_item)) + return resolved_item; // let the query system figure it out - tree resolved_item = query_compile (ref, lookup, final_segment, mappings, - expr_locus, is_qualified_path); + 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; } @@ -207,36 +224,24 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, { TyTy::BaseType *lookup = nullptr; bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup); - rust_assert (ok); + if (!ok) + return error_mark_node; // need to look up the reference for this identifier // this can fail because it might be a Constructor for something // in that case the caller should attempt ResolvePathType::Compile - NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - auto resolved = nr_ctx.lookup (mappings.get_nodeid ()); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (!resolved) - return attempt_constructor_expression_lookup (lookup, ctx, mappings, - expr_locus); + auto resolved = nr_ctx.lookup (mappings.get_nodeid ()); - ref_node_id = *resolved; - } - else - { - if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (), - &ref_node_id)) - return attempt_constructor_expression_lookup (lookup, ctx, mappings, - expr_locus); - } + if (!resolved) + return attempt_constructor_expression_lookup (lookup, ctx, mappings, + expr_locus); return resolve_with_node_id (final_segment, mappings, expr_locus, - is_qualified_path, ref_node_id); + is_qualified_path, *resolved); } tree @@ -259,10 +264,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, HIR::ExternalItem *resolved_extern_item = hir_extern_item->first; if (!lookup->has_substitutions_defined ()) return CompileExternItem::compile (resolved_extern_item, ctx, nullptr, - true, expr_locus); + expr_locus); else return CompileExternItem::compile (resolved_extern_item, ctx, lookup, - true, expr_locus); + expr_locus); } else { @@ -284,10 +289,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, { if (!lookup->has_substitutions_defined ()) return CompileInherentImplItem::Compile (resolved_item->first, ctx, - nullptr, true, expr_locus); + nullptr, expr_locus); else return CompileInherentImplItem::Compile (resolved_item->first, ctx, - lookup, true, expr_locus); + lookup, expr_locus); } else if (auto trait_item = ctx->get_mappings ().lookup_hir_trait_item (ref)) @@ -334,11 +339,18 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, rust_assert (lookup->is<TyTy::FnType> ()); auto fn = lookup->as<TyTy::FnType> (); rust_assert (fn->get_num_type_params () > 0); - auto &self = fn->get_substs ().at (0); - auto receiver = self.get_param_ty (); + TyTy::SubstitutionParamMapping &self = fn->get_substs ().at (0); + TyTy::BaseGeneric *receiver = self.get_param_ty (); + TyTy::BaseType *r = receiver; + if (!receiver->can_resolve ()) + { + bool ok + = ctx->get_tyctx ()->lookup_type (receiver->get_ref (), &r); + rust_assert (ok); + } + auto candidates - = Resolver::PathProbeImplTrait::Probe (receiver, final_segment, - trait_ref); + = Resolver::PathProbeImplTrait::Probe (r, final_segment, trait_ref); if (candidates.size () == 0) { // this means we are defaulting back to the trait_item if @@ -370,11 +382,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, if (!lookup->has_substitutions_defined ()) return CompileInherentImplItem::Compile (impl_item, ctx, - nullptr, true, - expr_locus); + nullptr, expr_locus); else return CompileInherentImplItem::Compile (impl_item, ctx, lookup, - true, expr_locus); + expr_locus); } } } diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc index a4b5a98..b520baf 100644 --- a/gcc/rust/backend/rust-compile-stmt.cc +++ b/gcc/rust/backend/rust-compile-stmt.cc @@ -58,6 +58,9 @@ CompileStmt::visit (HIR::LetStmt &stmt) return; } + rust_debug_loc (stmt.get_locus (), " -> LetStmt %s", + ty->as_string ().c_str ()); + // setup var decl nodes fncontext fnctx = ctx->peek_fn (); tree fndecl = fnctx.fndecl; diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 83e5756..5b00afa 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -17,11 +17,11 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-type.h" -#include "rust-compile-expr.h" #include "rust-constexpr.h" -#include "rust-gcc.h" +#include "rust-compile-base.h" #include "tree.h" +#include "fold-const.h" #include "stor-layout.h" namespace Rust { @@ -121,6 +121,13 @@ TyTyResolveCompile::visit (const TyTy::InferType &type) if (orig == lookup) { + TyTy::BaseType *def = nullptr; + if (type.default_type (&def)) + { + translated = TyTyResolveCompile::compile (ctx, def); + return; + } + translated = error_mark_node; return; } @@ -129,7 +136,31 @@ TyTyResolveCompile::visit (const TyTy::InferType &type) } void -TyTyResolveCompile::visit (const TyTy::ParamType &) +TyTyResolveCompile::visit (const TyTy::ParamType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstParamType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstValueType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstInferType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstErrorType &type) { translated = error_mark_node; } @@ -173,8 +204,8 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type) // this should be based on the closure move-ability tree decl_type = TyTyResolveCompile::compile (ctx, lookup); tree capture_type = build_reference_type (decl_type); - fields.push_back (Backend::typed_identifier (mappings_name, capture_type, - type.get_ident ().locus)); + fields.emplace_back (mappings_name, capture_type, + type.get_ident ().locus); } tree type_record = Backend::struct_type (fields); @@ -189,7 +220,7 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type) void TyTyResolveCompile::visit (const TyTy::FnType &type) { - Backend::typed_identifier receiver; + Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION); std::vector<Backend::typed_identifier> parameters; std::vector<Backend::typed_identifier> results; @@ -204,8 +235,7 @@ TyTyResolveCompile::visit (const TyTy::FnType &type) auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode); location_t return_type_locus = ctx->get_mappings ().lookup_location (hir_type->get_ref ()); - results.push_back ( - Backend::typed_identifier ("_", ret, return_type_locus)); + results.emplace_back ("_", ret, return_type_locus); } for (auto ¶m_pair : type.get_params ()) @@ -214,11 +244,10 @@ TyTyResolveCompile::visit (const TyTy::FnType &type) auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode); - auto compiled_param = Backend::typed_identifier ( - param_pair.get_pattern ().as_string (), compiled_param_type, - ctx->get_mappings ().lookup_location (param_tyty->get_ref ())); - - parameters.push_back (compiled_param); + parameters.emplace_back (param_pair.get_pattern ().as_string (), + compiled_param_type, + ctx->get_mappings ().lookup_location ( + param_tyty->get_ref ())); } if (!type.is_variadic ()) @@ -264,10 +293,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field->get_field_type ()); - Backend::typed_identifier f (field->get_name (), compiled_field_ty, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (f)); + fields.emplace_back (field->get_name (), compiled_field_ty, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); } type_record = type.is_union () ? Backend::union_type (fields, false) @@ -344,10 +372,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) == TyTy::VariantDef::VariantType::TUPLE) field_name = "__" + field->get_name (); - Backend::typed_identifier f ( - field_name, compiled_field_ty, - ctx->get_mappings ().lookup_location (type.get_ty_ref ())); - fields.push_back (std::move (f)); + fields.emplace_back (field_name, compiled_field_ty, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); } tree variant_record = Backend::struct_type (fields); @@ -369,10 +396,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) TyTy::VariantDef *variant = type.get_variants ().at (i++); std::string implicit_variant_name = variant->get_identifier (); - Backend::typed_identifier f (implicit_variant_name, variant_record, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - enum_fields.push_back (std::move (f)); + enum_fields.emplace_back (implicit_variant_name, variant_record, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); } // @@ -447,14 +473,13 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type) // this, rather than simply emitting the integer, is that this // approach makes it simpler to use a C-only debugger, or // GDB's C mode, when debugging Rust. - Backend::typed_identifier f ("__" + std::to_string (i), compiled_field_ty, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (f)); + fields.emplace_back ("__" + std::to_string (i), compiled_field_ty, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); } tree struct_type_record = Backend::struct_type (fields); - translated = Backend::named_type (type.as_string (), struct_type_record, + translated = Backend::named_type (type.get_name (), struct_type_record, type.get_ident ().locus); } @@ -463,26 +488,29 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) { tree element_type = TyTyResolveCompile::compile (ctx, type.get_element_type ()); + auto const_capacity = type.get_capacity (); - ctx->push_const_context (); + // Check if capacity is a const type + if (const_capacity->get_kind () != TyTy::TypeKind::CONST) + { + rust_error_at (type.get_locus (), "array capacity is not a const type"); + translated = error_mark_node; + return; + } - HIR::Expr &hir_capacity_expr = type.get_capacity_expr (); - TyTy::BaseType *capacity_expr_ty = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type ( - hir_capacity_expr.get_mappings ().get_hirid (), &capacity_expr_ty); - rust_assert (ok); - tree capacity_expr = HIRCompileBase::compile_constant_expr ( - ctx, hir_capacity_expr.get_mappings ().get_hirid (), capacity_expr_ty, - capacity_expr_ty, Resolver::CanonicalPath::create_empty (), - hir_capacity_expr, type.get_locus (), hir_capacity_expr.get_locus ()); + auto *capacity_const = const_capacity->as_const_type (); - ctx->pop_const_context (); + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const); + auto folded_capacity_expr = capacity_value.get_value (); - tree folded_capacity_expr = fold_expr (capacity_expr); + // build_index_type takes the maximum index, which is one less than + // the length. + tree index_type_tree = build_index_type ( + fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node)); - translated = Backend::array_type (element_type, folded_capacity_expr); - if (translated != error_mark_node) - translated = ctx->insert_compiled_type (translated); + translated = build_array_type (element_type, index_type_tree, false); } void @@ -755,7 +783,9 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) void TyTyResolveCompile::visit (const TyTy::OpaqueType &type) { - translated = error_mark_node; + rust_assert (type.can_resolve ()); + auto underlying = type.resolve (); + translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode); } tree @@ -768,17 +798,15 @@ TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type) tree uint = Backend::integer_type (true, Backend::get_pointer_size ()); tree uintptr_ty = build_pointer_type (uint); - Backend::typed_identifier f ("pointer", uintptr_ty, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (f)); + fields.emplace_back ("pointer", uintptr_ty, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); tree vtable_size = build_int_cst (size_type_node, items.size ()); tree vtable_type = Backend::array_type (uintptr_ty, vtable_size); - Backend::typed_identifier vtf ("vtable", vtable_type, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (vtf)); + fields.emplace_back ("vtable", vtable_type, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); tree record = Backend::struct_type (fields); RS_DST_FLAG (record) = 1; diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h index 7ebc4a6..d6c3259 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -50,6 +50,10 @@ public: void visit (const TyTy::ReferenceType &) override; void visit (const TyTy::PointerType &) override; void visit (const TyTy::ParamType &) override; + void visit (const TyTy::ConstParamType &) override; + void visit (const TyTy::ConstValueType &) override; + void visit (const TyTy::ConstInferType &) override; + void visit (const TyTy::ConstErrorType &) override; void visit (const TyTy::StrType &) override; void visit (const TyTy::NeverType &) override; void visit (const TyTy::PlaceholderType &) override; diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 4c46a7b..1f306ad 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -64,30 +64,79 @@ public: ctx->insert_var_decl (stmt_id, var); vars.push_back (var); + + if (pattern.has_subpattern ()) + { + auto subpattern_vars + = CompileVarDecl::compile (fndecl, translated_type, + &pattern.get_subpattern (), ctx); + vars.insert (vars.end (), subpattern_vars.begin (), + subpattern_vars.end ()); + } } void visit (HIR::TuplePattern &pattern) override { + rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: { - rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( + case HIR::TuplePatternItems::ItemType::NO_REST: + { + auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> ( + pattern.get_items ()); + + tree field = TYPE_FIELDS (translated_type); + for (auto &sub : items_no_rest.get_patterns ()) + { + gcc_assert (field != NULL_TREE); + tree sub_ty = TREE_TYPE (field); + CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); + field = DECL_CHAIN (field); + } + } + break; + + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> ( pattern.get_items ()); - size_t offs = 0; - for (auto &sub : items.get_patterns ()) + // count total fields in translated_type + size_t total_fields = 0; + for (tree t = TYPE_FIELDS (translated_type); t; t = DECL_CHAIN (t)) + { + total_fields++; + } + + // process lower patterns + tree field = TYPE_FIELDS (translated_type); + for (auto &sub : items_has_rest.get_lower_patterns ()) + { + gcc_assert (field != NULL_TREE); + tree sub_ty = TREE_TYPE (field); + CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); + field = DECL_CHAIN (field); + } + + // process upper patterns + if (!items_has_rest.get_upper_patterns ().empty ()) { - tree sub_ty = error_mark_node; - tree field = TYPE_FIELDS (translated_type); - for (size_t i = 0; i < offs; i++) + size_t upper_start + = total_fields - items_has_rest.get_upper_patterns ().size (); + field = TYPE_FIELDS (translated_type); + for (size_t i = 0; i < upper_start; i++) { field = DECL_CHAIN (field); gcc_assert (field != NULL_TREE); } - sub_ty = TREE_TYPE (field); - CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); - offs++; + + for (auto &sub : items_has_rest.get_upper_patterns ()) + { + gcc_assert (field != NULL_TREE); + tree sub_ty = TREE_TYPE (field); + CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); + field = DECL_CHAIN (field); + } } } break; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 7b00066..40f16e4 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -183,8 +183,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval, } tree -HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, - const TyTy::BaseType *actual, +HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, TyTy::BaseType *actual, const TyTy::DynamicObjectType *ty, location_t locus) { @@ -201,9 +200,7 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, // __trait_object_ptr // [list of function ptrs] - std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>> - probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (actual); - + auto probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (actual); tree address_of_compiled_ref = null_pointer_node; if (!actual->is_unit ()) address_of_compiled_ref = address_expression (compiled_ref, locus); @@ -241,12 +238,13 @@ HIRCompileBase::compute_address_for_trait_item ( &receiver_bounds, const TyTy::BaseType *receiver, const TyTy::BaseType *root, location_t locus) { - TyTy::TypeBoundPredicateItem predicate_item + tl::optional<TyTy::TypeBoundPredicateItem> predicate_item = predicate->lookup_associated_item (ref->get_identifier ()); - rust_assert (!predicate_item.is_error ()); + rust_assert (predicate_item.has_value ()); // This is the expected end type - TyTy::BaseType *trait_item_type = predicate_item.get_tyty_for_receiver (root); + TyTy::BaseType *trait_item_type + = predicate_item->get_tyty_for_receiver (root); rust_assert (trait_item_type->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *trait_item_fntype = static_cast<TyTy::FnType *> (trait_item_type); @@ -338,7 +336,7 @@ HIRCompileBase::compute_address_for_trait_item ( } return CompileInherentImplItem::Compile (associated_function, ctx, - lookup_fntype, true, locus); + lookup_fntype, locus); } // we can only compile trait-items with a body diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index dc2d6b1..e32ba3a 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -68,32 +68,24 @@ literal_type_p (tree t) return false; } -static bool -verify_constant (tree, bool, bool *, bool *); - -static HOST_WIDE_INT -find_array_ctor_elt (tree ary, tree dindex, bool insert = false); -static int -array_index_cmp (tree key, tree index); -static bool -potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, - tsubst_flags_t flags, tree *jump_target); -bool -potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, - tsubst_flags_t flags); -tree -unshare_constructor (tree t MEM_STAT_DECL); -void -maybe_save_constexpr_fundef (tree fun); - -static bool -returns (tree *jump_target); -static bool -breaks (tree *jump_target); -static bool -continues (tree *jump_target); -static bool -switches (tree *jump_target); +static bool verify_constant (tree, bool, bool *, bool *); + +static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex, + bool insert = false); +static int array_index_cmp (tree key, tree index); +static bool potential_constant_expression_1 (tree t, bool want_rval, + bool strict, bool now, + tsubst_flags_t flags, + tree *jump_target); +bool potential_constant_expression_1 (tree t, bool want_rval, bool strict, + bool now, tsubst_flags_t flags); +tree unshare_constructor (tree t MEM_STAT_DECL); +void maybe_save_constexpr_fundef (tree fun); + +static bool returns (tree *jump_target); +static bool breaks (tree *jump_target); +static bool continues (tree *jump_target); +static bool switches (tree *jump_target); struct constexpr_global_ctx { @@ -109,12 +101,54 @@ struct constexpr_global_ctx auto_vec<tree, 16> heap_vars; /* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR. */ vec<tree> *cleanups; + /* If non-null, only allow modification of existing values of the variables + in this set. Set by modifiable_tracker, below. */ + hash_set<tree> *modifiable; /* Number of heap VAR_DECL deallocations. */ unsigned heap_dealloc_count; /* Constructor. */ constexpr_global_ctx () : constexpr_ops_count (0), cleanups (NULL), heap_dealloc_count (0) {} + + tree get_value (tree t) + { + if (tree *p = values.get (t)) + if (*p != void_node) + return *p; + return NULL_TREE; + } + tree *get_value_ptr (tree t, bool initializing) + { + if (modifiable && !modifiable->contains (t)) + return nullptr; + if (tree *p = values.get (t)) + { + if (*p != void_node) + return p; + else if (initializing) + { + *p = NULL_TREE; + return p; + } + } + return nullptr; + } + void put_value (tree t, tree v) + { + bool already_in_map = values.put (t, v); + if (!already_in_map && modifiable) + modifiable->add (t); + } + void destroy_value (tree t) + { + if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL + || TREE_CODE (t) == RESULT_DECL) + values.put (t, void_node); + else + values.remove (t); + } + void clear_value (tree t) { values.remove (t); } }; /* In constexpr.cc */ @@ -463,60 +497,62 @@ save_fundef_copy (tree fun, tree copy) *slot = copy; } -static tree -constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p, - bool unshare_p); -tree -decl_constant_value (tree decl, bool unshare_p); +static tree constant_value_1 (tree decl, bool strict_p, + bool return_aggregate_cst_ok_p, bool unshare_p); +static tree decl_really_constant_value (tree decl, bool unshare_p /*= true*/); +tree decl_constant_value (tree decl, bool unshare_p); -static void -non_const_var_error (location_t loc, tree r); +static void non_const_var_error (location_t loc, tree r); -static tree -eval_constant_expression (const constexpr_ctx *ctx, tree, bool, bool *, bool *, - tree * = NULL); +static tree eval_constant_expression (const constexpr_ctx *ctx, tree, bool, + bool *, bool *, tree *jump_target); -static tree -constexpr_fn_retval (const constexpr_ctx *ctx, tree r); +static tree constexpr_fn_retval (const constexpr_ctx *ctx, tree r); -static tree -eval_store_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_store_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *, tree *jump_target); -static tree -eval_call_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_call_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *, tree *); -static tree -eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *, tree *jump_target); -static tree -get_function_named_in_call (tree t); +static tree get_function_named_in_call (tree t); -static tree -eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); -static tree -extract_string_elt (tree string, unsigned chars_per_elt, unsigned index); +static tree eval_statement_list (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); +static tree extract_string_elt (tree string, unsigned chars_per_elt, + unsigned index); -static tree -eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p, - tree *jump_target); - -static tree -eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p); +static tree eval_conditional_expression (const constexpr_ctx *ctx, tree t, + bool lval, bool *non_constant_p, + bool *overflow_p, tree *jump_target); -static tree -eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); +static tree eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); -static tree -eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); - -static tree -eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, - bool *non_constant_p, bool *overflow_p); +static tree eval_loop_expr (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); + +static tree eval_switch_expr (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); + +static tree eval_unary_expression (const constexpr_ctx *ctx, tree t, + bool /*lval*/, bool *non_constant_p, + bool *overflow_p, tree *jump_target); +static bool eval_check_shift_p (location_t loc, const constexpr_ctx *ctx, + enum tree_code code, tree type, tree lhs, + tree rhs); +static tree fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, + tree lhs, tree rhs, + bool *non_constant_p, + bool *overflow_p, tree *jump_target); +static tree maybe_fold_addr_pointer_plus (tree t); /* Variables and functions to manage constexpr call expansion context. These do not need to be marked for PCH or GC. */ @@ -578,8 +614,9 @@ fold_expr (tree expr) bool non_constant_p = false; bool overflow_p = false; + tree jump_target = NULL_TREE; tree folded = eval_constant_expression (&ctx, expr, false, &non_constant_p, - &overflow_p); + &overflow_p, &jump_target); rust_assert (folded != NULL_TREE); // more logic here to possibly port @@ -605,13 +642,13 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2) otherwise return NULL_TREE. */ static tree -union_active_member (const constexpr_ctx *ctx, tree t) +union_active_member (const constexpr_ctx *ctx, tree t, tree *jump_target) { constexpr_ctx new_ctx = *ctx; new_ctx.quiet = true; bool non_constant_p = false, overflow_p = false; tree ctor = eval_constant_expression (&new_ctx, t, false, &non_constant_p, - &overflow_p); + &overflow_p, jump_target); if (TREE_CODE (ctor) == CONSTRUCTOR && CONSTRUCTOR_NELTS (ctor) == 1 && CONSTRUCTOR_ELT (ctor, 0)->index && TREE_CODE (CONSTRUCTOR_ELT (ctor, 0)->index) == FIELD_DECL) @@ -623,7 +660,8 @@ union_active_member (const constexpr_ctx *ctx, tree t) static tree fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, - tree op, unsigned HOST_WIDE_INT off, bool *empty_base) + tree op, unsigned HOST_WIDE_INT off, bool *empty_base, + tree *jump_target) { tree optype = TREE_TYPE (op); unsigned HOST_WIDE_INT const_nunits; @@ -670,7 +708,8 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, tree index = size_int (idx + tree_to_uhwi (min_val)); op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index, NULL_TREE, NULL_TREE); - return fold_indirect_ref_1 (ctx, loc, type, op, rem, empty_base); + return fold_indirect_ref_1 (ctx, loc, type, op, rem, empty_base, + jump_target); } } /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */ @@ -679,7 +718,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, { if (TREE_CODE (optype) == UNION_TYPE) /* For unions prefer the currently active member. */ - if (tree field = union_active_member (ctx, op)) + if (tree field = union_active_member (ctx, op, jump_target)) { unsigned HOST_WIDE_INT el_sz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))); @@ -688,7 +727,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field, NULL_TREE); if (tree ret = fold_indirect_ref_1 (ctx, loc, type, cop, off, - empty_base)) + empty_base, jump_target)) return ret; } } @@ -707,8 +746,9 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, { tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field, NULL_TREE); - if (tree ret = fold_indirect_ref_1 (ctx, loc, type, cop, - off - upos, empty_base)) + if (tree ret + = fold_indirect_ref_1 (ctx, loc, type, cop, off - upos, + empty_base, jump_target)) return ret; } } @@ -737,7 +777,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, static tree rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, - tree op0, bool *empty_base) + tree op0, bool *empty_base, tree *jump_target) { tree sub = op0; tree subtype; @@ -796,7 +836,8 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, tree off = integer_zero_node; canonicalize_obj_off (op, off); gcc_assert (integer_zerop (off)); - return fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base); + return fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base, + jump_target); } } else if (TREE_CODE (sub) == POINTER_PLUS_EXPR @@ -811,7 +852,7 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, tree obj = TREE_OPERAND (op00, 0); canonicalize_obj_off (obj, off); return fold_indirect_ref_1 (ctx, loc, type, obj, tree_to_uhwi (off), - empty_base); + empty_base, jump_target); } } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ @@ -820,8 +861,8 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, { tree type_domain; tree min_val = size_zero_node; - tree newsub - = rs_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, NULL); + tree newsub = rs_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, + NULL, jump_target); if (newsub) sub = newsub; else @@ -840,7 +881,7 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, static tree rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree orig_op0 = TREE_OPERAND (t, 0); bool empty_base = false; @@ -858,13 +899,13 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, /* First try to simplify it directly. */ tree r = rs_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), - orig_op0, &empty_base); + orig_op0, &empty_base, jump_target); if (!r) { /* If that didn't work, evaluate the operand first. */ - tree op0 - = eval_constant_expression (ctx, orig_op0, - /*lval*/ false, non_constant_p, overflow_p); + tree op0 = eval_constant_expression (ctx, orig_op0, + /*lval*/ false, non_constant_p, + overflow_p, jump_target); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -878,7 +919,7 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, } r = rs_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), op0, - &empty_base); + &empty_base, jump_target); if (r == NULL_TREE) { /* We couldn't fold to a constant value. Make sure it's not @@ -907,7 +948,8 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, } } - r = eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p); + r = eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; @@ -933,17 +975,17 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, static tree eval_logical_expression (const constexpr_ctx *ctx, tree t, tree bailout_value, tree continue_value, bool lval, bool *non_constant_p, - bool *overflow_p) + bool *overflow_p, tree *jump_target) { tree r; tree lhs = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); VERIFY_CONSTANT (lhs); if (tree_int_cst_equal (lhs, bailout_value)) return lhs; gcc_assert (tree_int_cst_equal (lhs, continue_value)); r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), lval, non_constant_p, - overflow_p); + overflow_p, jump_target); VERIFY_CONSTANT (r); return r; } @@ -1235,7 +1277,8 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1) /* We fell off the end of the CONSTRUCTOR, so insert a new entry at the end. */ - insert : { + insert: + { constructor_elt ce = {index, NULL_TREE}; vec_safe_insert (CONSTRUCTOR_ELTS (ctor), idx, ce); @@ -1258,19 +1301,20 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1) static tree eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { - tree arg1 - = eval_constant_expression (ctx, TREE_OPERAND (t, 0), - /*lval*/ false, non_constant_p, overflow_p); + tree arg1 = eval_constant_expression (ctx, TREE_OPERAND (t, 0), + /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (arg1); - tree arg2 - = eval_constant_expression (ctx, TREE_OPERAND (t, 1), - /*lval*/ false, non_constant_p, overflow_p); + tree arg2 = eval_constant_expression (ctx, TREE_OPERAND (t, 1), + /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (arg2); - tree arg3 - = eval_constant_expression (ctx, TREE_OPERAND (t, 2), - /*lval*/ false, non_constant_p, overflow_p); + tree arg3 = eval_constant_expression (ctx, TREE_OPERAND (t, 2), + /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (arg3); location_t loc = EXPR_LOCATION (t); tree type = TREE_TYPE (t); @@ -1295,7 +1339,7 @@ eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t, static tree eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t); bool changed = false; @@ -1346,8 +1390,9 @@ eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval, the active union member now so that we can later detect and diagnose if its initializer attempts to activate another member. */ get_or_insert_ctor_field (ctx->ctor, index); - tree elt = eval_constant_expression (&new_ctx, value, lval, - non_constant_p, overflow_p); + tree elt + = eval_constant_expression (&new_ctx, value, lval, non_constant_p, + overflow_p, jump_target); /* Don't VERIFY_CONSTANT here. */ if (ctx->quiet && *non_constant_p) break; @@ -1416,7 +1461,8 @@ eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval, static tree cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { int i; tree args[3]; @@ -1424,8 +1470,9 @@ cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, bool lval, for (i = 0; i < 3; i++) { - args[i] = eval_constant_expression (ctx, TREE_OPERAND (t, i), lval, - non_constant_p, overflow_p); + args[i] + = eval_constant_expression (ctx, TREE_OPERAND (t, i), lval, + non_constant_p, overflow_p, jump_target); VERIFY_CONSTANT (args[i]); } @@ -1568,10 +1615,10 @@ free_constructor (tree t) } } -static tree -eval_and_check_array_index (const constexpr_ctx *ctx, tree t, - bool allow_one_past, bool *non_constant_p, - bool *overflow_p); +static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t, + bool allow_one_past, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); // forked from gcc/cp/constexpr.cc cxx_eval_array_reference @@ -1580,11 +1627,11 @@ eval_and_check_array_index (const constexpr_ctx *ctx, tree t, static tree eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree oldary = TREE_OPERAND (t, 0); - tree ary - = eval_constant_expression (ctx, oldary, lval, non_constant_p, overflow_p); + tree ary = eval_constant_expression (ctx, oldary, lval, non_constant_p, + overflow_p, jump_target); if (*non_constant_p) return t; if (!lval && TREE_CODE (ary) == VIEW_CONVERT_EXPR @@ -1593,8 +1640,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval, ary = TREE_OPERAND (ary, 0); tree oldidx = TREE_OPERAND (t, 1); - tree index - = eval_and_check_array_index (ctx, t, lval, non_constant_p, overflow_p); + tree index = eval_and_check_array_index (ctx, t, lval, non_constant_p, + overflow_p, jump_target); if (*non_constant_p) return t; @@ -1696,7 +1743,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval, new_ctx.ctor = build_constructor (elem_type, NULL); ctx = &new_ctx; } - t = eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p); + t = eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p, + jump_target); if (!SCALAR_TYPE_P (elem_type) && t != ctx->ctor) free_constructor (ctx->ctor); return t; @@ -1709,7 +1757,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval, static tree eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { unsigned HOST_WIDE_INT i; tree field; @@ -1717,7 +1766,7 @@ eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval, tree part = TREE_OPERAND (t, 1); tree orig_whole = TREE_OPERAND (t, 0); tree whole = eval_constant_expression (ctx, orig_whole, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); if (INDIRECT_REF_P (whole) && integer_zerop (TREE_OPERAND (whole, 0))) { if (!ctx->quiet) @@ -1806,8 +1855,8 @@ eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval, // back to handle this to assign suitable value to value before sending it in // eval_constant_expression below // value = build_value_init (TREE_TYPE (t), tf_warning_or_error); - return eval_constant_expression (ctx, value, lval, non_constant_p, - overflow_p); + return eval_constant_expression (ctx, value, lval, non_constant_p, overflow_p, + jump_target); } /* Subroutine of cxx_eval_statement_list. Determine whether the statement @@ -1866,7 +1915,7 @@ label_matches (const constexpr_ctx *ctx, tree *jump_target, tree stmt) static tree eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, bool *non_constant_p, bool *overflow_p, - tree *jump_target /* = NULL */) + tree *jump_target) { if (jump_target && *jump_target) { @@ -1901,6 +1950,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, location_t loc = EXPR_LOCATION (t); + if (t == NULL_TREE) + return NULL_TREE; + if (CONSTANT_CLASS_P (t)) { if (TREE_OVERFLOW (t)) @@ -1934,33 +1986,44 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, { r = DECL_VALUE_EXPR (t); return eval_constant_expression (ctx, r, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } - /* fall through */ - case CONST_DECL: { - /* We used to not check lval for CONST_DECL, but darwin.cc uses - CONST_DECL for aggregate constants. */ - if (lval) - return t; - else if (t == ctx->object) - return ctx->ctor; - if (VAR_P (t)) - if (tree *p = ctx->global->values.get (t)) - if (*p != NULL_TREE) - { - r = *p; - break; - } + /* fall through */ + case CONST_DECL: + /* We used to not check lval for CONST_DECL, but darwin.cc uses + CONST_DECL for aggregate constants. */ + if (lval) + return t; + else if (t == ctx->object) + return ctx->ctor; + if (VAR_P (t)) + { + if (tree v = ctx->global->get_value (t)) + { + r = v; + break; + } + } + if (COMPLETE_TYPE_P (TREE_TYPE (t)) + && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/ false)) + { + /* If the class is empty, we aren't actually loading anything. */ + r = build_constructor (TREE_TYPE (t), NULL); + TREE_CONSTANT (r) = true; + } + else if (ctx->strict) + r = decl_really_constant_value (t, /*unshare_p=*/false); + else r = decl_constant_value (t, /*unshare_p=*/false); - if (TREE_CODE (r) == TARGET_EXPR - && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR) - r = TARGET_EXPR_INITIAL (r); - if (DECL_P (r)) - { + if (TREE_CODE (r) == TARGET_EXPR + && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR) + r = TARGET_EXPR_INITIAL (r); + if (DECL_P (r) && !(VAR_P (t) && TYPE_REF_P (TREE_TYPE (t)))) + { + if (!ctx->quiet) non_const_var_error (loc, r); - return r; - } - } + *non_constant_p = true; + } break; case PARM_DECL: @@ -2026,7 +2089,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case LTGT_EXPR: case RANGE_EXPR: case COMPLEX_EXPR: - r = eval_binary_expression (ctx, t, lval, non_constant_p, overflow_p); + r = eval_binary_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; /* fold can introduce non-IF versions of these; still treat them as @@ -2035,17 +2099,18 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case TRUTH_ANDIF_EXPR: r = eval_logical_expression (ctx, t, boolean_false_node, boolean_true_node, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); break; case TRUTH_OR_EXPR: case TRUTH_ORIF_EXPR: r = eval_logical_expression (ctx, t, boolean_true_node, boolean_false_node, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); break; - case TARGET_EXPR: { + case TARGET_EXPR: + { tree type = TREE_TYPE (t); if (!literal_type_p (type)) @@ -2090,7 +2155,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, /* Pass false for 'lval' because this indicates initialization of a temporary. */ r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); if (*non_constant_p) break; /* Adjust the type of the result to the type of the temporary. */ @@ -2107,13 +2172,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, break; case CALL_EXPR: - r = eval_call_expression (ctx, t, lval, non_constant_p, overflow_p); + r = eval_call_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case RETURN_EXPR: if (TREE_OPERAND (t, 0) != NULL_TREE) r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); /* FALLTHRU */ case BREAK_STMT: case CONTINUE_STMT: @@ -2129,7 +2195,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, } break; - case DECL_EXPR: { + case DECL_EXPR: + { r = DECL_EXPR_DECL (t); if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r))) @@ -2145,7 +2212,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, if (tree init = DECL_INITIAL (r)) { init = eval_constant_expression (ctx, init, false, non_constant_p, - overflow_p); + overflow_p, jump_target); /* Don't share a CONSTRUCTOR that might be changed. */ init = unshare_constructor (init); /* Remember that a constant object's constructor has already @@ -2166,12 +2233,13 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, constant without its operand being, and vice versa. */ case MEM_REF: case INDIRECT_REF: - r = rs_eval_indirect_ref (ctx, t, lval, non_constant_p, overflow_p); + r = rs_eval_indirect_ref (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case VEC_PERM_EXPR: - r = cxx_eval_trinary_expression (ctx, t, lval, non_constant_p, - overflow_p); + r = cxx_eval_trinary_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case PAREN_EXPR: @@ -2179,11 +2247,12 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, /* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in constant expressions since it's unaffected by -fassociative-math. */ r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); break; case MODIFY_EXPR: - r = eval_store_expression (ctx, t, false, non_constant_p, overflow_p); + r = eval_store_expression (ctx, t, false, non_constant_p, overflow_p, + jump_target); break; case STATEMENT_LIST: @@ -2199,12 +2268,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case OBJ_TYPE_REF: /* Virtual function lookup. We don't need to do anything fancy. */ return eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); - case EXIT_EXPR: { + case EXIT_EXPR: + { tree cond = TREE_OPERAND (t, 0); - cond = eval_constant_expression (ctx, cond, /*lval*/ false, - non_constant_p, overflow_p); + cond + = eval_constant_expression (ctx, cond, /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (cond); if (integer_nonzerop (cond)) *jump_target = t; @@ -2234,7 +2305,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, else { r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) break; ctx->global->values.put (t, r); @@ -2243,11 +2315,12 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, } break; - case ADDR_EXPR: { + case ADDR_EXPR: + { tree oldop = TREE_OPERAND (t, 0); tree op = eval_constant_expression (ctx, oldop, /*lval*/ true, non_constant_p, - overflow_p); + overflow_p, jump_target); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -2261,7 +2334,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, break; } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* check_return_expr sometimes wraps a TARGET_EXPR in a COMPOUND_EXPR; don't get confused. Also handle EMPTY_CLASS_EXPR introduced by build_call_a. */ @@ -2291,7 +2365,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, if (lval) { r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (r == error_mark_node) ; else if (r == TREE_OPERAND (t, 0)) @@ -2310,7 +2385,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case BIT_NOT_EXPR: case TRUTH_NOT_EXPR: case FIXED_CONVERT_EXPR: - r = eval_unary_expression (ctx, t, lval, non_constant_p, overflow_p); + r = eval_unary_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case LOOP_EXPR: @@ -2325,7 +2401,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, break; case ARRAY_REF: - r = eval_array_reference (ctx, t, lval, non_constant_p, overflow_p); + r = eval_array_reference (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case COMPONENT_REF: @@ -2339,11 +2416,13 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, *non_constant_p = true; return t; } - r = eval_component_reference (ctx, t, lval, non_constant_p, overflow_p); + r = eval_component_reference (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case BIT_FIELD_REF: - r = eval_bit_field_ref (ctx, t, lval, non_constant_p, overflow_p); + r = eval_bit_field_ref (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case COND_EXPR: @@ -2388,7 +2467,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case VEC_COND_EXPR: r = eval_vector_conditional_expression (ctx, t, non_constant_p, - overflow_p); + overflow_p, jump_target); break; case TRY_CATCH_EXPR: @@ -2401,7 +2480,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, non_constant_p, overflow_p, jump_target); break; - case CLEANUP_POINT_EXPR: { + case CLEANUP_POINT_EXPR: + { auto_vec<tree, 2> cleanups; vec<tree> *prev_cleanups = ctx->global->cleanups; ctx->global->cleanups = &cleanups; @@ -2413,7 +2493,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) eval_constant_expression (ctx, cleanup, false, non_constant_p, - overflow_p); + overflow_p, jump_target); } break; @@ -2423,7 +2503,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, if (!*non_constant_p) /* Also evaluate the cleanup. */ eval_constant_expression (ctx, TREE_OPERAND (t, 1), true, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); break; case CONSTRUCTOR: @@ -2435,17 +2515,19 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, if (TREE_CONSTANT (t)) return fold (t); } - r = eval_bare_aggregate (ctx, t, lval, non_constant_p, overflow_p); + r = eval_bare_aggregate (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; /* FALLTHROUGH. */ case NOP_EXPR: case CONVERT_EXPR: - case VIEW_CONVERT_EXPR: { + case VIEW_CONVERT_EXPR: + { tree oldop = TREE_OPERAND (t, 0); tree op = eval_constant_expression (ctx, oldop, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); if (*non_constant_p) return t; tree type = TREE_TYPE (t); @@ -2576,7 +2658,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, return ctor; else return eval_constant_expression (ctx, ctor, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } /* A placeholder without a referent. We can get here when checking whether NSDMIs are noexcept, or in massage_init_elt; @@ -2637,7 +2719,8 @@ is_empty_field (tree decl) static tree eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { constexpr_ctx new_ctx = *ctx; @@ -2658,7 +2741,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, if (!SCALAR_TYPE_P (type)) new_ctx.ctor = new_ctx.object = NULL_TREE; init = eval_constant_expression (&new_ctx, init, false, non_constant_p, - overflow_p); + overflow_p, jump_target); if (*non_constant_p) return t; } @@ -2670,7 +2753,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, as a whole; otherwise, only evaluate the innermost piece to avoid building up unnecessary *_REFs. */ target = eval_constant_expression (ctx, target, true, non_constant_p, - overflow_p); + overflow_p, jump_target); evaluated = true; if (*non_constant_p) return t; @@ -2688,7 +2771,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, { case BIT_FIELD_REF: case COMPONENT_REF: - case ARRAY_REF: { + case ARRAY_REF: + { tree ob = TREE_OPERAND (probe, 0); tree elt = TREE_OPERAND (probe, 1); if (TREE_CODE (elt) == FIELD_DECL /*&& DECL_MUTABLE_P (elt)*/) @@ -2698,7 +2782,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, if (TREE_CODE (probe) == ARRAY_REF) { elt = eval_and_check_array_index (ctx, probe, false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; } @@ -2722,8 +2807,9 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, object = probe; else { - probe = eval_constant_expression (ctx, probe, true, - non_constant_p, overflow_p); + probe + = eval_constant_expression (ctx, probe, true, non_constant_p, + overflow_p, jump_target); evaluated = true; if (*non_constant_p) return t; @@ -2914,7 +3000,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, if (tree tinit = TARGET_EXPR_INITIAL (init)) init = tinit; init = eval_constant_expression (&new_ctx, init, false, non_constant_p, - overflow_p); + overflow_p, jump_target); /* The hash table might have moved since the get earlier, and the initializer might have mutated the underlying CONSTRUCTORs, so we must recompute VALP. */ @@ -3016,22 +3102,115 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, Like cxx_eval_unary_expression, except for binary expressions. */ static tree eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { + tree r = NULL_TREE; tree orig_lhs = TREE_OPERAND (t, 0); tree orig_rhs = TREE_OPERAND (t, 1); tree lhs, rhs; - lhs = eval_constant_expression (ctx, orig_lhs, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); + /* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer + subtraction. */ + if (*non_constant_p) + return t; + if (*jump_target) + return NULL_TREE; + rhs = eval_constant_expression (ctx, orig_rhs, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); + if (*non_constant_p) + return t; + if (*jump_target) + return NULL_TREE; location_t loc = EXPR_LOCATION (t); enum tree_code code = TREE_CODE (t); tree type = TREE_TYPE (t); - return fold_binary_loc (loc, code, type, lhs, rhs); + if (code == EQ_EXPR || code == NE_EXPR) + { + bool is_code_eq = (code == EQ_EXPR); + + if (TREE_CODE (lhs) == PTRMEM_CST && TREE_CODE (rhs) == PTRMEM_CST) + { + tree lmem = PTRMEM_CST_MEMBER (lhs); + tree rmem = PTRMEM_CST_MEMBER (rhs); + bool eq = false; + if (TREE_CODE (lmem) == TREE_CODE (rmem) + && TREE_CODE (lmem) == FIELD_DECL + && TREE_CODE (DECL_CONTEXT (lmem)) == UNION_TYPE + && same_type_p (DECL_CONTEXT (lmem), DECL_CONTEXT (rmem))) + /* If both refer to (possibly different) members of the same union + (12.3), they compare equal. */ + eq = true; + // else + // eq = cp_tree_equal (lhs, rhs); + r = constant_boolean_node (eq == is_code_eq, type); + } + else if ((TREE_CODE (lhs) == PTRMEM_CST || TREE_CODE (rhs) == PTRMEM_CST) + && (null_member_pointer_value_p (lhs) + || null_member_pointer_value_p (rhs))) + r = constant_boolean_node (!is_code_eq, type); + } + if (r == NULL_TREE && TREE_CODE_CLASS (code) == tcc_comparison + && POINTER_TYPE_P (TREE_TYPE (lhs))) + { + if (tree lhso = maybe_fold_addr_pointer_plus (lhs)) + lhs = fold_convert (TREE_TYPE (lhs), lhso); + if (tree rhso = maybe_fold_addr_pointer_plus (rhs)) + rhs = fold_convert (TREE_TYPE (rhs), rhso); + } + if (code == POINTER_PLUS_EXPR && !*non_constant_p && integer_zerop (lhs) + && !integer_zerop (rhs)) + { + if (!ctx->quiet) + error ("arithmetic involving a null pointer in %qE", lhs); + *non_constant_p = true; + return t; + } + else if (code == POINTER_PLUS_EXPR) + { + r = fold_pointer_plus_expression (ctx, t, lhs, rhs, non_constant_p, + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; + } + + if (r == NULL_TREE) + { + r = fold_binary_loc (loc, code, type, lhs, rhs); + } + + if (r == NULL_TREE && (code == LSHIFT_EXPR || code == RSHIFT_EXPR) + && TREE_CODE (lhs) == INTEGER_CST && TREE_CODE (rhs) == INTEGER_CST + && wi::neg_p (wi::to_wide (rhs))) + { + /* For diagnostics and -fpermissive emulate previous behavior of + handling shifts by negative amount. */ + tree nrhs = const_unop (NEGATE_EXPR, TREE_TYPE (rhs), rhs); + if (nrhs) + r = fold_binary_loc (loc, + code == LSHIFT_EXPR ? RSHIFT_EXPR : LSHIFT_EXPR, + type, lhs, nrhs); + } + + if (r == NULL_TREE) + { + if (lhs == orig_lhs && rhs == orig_rhs) + r = t; + else + r = build2_loc (loc, code, type, lhs, rhs); + } + else if (eval_check_shift_p (loc, ctx, code, type, lhs, rhs)) + *non_constant_p = true; + /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to + a local array in a constexpr function. */ + bool ptr = INDIRECT_TYPE_P (TREE_TYPE (lhs)); + if (!ptr) + VERIFY_CONSTANT (r); + return r; } /* Helper function of cxx_bind_parameters_in_call. Return non-NULL @@ -3069,7 +3248,7 @@ addr_of_non_const_var (tree *tp, int *walk_subtrees, void *data) static tree rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, bool *non_constant_p, bool *overflow_p, - bool *non_constant_args) + bool *non_constant_args, tree *jump_target) { const int nargs = call_expr_nargs (t); tree parms = DECL_ARGUMENTS (fun); @@ -3093,7 +3272,7 @@ rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, such as this, but here we do the elision differently: we keep the TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */ arg = eval_constant_expression (ctx, x, /*lval=*/false, non_constant_p, - overflow_p); + overflow_p, jump_target); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p && ctx->quiet) break; @@ -3159,7 +3338,8 @@ rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, static tree eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, - bool lval, bool *non_constant_p, bool *overflow_p) + bool lval, bool *non_constant_p, bool *overflow_p, + tree *jump_target) { const int nargs = call_expr_nargs (t); tree *args = (tree *) alloca (nargs * sizeof (tree)); @@ -3262,8 +3442,9 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, || potential_constant_expression (arg)) { bool dummy1 = false, dummy2 = false; - arg - = eval_constant_expression (&new_ctx, arg, false, &dummy1, &dummy2); + tree dummy_jump_target = NULL_TREE; + arg = eval_constant_expression (&new_ctx, arg, false, &dummy1, + &dummy2, &dummy_jump_target); } if (bi_const_p) @@ -3359,7 +3540,7 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, } return eval_constant_expression (&new_ctx, new_call, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } // Subroutine of cxx_eval_constant_expression. @@ -3367,7 +3548,7 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, // evaluation. static tree eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { location_t loc = EXPR_LOCATION (t); tree fun = get_function_named_in_call (t); @@ -3396,12 +3577,12 @@ eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval, if (fndecl_built_in_p (fun)) return eval_builtin_function_call (ctx, t, fun, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); bool non_constant_args = false; new_call.bindings = rs_bind_parameters_in_call (ctx, t, fun, non_constant_p, overflow_p, - &non_constant_args); + &non_constant_args, jump_target); /* We build up the bindings list before we know whether we already have this call cached. If we don't end up saving these bindings, ggc_free them when @@ -3940,7 +4121,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) { switch (TREE_CODE (body)) { - case STATEMENT_LIST: { + case STATEMENT_LIST: + { tree expr = NULL_TREE; for (tree stmt : tsi_range (body)) { @@ -3958,13 +4140,15 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) return expr; } - case RETURN_EXPR: { + case RETURN_EXPR: + { bool non_constant_p = false; bool overflow_p = false; return eval_constant_expression (ctx, body, false, &non_constant_p, - &overflow_p); + &overflow_p, NULL); } - case DECL_EXPR: { + case DECL_EXPR: + { tree decl = DECL_EXPR_DECL (body); if (TREE_CODE (decl) == USING_DECL /* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */ @@ -3976,7 +4160,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) case CLEANUP_POINT_EXPR: return constexpr_fn_retval (ctx, TREE_OPERAND (body, 0)); - case BIND_EXPR: { + case BIND_EXPR: + { tree b = BIND_EXPR_BODY (body); return constexpr_fn_retval (ctx, b); } @@ -4024,6 +4209,17 @@ constant_value_1 (tree decl, bool, bool, bool unshare_p) return unshare_p ? unshare_expr (decl) : decl; } +/* Like scalar_constant_value, but can also return aggregate initializers. + If UNSHARE_P, return an unshared copy of the initializer. */ + +tree +decl_really_constant_value (tree decl, bool unshare_p /*= true*/) +{ + return constant_value_1 (decl, /*strict_p=*/true, + /*return_aggregate_cst_ok_p=*/true, + /*unshare_p=*/unshare_p); +} + // A more relaxed version of decl_really_constant_value, used by the // common C/C++ code. tree @@ -4037,15 +4233,38 @@ decl_constant_value (tree decl, bool unshare_p) static void non_const_var_error (location_t loc, tree r) { - error_at (loc, - "the value of %qD is not usable in a constant " - "expression", - r); + tree type = TREE_TYPE (r); + /* Avoid error cascade. */ if (DECL_INITIAL (r) == error_mark_node) return; - - // more in cp/constexpr.cc + if (DECL_DECLARED_CONSTEXPR_P (r)) + inform (DECL_SOURCE_LOCATION (r), "%qD used in its own initializer", r); + else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)) + { + if (!DECL_INITIAL (r) || !TREE_CONSTANT (DECL_INITIAL (r)) + || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)) + inform (DECL_SOURCE_LOCATION (r), + "%qD was not initialized with a constant " + "expression", + r); + else + gcc_unreachable (); + } + else if (TYPE_REF_P (type)) + inform (DECL_SOURCE_LOCATION (r), + "%qD was not initialized with a constant " + "expression", + r); + else + { + if (!DECL_DECLARED_CONSTEXPR_P (r)) + inform (DECL_SOURCE_LOCATION (r), "%qD was not declared %<constexpr%>", + r); + else + inform (DECL_SOURCE_LOCATION (r), + "%qD does not have integral or enumeration type", r); + } } static tree @@ -4136,7 +4355,8 @@ array_index_cmp (tree key, tree index) { case INTEGER_CST: return tree_int_cst_compare (key, index); - case RANGE_EXPR: { + case RANGE_EXPR: + { tree lo = TREE_OPERAND (index, 0); tree hi = TREE_OPERAND (index, 1); if (tree_int_cst_lt (key, lo)) @@ -4321,7 +4541,7 @@ verify_constant (tree t, bool allow_non_constant, bool *non_constant_p, if (!*non_constant_p && !reduced_constant_expression_p (t) && t != void_node) { if (!allow_non_constant) - error ("%q+E is not a constant expression", t); + error_at (EXPR_LOCATION (t), "is not a constant expression"); *non_constant_p = true; } if (TREE_OVERFLOW_P (t)) @@ -4426,7 +4646,8 @@ diag_array_subscript (location_t loc, const constexpr_ctx *ctx, tree array, static tree get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree nelts; if (TREE_CODE (type) == ARRAY_TYPE) @@ -4442,8 +4663,8 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, rust_unreachable (); /* For VLAs, the number of elements won't be an integer constant. */ - nelts - = eval_constant_expression (ctx, nelts, false, non_constant_p, overflow_p); + nelts = eval_constant_expression (ctx, nelts, false, non_constant_p, + overflow_p, jump_target); return nelts; } @@ -4455,13 +4676,13 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t, bool allow_one_past, bool *non_constant_p, - bool *overflow_p) + bool *overflow_p, tree *jump_target) { location_t loc = rs_expr_loc_or_input_loc (t); tree ary = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 1); tree index = eval_constant_expression (ctx, t, allow_one_past, non_constant_p, - overflow_p); + overflow_p, jump_target); VERIFY_CONSTANT (index); if (!tree_fits_shwi_p (index) || tree_int_cst_sgn (index) < 0) @@ -4472,7 +4693,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx, tree t, } tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p, - overflow_p); + overflow_p, jump_target); VERIFY_CONSTANT (nelts); if (allow_one_past ? !tree_int_cst_le (index, nelts) : !tree_int_cst_lt (index, nelts)) @@ -4682,9 +4903,9 @@ eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, bool *non_constant_p, bool *overflow_p, tree *jump_target) { - tree val - = eval_constant_expression (ctx, TREE_OPERAND (t, 0), - /*lval*/ false, non_constant_p, overflow_p); + tree val = eval_constant_expression (ctx, TREE_OPERAND (t, 0), + /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (val); if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t)) { @@ -4721,14 +4942,14 @@ eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, static tree eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree orig_whole = TREE_OPERAND (t, 0); tree retval, fldval, utype, mask; bool fld_seen = false; HOST_WIDE_INT istart, isize; tree whole = eval_constant_expression (ctx, orig_whole, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); tree start, field, value; unsigned HOST_WIDE_INT i; @@ -4959,8 +5180,8 @@ eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, { tree cond = TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_COND (t) : SWITCH_COND (t); - cond - = eval_constant_expression (ctx, cond, false, non_constant_p, overflow_p); + cond = eval_constant_expression (ctx, cond, false, non_constant_p, overflow_p, + jump_target); VERIFY_CONSTANT (cond); *jump_target = cond; @@ -4994,12 +5215,13 @@ eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, static tree eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree r; tree orig_arg = TREE_OPERAND (t, 0); tree arg = eval_constant_expression (ctx, orig_arg, /*lval*/ false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); VERIFY_CONSTANT (arg); location_t loc = EXPR_LOCATION (t); enum tree_code code = TREE_CODE (t); @@ -5135,7 +5357,9 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, if (manifestly_const_eval) instantiate_constexpr_fns (r); - r = eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p); + tree jump_target = NULL_TREE; + r = eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p, + &jump_target); if (!constexpr_dtor) verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p); @@ -5147,7 +5371,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) eval_constant_expression (&ctx, cleanup, false, &non_constant_p, - &overflow_p); + &overflow_p, NULL); /* Mutable logic is a bit tricky: we want to allow initialization of constexpr variables with mutable members, but we can't copy those @@ -5907,7 +6131,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, /* A pointer-to-member constant. */ return true; - // handle_addr_expr: #if 0 /* FIXME adjust when issue 1197 is fully resolved. For now don't do any checking here, as we might dereference the pointer later. If @@ -5943,7 +6166,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case BIT_FIELD_REF: return RECUR (TREE_OPERAND (t, 0), want_rval); - case INDIRECT_REF: { + case INDIRECT_REF: + { tree x = TREE_OPERAND (t, 0); STRIP_NOPS (x); return RECUR (x, rval); @@ -6214,7 +6438,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case INIT_EXPR: return RECUR (TREE_OPERAND (t, 1), rval); - case CONSTRUCTOR: { + case CONSTRUCTOR: + { vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t); constructor_elt *ce; for (i = 0; vec_safe_iterate (v, i, &ce); ++i) @@ -6223,7 +6448,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return true; } - case TREE_LIST: { + case TREE_LIST: + { gcc_assert (TREE_PURPOSE (t) == NULL_TREE || DECL_P (TREE_PURPOSE (t))); if (!RECUR (TREE_VALUE (t), want_rval)) return false; @@ -6238,7 +6464,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case ROUND_DIV_EXPR: case TRUNC_MOD_EXPR: case CEIL_MOD_EXPR: - case ROUND_MOD_EXPR: { + case ROUND_MOD_EXPR: + { tree denom = TREE_OPERAND (t, 1); if (!RECUR (denom, rval)) return false; @@ -6258,7 +6485,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, } } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* check_return_expr sometimes wraps a TARGET_EXPR in a COMPOUND_EXPR; don't get confused. */ tree op0 = TREE_OPERAND (t, 0); @@ -6280,7 +6508,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case TRUTH_OR_EXPR: case TRUTH_ORIF_EXPR: tmp = boolean_false_node; - truth : { + truth: + { tree op0 = TREE_OPERAND (t, 0); tree op1 = TREE_OPERAND (t, 1); if (!RECUR (op0, rval)) @@ -6477,6 +6706,170 @@ fold_non_dependent_init (tree t, tsubst_flags_t /*=tf_warning_or_error*/, return maybe_constant_init (t, object, manifestly_const_eval); } +/* Check whether the shift operation with code CODE and type TYPE on LHS + and RHS is undefined. If it is, give an error with an explanation, + and return true; return false otherwise. */ + +static bool +eval_check_shift_p (location_t loc, const constexpr_ctx *ctx, + enum tree_code code, tree type, tree lhs, tree rhs) +{ + if ((code != LSHIFT_EXPR && code != RSHIFT_EXPR) + || TREE_CODE (lhs) != INTEGER_CST || TREE_CODE (rhs) != INTEGER_CST) + return false; + + tree lhstype = TREE_TYPE (lhs); + unsigned HOST_WIDE_INT uprec = TYPE_PRECISION (TREE_TYPE (lhs)); + + /* [expr.shift] The behavior is undefined if the right operand + is negative, or greater than or equal to the length in bits + of the promoted left operand. */ + if (tree_int_cst_sgn (rhs) == -1) + { + if (!ctx->quiet) + permerror (loc, "right operand of shift expression %q+E is negative", + build2_loc (loc, code, type, lhs, rhs)); + return (!flag_permissive || ctx->quiet); + } + if (compare_tree_int (rhs, uprec) >= 0) + { + if (!ctx->quiet) + permerror (loc, + "right operand of shift expression %q+E is greater " + "than or equal to the precision %wu of the left operand", + build2_loc (loc, code, type, lhs, rhs), uprec); + return (!flag_permissive || ctx->quiet); + } + + /* The value of E1 << E2 is E1 left-shifted E2 bit positions; [...] + if E1 has a signed type and non-negative value, and E1x2^E2 is + representable in the corresponding unsigned type of the result type, + then that value, converted to the result type, is the resulting value; + otherwise, the behavior is undefined. + For C++20: + The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo + 2^N, where N is the range exponent of the type of the result. */ + if (code == LSHIFT_EXPR && !TYPE_OVERFLOW_WRAPS (lhstype)) + { + if (tree_int_cst_sgn (lhs) == -1) + { + if (!ctx->quiet) + permerror (loc, "left operand of shift expression %q+E is negative", + build2_loc (loc, code, type, lhs, rhs)); + return (!flag_permissive || ctx->quiet); + } + /* For signed x << y the following: + (unsigned) x >> ((prec (lhs) - 1) - y) + if > 1, is undefined. The right-hand side of this formula + is the highest bit of the LHS that can be set (starting from 0), + so that the shift doesn't overflow. We then right-shift the LHS + to see whether any other bit is set making the original shift + undefined -- the result is not representable in the corresponding + unsigned type. */ + tree t = build_int_cst (unsigned_type_node, uprec - 1); + t = fold_build2 (MINUS_EXPR, unsigned_type_node, t, rhs); + tree ulhs = fold_convert (unsigned_type_for (lhstype), lhs); + t = fold_build2 (RSHIFT_EXPR, TREE_TYPE (ulhs), ulhs, t); + if (tree_int_cst_lt (integer_one_node, t)) + { + if (!ctx->quiet) + permerror (loc, "shift expression %q+E overflows", + build2_loc (loc, code, type, lhs, rhs)); + return (!flag_permissive || ctx->quiet); + } + } + return false; +} + +/* Helper function for cxx_eval_binary_expression. Try to optimize + original POINTER_PLUS_EXPR T, LHS p+ RHS, return NULL_TREE if the + generic folding should be used. */ + +static tree +fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, tree lhs, + tree rhs, bool *non_constant_p, bool *overflow_p, + tree *jump_target) +{ + STRIP_NOPS (lhs); + if (TREE_CODE (lhs) != ADDR_EXPR) + return NULL_TREE; + + lhs = TREE_OPERAND (lhs, 0); + + /* &A[i] p+ j => &A[i + j] */ + if (TREE_CODE (lhs) == ARRAY_REF + && TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST + && TREE_CODE (rhs) == INTEGER_CST && TYPE_SIZE_UNIT (TREE_TYPE (lhs)) + && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST) + { + tree orig_type = TREE_TYPE (t); + location_t loc = EXPR_LOCATION (t); + tree type = TREE_TYPE (lhs); + + t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1)); + tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0))); + nelts = eval_constant_expression (ctx, nelts, true, non_constant_p, + overflow_p, jump_target); + if (*non_constant_p) + return NULL_TREE; + if (*jump_target) + return NULL_TREE; + /* Don't fold an out-of-bound access. */ + if (!tree_int_cst_le (t, nelts)) + return NULL_TREE; + rhs = fold_convert (ssizetype, rhs); + /* Don't fold if rhs can't be divided exactly by TYPE_SIZE_UNIT. + constexpr int A[1]; ... (char *)&A[0] + 1 */ + if (!integer_zerop (fold_build2_loc (loc, TRUNC_MOD_EXPR, sizetype, rhs, + TYPE_SIZE_UNIT (type)))) + return NULL_TREE; + /* Make sure to treat the second operand of POINTER_PLUS_EXPR + as signed. */ + rhs = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype, rhs, + TYPE_SIZE_UNIT (type)); + t = size_binop_loc (loc, PLUS_EXPR, rhs, t); + t = build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (lhs, 0), t, NULL_TREE, + NULL_TREE); + t = build_fold_addr_expr (t); + t = fold_convert (orig_type, t); + return eval_constant_expression (ctx, t, true, non_constant_p, overflow_p, + jump_target); + } + + return NULL_TREE; +} + +/* Try to fold expressions like + (struct S *) (&a[0].D.2378 + 12) + into + &MEM <struct T> [(void *)&a + 12B] + This is something normally done by gimple_fold_stmt_to_constant_1 + on GIMPLE, but is undesirable on GENERIC if we are e.g. going to + dereference the address because some details are lost. + For pointer comparisons we want such folding though so that + match.pd address_compare optimization works. */ + +static tree +maybe_fold_addr_pointer_plus (tree t) +{ + while (CONVERT_EXPR_P (t) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))) + t = TREE_OPERAND (t, 0); + if (TREE_CODE (t) != POINTER_PLUS_EXPR) + return NULL_TREE; + tree op0 = TREE_OPERAND (t, 0); + tree op1 = TREE_OPERAND (t, 1); + if (TREE_CODE (op1) != INTEGER_CST) + return NULL_TREE; + while (CONVERT_EXPR_P (op0) + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))) + op0 = TREE_OPERAND (op0, 0); + if (TREE_CODE (op0) != ADDR_EXPR) + return NULL_TREE; + op1 = fold_convert (ptr_type_node, op1); + tree r = fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (op0)), op0, op1); + return build1_loc (EXPR_LOCATION (t), ADDR_EXPR, TREE_TYPE (op0), r); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-constexpr.h b/gcc/rust/backend/rust-constexpr.h index 77a0797..27f0a2e 100644 --- a/gcc/rust/backend/rust-constexpr.h +++ b/gcc/rust/backend/rust-constexpr.h @@ -24,8 +24,7 @@ namespace Rust { namespace Compile { extern tree fold_expr (tree); -extern void -maybe_save_constexpr_fundef (tree fun); +extern void maybe_save_constexpr_fundef (tree fun); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc index d0df4ab..f6b1a4c 100644 --- a/gcc/rust/backend/rust-mangle-v0.cc +++ b/gcc/rust/backend/rust-mangle-v0.cc @@ -62,9 +62,9 @@ struct V0Path } }; -static std::string -v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +static std::string v0_path (Rust::Compile::Context *ctx, + const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); static std::string v0_tuple_prefix (const TyTy::BaseType *ty) @@ -148,7 +148,8 @@ v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty) // TODO: generics switch (ty->get_kind ()) { - case TyTy::TypeKind::ADT: { + case TyTy::TypeKind::ADT: + { const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (ty); return v0_path (ctx, ty, adt->get_ident ().path); } @@ -387,7 +388,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, { switch (impl_item->first->get_impl_item_type ()) { - case HIR::ImplItem::FUNCTION: { + case HIR::ImplItem::FUNCTION: + { HIR::Function *fn = static_cast<HIR::Function *> (impl_item->first); v0path @@ -408,7 +410,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, { switch (trait_item.value ()->get_item_kind ()) { - case HIR::TraitItem::FUNC: { + case HIR::TraitItem::FUNC: + { auto fn = static_cast<HIR::TraitItemFunc *> (*trait_item); rust_unreachable (); v0path = v0_function_path (v0path, ctx, ty, @@ -428,7 +431,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, else if (auto item = mappings.lookup_hir_item (hir_id)) switch (item.value ()->get_item_kind ()) { - case HIR::Item::ItemKind::Function: { + case HIR::Item::ItemKind::Function: + { HIR::Function *fn = static_cast<HIR::Function *> (*item); v0path = v0_function_path (v0path, ctx, ty, fn->get_generic_params (), diff --git a/gcc/rust/backend/rust-mangle.h b/gcc/rust/backend/rust-mangle.h index 2a84b6b..418f2bd 100644 --- a/gcc/rust/backend/rust-mangle.h +++ b/gcc/rust/backend/rust-mangle.h @@ -49,13 +49,12 @@ private: static enum MangleVersion version; }; -std::string -legacy_mangle_item (const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +std::string legacy_mangle_item (const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); -std::string -v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +std::string v0_mangle_item (Rust::Compile::Context *ctx, + const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index 6cba04b..b86c3c8 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -268,7 +268,8 @@ convert_to_void (tree expr, impl_conv_void implicit) return expr; switch (TREE_CODE (expr)) { - case COND_EXPR: { + case COND_EXPR: + { /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr, 1); tree op2 = TREE_OPERAND (expr, 2); @@ -294,7 +295,8 @@ convert_to_void (tree expr, impl_conv_void implicit) break; } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr, 1); tree new_op1; @@ -323,7 +325,8 @@ convert_to_void (tree expr, impl_conv_void implicit) maybe_warn_nodiscard (expr, implicit); break; - case INDIRECT_REF: { + case INDIRECT_REF: + { tree type = TREE_TYPE (expr); int is_reference = TYPE_REF_P (TREE_TYPE (TREE_OPERAND (expr, 0))); int is_volatile = TYPE_VOLATILE (type); @@ -518,7 +521,8 @@ convert_to_void (tree expr, impl_conv_void implicit) break; } - case VAR_DECL: { + case VAR_DECL: + { /* External variables might be incomplete. */ tree type = TREE_TYPE (expr); int is_complete = COMPLETE_TYPE_P (type); @@ -1485,7 +1489,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data) parameter pack. ??? Should some of these be in cp_walk_subtrees? */ switch (TREE_CODE (t)) { - case DECL_EXPR: { + case DECL_EXPR: + { tree decl = DECL_EXPR_DECL (t); if (is_typedef_decl (decl)) /* Since we stop at typedefs above, we need to look through them at @@ -1506,7 +1511,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data) *walk_subtrees = 0; return NULL_TREE; - case DECLTYPE_TYPE: { + case DECLTYPE_TYPE: + { /* When traversing a DECLTYPE_TYPE_EXPR, we need to set type_pack_expansion_p to false so that any placeholders within the expression don't get marked as parameter packs. */ @@ -1970,7 +1976,8 @@ rs_tree_equal (tree t1, tree t2) case SAVE_EXPR: return rs_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); - case CALL_EXPR: { + case CALL_EXPR: + { if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2)) return false; @@ -1996,7 +2003,8 @@ rs_tree_equal (tree t1, tree t2) return true; } - case TARGET_EXPR: { + case TARGET_EXPR: + { tree o1 = TREE_OPERAND (t1, 0); tree o2 = TREE_OPERAND (t2, 0); @@ -2067,7 +2075,8 @@ rs_tree_equal (tree t1, tree t2) case tcc_expression: case tcc_vl_exp: case tcc_reference: - case tcc_statement: { + case tcc_statement: + { int n = rs_tree_operand_length (t1); if (TREE_CODE_CLASS (code1) == tcc_vl_exp && n != TREE_OPERAND_LENGTH (t2)) @@ -2095,7 +2104,11 @@ rs_tree_equal (tree t1, tree t2) /* TRUE iff TYPE is publicly & uniquely derived from PARENT. */ -bool publicly_uniquely_derived_p (tree, tree) { return false; } +bool +publicly_uniquely_derived_p (tree, tree) +{ + return false; +} // forked from gcc/cp/typeck.cc comp_except_types @@ -3375,7 +3388,11 @@ release_tree_vector (vec<tree, va_gc> *vec) /* As above, but also check value-dependence of the expression as a whole. */ -bool instantiation_dependent_expression_p (tree) { return false; } +bool +instantiation_dependent_expression_p (tree) +{ + return false; +} // forked from gcc/cp/cvt.cc cp_get_callee @@ -3425,7 +3442,11 @@ scalarish_type_p (const_tree t) constructors are deleted. This function implements the ABI notion of non-trivial copy, which has diverged from the one in the standard. */ -bool type_has_nontrivial_copy_init (const_tree) { return false; } +bool +type_has_nontrivial_copy_init (const_tree) +{ + return false; +} // forked from gcc/cp/tree.cc build_local_temp @@ -3448,7 +3469,11 @@ build_local_temp (tree type) /* Returns true iff DECL is a capture proxy for a normal capture (i.e. without explicit initializer). */ -bool is_normal_capture_proxy (tree) { return false; } +bool +is_normal_capture_proxy (tree) +{ + return false; +} // forked from gcc/cp/c-common.cc reject_gcc_builtin @@ -3522,7 +3547,8 @@ is_bitfield_expr_with_lowered_type (const_tree exp) case BIT_NOT_EXPR: return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); - case COMPONENT_REF: { + case COMPONENT_REF: + { tree field; field = TREE_OPERAND (exp, 1); @@ -3848,16 +3874,18 @@ strip_top_quals (tree t) /* Print an error message for invalid use of an incomplete type. VALUE is the expression that was used (or 0 if that isn't known) and TYPE is the type that was invalid. DIAG_KIND indicates the - type of diagnostic (see diagnostic.def). */ + type of diagnostic (see diagnostics/kinds.def). */ void cxx_incomplete_type_diagnostic (location_t loc, const_tree value, - const_tree type, diagnostic_t diag_kind) + const_tree type, + enum diagnostics::kind diag_kind) { // bool is_decl = false, complained = false; - gcc_assert (diag_kind == DK_WARNING || diag_kind == DK_PEDWARN - || diag_kind == DK_ERROR); + gcc_assert (diag_kind == diagnostics::kind::warning + || diag_kind == diagnostics::kind::pedwarn + || diag_kind == diagnostics::kind::error); /* Avoid duplicate error message. */ if (TREE_CODE (type) == ERROR_MARK) @@ -3907,7 +3935,8 @@ retry: break; case OFFSET_TYPE: - bad_member : { + bad_member: + { tree member = TREE_OPERAND (value, 1); if (is_overloaded_fn (member)) member = get_first_fn (member); @@ -3992,13 +4021,21 @@ decl_constant_var_p (tree decl) /* Returns true iff DECL is a variable or function declared with an auto type that has not yet been deduced to a real type. */ -bool undeduced_auto_decl (tree) { return false; } +bool +undeduced_auto_decl (tree) +{ + return false; +} // forked from gcc/cp/decl.cc require_deduced_type /* Complain if DECL has an undeduced return type. */ -bool require_deduced_type (tree, tsubst_flags_t) { return true; } +bool +require_deduced_type (tree, tsubst_flags_t) +{ + return true; +} /* Return the location of a tree passed to %+ formats. */ @@ -4288,10 +4325,9 @@ struct GTY ((for_user)) source_location_table_entry } // namespace Rust -extern void -gt_pch_nx (Rust::source_location_table_entry &); -extern void -gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator, void *); +extern void gt_pch_nx (Rust::source_location_table_entry &); +extern void gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator, + void *); namespace Rust { @@ -4419,7 +4455,8 @@ lvalue_kind (const_tree ref) case VIEW_CONVERT_EXPR: return lvalue_kind (TREE_OPERAND (ref, 0)); - case ARRAY_REF: { + case ARRAY_REF: + { tree op1 = TREE_OPERAND (ref, 0); if (TREE_CODE (TREE_TYPE (op1)) == ARRAY_TYPE) { @@ -4516,7 +4553,8 @@ lvalue_kind (const_tree ref) op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1)); break; - case COND_EXPR: { + case COND_EXPR: + { tree op1 = TREE_OPERAND (ref, 1); if (!op1) op1 = TREE_OPERAND (ref, 0); @@ -5131,7 +5169,7 @@ complete_type_or_maybe_complain (tree type, tree value, tsubst_flags_t complain) else if (!COMPLETE_TYPE_P (type)) { if (complain & tf_error) - cxx_incomplete_type_diagnostic (value, type, DK_ERROR); + cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error); note_failed_type_completion_for_satisfaction (type); return NULL_TREE; } diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index bb99684..9e859d4 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -1543,7 +1543,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; #if defined ENABLE_TREE_CHECKING #define LANG_DECL_MIN_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!LANG_DECL_HAS_MIN (NODE)) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1554,7 +1554,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; template, not just on a FUNCTION_DECL. So when looking for things in lang_decl_fn, look down through a TEMPLATE_DECL into its result. */ #define LANG_DECL_FN_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != lds_fn) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1562,7 +1562,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_NS_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != lds_ns) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1570,7 +1570,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_PARM_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (TREE_CODE (NODE) != PARM_DECL || lt->u.base.selector != lds_parm) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1578,7 +1578,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_DECOMP_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!VAR_P (NODE) || lt->u.base.selector != lds_decomp) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -2060,8 +2060,8 @@ struct GTY (()) rust_cxx_saved_binding // forked from gcc/cp/name-lookup.h resort_type_member_vec /* needed for GTY annotation */ -extern void -resort_type_member_vec (void *, void *, gt_pointer_operator, void *); +extern void resort_type_member_vec (void *, void *, gt_pointer_operator, + void *); // forked from gcc/cp/cp-tree.h saved_scope @@ -2895,8 +2895,7 @@ enum compare_bounds_t bounds_first }; -extern tree -convert_to_void (tree expr, impl_conv_void implicit); +extern tree convert_to_void (tree expr, impl_conv_void implicit); // The lvalue-to-rvalue conversion (7.1) is applied if and only if the // expression is a glvalue of volatile-qualified type and it is one of the @@ -2911,63 +2910,52 @@ convert_to_void (tree expr, impl_conv_void implicit); // operands are one of these expressions, or // * comma expression (8.19) where the right operand is one of these // expressions. -extern tree -mark_discarded_use (tree expr); +extern tree mark_discarded_use (tree expr); // Mark EXP as read, not just set, for set but not used -Wunused warning // purposes. -extern void -mark_exp_read (tree exp); +extern void mark_exp_read (tree exp); // We've seen an actual use of EXPR. Possibly replace an outer variable // reference inside with its constant value or a lambda capture. -extern tree -mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc, - bool reject_builtin); +extern tree mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc, + bool reject_builtin); // Called whenever the expression EXPR is used in an rvalue context. // When REJECT_BUILTIN is true the expression is checked to make sure // it doesn't make it possible to obtain the address of a GCC built-in // function with no library fallback (or any of its bits, such as in // a conversion to bool). -extern tree -mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION, - bool reject_builtin = true); +extern tree mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION, + bool reject_builtin = true); // Called whenever an expression is used in an lvalue context. -extern tree -mark_lvalue_use (tree expr); +extern tree mark_lvalue_use (tree expr); // As above, but don't consider this use a read. -extern tree -mark_lvalue_use_nonread (tree expr); +extern tree mark_lvalue_use_nonread (tree expr); // We are using a reference VAL for its value. Bash that reference all the way // down to its lowest form. -extern tree -convert_from_reference (tree val); +extern tree convert_from_reference (tree val); // Subroutine of convert_to_void. Warn if we're discarding something with // attribute [[nodiscard]]. -extern void -maybe_warn_nodiscard (tree expr, impl_conv_void implicit); +extern void maybe_warn_nodiscard (tree expr, impl_conv_void implicit); -extern location_t -expr_loc_or_loc (const_tree t, location_t or_loc); +extern location_t expr_loc_or_loc (const_tree t, location_t or_loc); -extern location_t -expr_loc_or_input_loc (const_tree t); +extern location_t expr_loc_or_input_loc (const_tree t); // FN is the callee of a CALL_EXPR or AGGR_INIT_EXPR; return the FUNCTION_DECL // if we can. -extern tree -get_fndecl_from_callee (tree fn); +extern tree get_fndecl_from_callee (tree fn); // FIXME some helpers from HIRCompileBase could probably be moved here over time // Return an expression for the address of BASE[INDEX], used in offset intrinsic -extern tree -pointer_offset_expression (tree base_tree, tree index_tree, location_t locus); +extern tree pointer_offset_expression (tree base_tree, tree index_tree, + location_t locus); /* A tree node, together with a location, so that we can track locations (and ranges) during parsing. @@ -2978,11 +2966,9 @@ pointer_offset_expression (tree base_tree, tree index_tree, location_t locus); extern location_t rs_expr_location (const_tree); -extern int -is_empty_class (tree type); +extern int is_empty_class (tree type); -extern bool -is_really_empty_class (tree, bool); +extern bool is_really_empty_class (tree, bool); extern bool builtin_valid_in_constant_expr_p (const_tree); @@ -2990,15 +2976,13 @@ extern bool maybe_constexpr_fn (tree); extern bool var_in_maybe_constexpr_fn (tree); -extern int -rs_type_quals (const_tree type); +extern int rs_type_quals (const_tree type); inline bool type_unknown_p (const_tree); extern bool decl_maybe_constant_var_p (tree); -extern void -init_modules (); +extern void init_modules (); extern bool var_in_constexpr_fn (tree); @@ -3006,11 +2990,9 @@ inline tree ovl_first (tree) ATTRIBUTE_PURE; inline bool type_unknown_p (const_tree); -extern tree -lookup_add (tree fns, tree lookup); +extern tree lookup_add (tree fns, tree lookup); -extern tree -ovl_make (tree fn, tree next = NULL_TREE); +extern tree ovl_make (tree fn, tree next = NULL_TREE); extern int is_overloaded_fn (tree) ATTRIBUTE_PURE; @@ -3024,19 +3006,15 @@ extern tree make_conv_op_name (tree); extern int type_memfn_quals (const_tree); -struct c_fileinfo * -get_fileinfo (const char *); +struct c_fileinfo *get_fileinfo (const char *); -extern tree -cxx_make_type (enum tree_code CXX_MEM_STAT_INFO); +extern tree cxx_make_type (enum tree_code CXX_MEM_STAT_INFO); -extern tree -build_cplus_array_type (tree, tree, int is_dep = -1); +extern tree build_cplus_array_type (tree, tree, int is_dep = -1); extern bool is_byte_access_type (tree); -extern bool -comptypes (tree, tree, int); +extern bool comptypes (tree, tree, int); extern tree canonical_eh_spec (tree); @@ -3046,8 +3024,7 @@ extern bool rs_tree_equal (tree, tree); extern bool compparms (const_tree, const_tree); -extern tree -rs_build_qualified_type_real (tree, int, tsubst_flags_t); +extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t); #define rs_build_qualified_type(TYPE, QUALS) \ rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error) extern bool cv_qualified_p (const_tree); @@ -3056,21 +3033,18 @@ extern bool similar_type_p (tree, tree); extern bool rs_tree_equal (tree, tree); -extern bool -vector_targets_convertible_p (const_tree t1, const_tree t2); +extern bool vector_targets_convertible_p (const_tree t1, const_tree t2); extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree); extern bool comp_ptr_ttypes_const (tree, tree, compare_bounds_t); -extern tree -get_class_binding_direct (tree, tree, bool want_type = false); +extern tree get_class_binding_direct (tree, tree, bool want_type = false); extern tree skip_artificial_parms_for (const_tree, tree); -extern void -lang_check_failed (const char *, int, - const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD; +extern void lang_check_failed (const char *, int, + const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD; extern tree default_init_uninitialized_part (tree); @@ -3088,8 +3062,7 @@ extern tree in_class_defaulted_default_constructor (tree); extern bool is_instantiation_of_constexpr (tree); -extern bool -check_for_uninitialized_const_var (tree, bool, tsubst_flags_t); +extern bool check_for_uninitialized_const_var (tree, bool, tsubst_flags_t); extern bool reduced_constant_expression_p (tree); @@ -3108,19 +3081,17 @@ extern tree is_bitfield_expr_with_lowered_type (const_tree); extern tree convert_bitfield_to_declared_type (tree); -extern tree -cp_fold_maybe_rvalue (tree, bool); +extern tree cp_fold_maybe_rvalue (tree, bool); extern tree maybe_undo_parenthesized_ref (tree); -extern tree -fold_offsetof (tree, tree = size_type_node, tree_code ctx = ERROR_MARK); +extern tree fold_offsetof (tree, tree = size_type_node, + tree_code ctx = ERROR_MARK); extern tree cp_truthvalue_conversion (tree, tsubst_flags_t); -extern tree -fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error, - bool = false, tree = NULL_TREE); +extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error, + bool = false, tree = NULL_TREE); extern int char_type_p (tree); @@ -3137,7 +3108,7 @@ extern bool reject_gcc_builtin (const_tree, location_t = UNKNOWN_LOCATION); extern tree resolve_nondeduced_context (tree, tsubst_flags_t); extern void cxx_incomplete_type_diagnostic (location_t, const_tree, const_tree, - diagnostic_t); + enum diagnostics::kind); extern void cxx_incomplete_type_error (location_t, const_tree, const_tree); @@ -3163,13 +3134,11 @@ extern tree build_new_constexpr_heap_type (tree, tree, tree); extern bool is_empty_field (tree); -extern bool -in_immediate_context (); +extern bool in_immediate_context (); extern tree cp_get_callee_fndecl_nofold (tree); -extern bool -cxx_mark_addressable (tree, bool = false); +extern bool cxx_mark_addressable (tree, bool = false); extern tree fold_builtin_source_location (location_t); @@ -3183,25 +3152,22 @@ extern bool glvalue_p (const_tree); extern cp_lvalue_kind lvalue_kind (const_tree); -extern tree -decl_constant_value (tree, bool); +extern tree decl_constant_value (tree, bool); extern tree lookup_enumerator (tree, tree); -extern int -is_class_type (tree, int); +extern int is_class_type (tree, int); extern tree braced_lists_to_strings (tree, tree); -extern tree -fold_builtin_is_pointer_inverconvertible_with_class (location_t, int, tree *); +extern tree fold_builtin_is_pointer_inverconvertible_with_class (location_t, + int, tree *); extern bool layout_compatible_type_p (tree, tree); extern tree finish_underlying_type (tree); -extern tree -c_common_type_for_mode (machine_mode, int); +extern tree c_common_type_for_mode (machine_mode, int); extern bool std_layout_type_p (const_tree); @@ -3213,25 +3179,21 @@ extern void note_failed_type_completion_for_satisfaction (tree); extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t); -extern bool -next_common_initial_seqence (tree &, tree &); +extern bool next_common_initial_seqence (tree &, tree &); extern bool null_member_pointer_value_p (tree); -extern tree -fold_builtin_is_corresponding_member (location_t, int, tree *); +extern tree fold_builtin_is_corresponding_member (location_t, int, tree *); extern tree cp_fold_rvalue (tree); -extern tree -maybe_constant_value (tree, tree = NULL_TREE, bool = false); +extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false); extern tree lvalue_type (tree); extern void lvalue_error (location_t, enum lvalue_use); -extern tree -cp_fold_maybe_rvalue (tree, bool); +extern tree cp_fold_maybe_rvalue (tree, bool); extern tree get_first_fn (tree) ATTRIBUTE_PURE; @@ -3253,13 +3215,12 @@ enum ce_exact }; -extern tree -rs_build_qualified_type_real (tree, int, tsubst_flags_t); +extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t); #define rs_build_qualified_type(TYPE, QUALS) \ rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error) -extern tree -rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, hash_set<tree> *); +extern tree rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, + hash_set<tree> *); #define rs_walk_tree(tp, func, data, pset) \ walk_tree_1 (tp, func, data, pset, rs_walk_subtrees) #define rs_walk_tree_without_duplicates(tp, func, data) \ @@ -3351,11 +3312,9 @@ gnu_vector_type_p (const_tree type) return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type); } -extern vec<tree, va_gc> * -make_tree_vector (void); +extern vec<tree, va_gc> *make_tree_vector (void); -extern void -release_tree_vector (vec<tree, va_gc> *); +extern void release_tree_vector (vec<tree, va_gc> *); /* Simplified unique_ptr clone to release a tree vec on exit. */ @@ -3373,7 +3332,7 @@ public: releasing_vec &operator= (const releasing_vec &); vec_t &operator* () const { return *v; } - vec_t *operator-> () const { return v; } + vec_t *operator->() const { return v; } vec_t *get () const { return v; } operator vec_t * () const { return v; } vec_t **operator& () { return &v; } @@ -3430,7 +3389,7 @@ null_node_p (const_tree expr) inline void cxx_incomplete_type_diagnostic (const_tree value, const_tree type, - diagnostic_t diag_kind) + enum diagnostics::kind diag_kind) { cxx_incomplete_type_diagnostic (rs_expr_loc_or_input_loc (value), value, type, diag_kind); @@ -3439,11 +3398,10 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type, inline void cxx_incomplete_type_error (const_tree value, const_tree type) { - cxx_incomplete_type_diagnostic (value, type, DK_ERROR); + cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error); } -extern location_t -location_of (tree t); +extern location_t location_of (tree t); /* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference. */ @@ -3465,23 +3423,18 @@ set_implicit_rvalue_p (tree ot) } namespace Compile { -extern tree -maybe_constant_init (tree, tree = NULL_TREE, bool = false); +extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false); -extern void -explain_invalid_constexpr_fn (tree fun); +extern void explain_invalid_constexpr_fn (tree fun); extern bool potential_constant_expression (tree); -extern bool -literal_type_p (tree t); +extern bool literal_type_p (tree t); -extern bool -maybe_constexpr_fn (tree t); +extern bool maybe_constexpr_fn (tree t); -extern tree -fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error, - bool = false, tree = NULL_TREE); +extern tree fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error, + bool = false, tree = NULL_TREE); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h index 0ce2142..0434bcf 100644 --- a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h +++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h @@ -239,31 +239,25 @@ struct Facts * * Output is not yet implemented and is only dumped to stdout. */ -extern "C" FFI::Output -polonius_run (FFI::FactsView input, bool dump_enabled); +extern "C" FFI::Output polonius_run (FFI::FactsView input, bool dump_enabled); // Helper functions for FFIVector to be used on Rust side extern "C" { -FFI::FFIVector<size_t> * -FFIVector__new (); +FFI::FFIVector<size_t> *FFIVector__new (); -FFI::FFIVectorPair * -FFIVector__new_vec_pair (); +FFI::FFIVectorPair *FFIVector__new_vec_pair (); -FFI::FFIVectorTriple * -FFIVector__new_vec_triple (); +FFI::FFIVectorTriple *FFIVector__new_vec_triple (); -void -FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element); +void FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element); void FFIVector__push_vec_pair (FFI::FFIVectorPair *vector, FFI::Pair<size_t, FFI::FFIVector<size_t> *> element); -void -FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector, - FFI::Triple<size_t, size_t, size_t> element); +void FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector, + FFI::Triple<size_t, size_t, size_t> element); } } // namespace Polonius diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc index d6acc6a..5b22c1a 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc @@ -240,7 +240,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr) auto &elems = expr.get_internal_elements (); switch (elems.get_array_expr_type ()) { - case HIR::ArrayElems::VALUES: { + case HIR::ArrayElems::VALUES: + { auto &elem_vals = (static_cast<HIR::ArrayElemsValues &> (elems)); auto init_values = visit_list (elem_vals.get_values ()); // collect locations @@ -254,7 +255,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr) lookup_type (expr), expr.get_locus ()); break; } - case HIR::ArrayElems::COPIED: { + case HIR::ArrayElems::COPIED: + { auto &elem_copied = (static_cast<HIR::ArrayElemsCopied &> (elems)); auto init = visit_expr (elem_copied.get_elem_to_copy ()); return_expr (new InitializerExpr ({init}), lookup_type (expr), @@ -325,6 +327,14 @@ ExprStmtBuilder::visit (HIR::InlineAsm &expr) {} void +ExprStmtBuilder::visit (HIR::LlvmInlineAsm &expr) +{} + +void +ExprStmtBuilder::visit (HIR::OffsetOf &expr) +{} + +void ExprStmtBuilder::visit (HIR::MethodCallExpr &expr) {} @@ -411,6 +421,18 @@ ExprStmtBuilder::visit (HIR::BlockExpr &block) } void +ExprStmtBuilder::visit (HIR::AnonConst &block) +{ + rust_unreachable (); +} + +void +ExprStmtBuilder::visit (HIR::ConstBlock &block) +{ + rust_unreachable (); +} + +void ExprStmtBuilder::visit (HIR::ContinueExpr &cont) { LoopAndLabelCtx info = cont.has_label () ? get_label_ctx (cont.get_label ()) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h index daedb68..ba5db8b 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h @@ -19,6 +19,7 @@ #ifndef RUST_BIR_BUILDER_EXPR_H #define RUST_BIR_BUILDER_EXPR_H +#include "rust-hir-expr.h" #include "rust-hir-visitor.h" #include "rust-bir-builder-internal.h" @@ -84,6 +85,8 @@ protected: // Expr void visit (HIR::MethodCallExpr &expr) override; void visit (HIR::FieldAccessExpr &expr) override; void visit (HIR::BlockExpr &block) override; + void visit (HIR::AnonConst &block) override; + void visit (HIR::ConstBlock &block) override; void visit (HIR::ContinueExpr &cont) override; void visit (HIR::BreakExpr &brk) override; void visit (HIR::RangeFromToExpr &range) override; @@ -100,6 +103,8 @@ protected: // Expr void visit (HIR::IfExpr &expr) override; void visit (HIR::IfExprConseqElse &expr) override; void visit (HIR::InlineAsm &expr) override; + void visit (HIR::LlvmInlineAsm &expr) override; + void visit (HIR::OffsetOf &expr) override; void visit (HIR::MatchExpr &expr) override; void visit (HIR::AwaitExpr &expr) override; diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index 4df0e14..de8a830 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -24,9 +24,10 @@ #include "rust-hir-item.h" #include "rust-hir-type-check.h" #include "rust-hir-visitor.h" -#include "rust-name-resolver.h" #include "rust-bir.h" #include "rust-bir-free-region.h" +#include "rust-immutable-name-resolution-context.h" +#include "options.h" namespace Rust { @@ -73,7 +74,7 @@ struct BuilderContext // External context. Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; // BIR output BasicBlocks basic_blocks; @@ -102,7 +103,7 @@ struct BuilderContext public: BuilderContext () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()) + resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()) { basic_blocks.emplace_back (); // StartBB } @@ -401,37 +402,31 @@ protected: // HIR resolution helpers template <typename T> NodeId resolve_label (T &expr) { - NodeId resolved_label; - bool ok - = ctx.resolver.lookup_resolved_label (expr.get_mappings ().get_nodeid (), - &resolved_label); - rust_assert (ok); - return resolved_label; + auto res = ctx.resolver.lookup (expr.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return res.value (); } template <typename T> PlaceId resolve_variable (T &variable) { - NodeId variable_id; - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); - return ctx.place_db.lookup_variable (variable_id); + auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return ctx.place_db.lookup_variable (res.value ()); } template <typename T> PlaceId resolve_variable_or_fn (T &variable, TyTy::BaseType *ty) { ty = (ty) ? ty : lookup_type (variable); + // Unlike variables, // functions do not have to be declared in PlaceDB before use. - NodeId variable_id; - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); if (ty->is<TyTy::FnType> ()) return ctx.place_db.get_constant (ty); - else - return ctx.place_db.lookup_or_add_variable (variable_id, ty); + + auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return ctx.place_db.lookup_or_add_variable (res.value (), ty); } protected: // Implicit conversions. diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h index 3bc622c..9108009 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h @@ -169,6 +169,14 @@ public: { return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); } + void visit (HIR::AnonConst &expr) override + { + return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); + } + void visit (HIR::ConstBlock &expr) override + { + return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); + } void visit (HIR::UnsafeBlockExpr &expr) override { return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); @@ -207,6 +215,8 @@ public: } void visit (HIR::InlineAsm &expr) override {} + void visit (HIR::LlvmInlineAsm &expr) override {} + void visit (HIR::OffsetOf &expr) override {} protected: // Illegal at this position. void visit (HIR::StructExprFieldIdentifier &field) override diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc index ee37bb0..e78d750 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc @@ -70,11 +70,34 @@ PatternBindingBuilder::visit (HIR::SlicePattern &pattern) return ty->as<TyTy::SliceType> ()->get_element_type (); }); - // Regions are unchnaged. + // Regions are unchanged. - for (auto &item : pattern.get_items ()) + switch (pattern.get_items ().get_item_type ()) { - item->accept_vis (*this); + case HIR::SlicePatternItems::NO_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &member : items.get_patterns ()) + { + member->accept_vis (*this); + } + break; + } + case HIR::SlicePatternItems::HAS_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (auto &member : items.get_lower_patterns ()) + { + member->accept_vis (*this); + } + for (auto &member : items.get_upper_patterns ()) + { + member->accept_vis (*this); + } + break; + } } } @@ -101,7 +124,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::TUPLE_PAT: { + case HIR::StructPatternField::TUPLE_PAT: + { auto tuple = static_cast<HIR::StructPatternFieldTuplePat *> (field.get ()); @@ -123,7 +147,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) tuple->get_tuple_pattern ().accept_vis (*this); break; } - case HIR::StructPatternField::IDENT_PAT: { + case HIR::StructPatternField::IDENT_PAT: + { auto ident_field = static_cast<HIR::StructPatternFieldIdentPat *> (field.get ()); TyTy::StructFieldType *field_ty = nullptr; @@ -139,7 +164,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) ident_field->get_pattern ().accept_vis (*this); break; } - case HIR::StructPatternField::IDENT: { + case HIR::StructPatternField::IDENT: + { auto ident_field = static_cast<HIR::StructPatternFieldIdent *> (field.get ()); TyTy::StructFieldType *field_ty = nullptr; @@ -199,15 +225,17 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::MULTIPLE: { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + case HIR::TuplePatternItems::NO_REST: + { + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } - case HIR::TuplePatternItems::RANGED: { + case HIR::TuplePatternItems::HAS_REST: + { auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); auto tyty = ctx.place_db[init.value ()].tyty; rust_assert (tyty->get_kind () == TyTy::TUPLE); @@ -244,9 +272,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::HAS_REST: + { auto &items - = static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ()); + = static_cast<HIR::TupleStructItemsHasRest &> (pattern.get_items ()); rust_assert (type->get_kind () == TyTy::ADT); auto adt_ty = static_cast<TyTy::ADTType *> (type); @@ -261,9 +290,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) visit_tuple_fields (items.get_upper_patterns (), saved, index); break; } - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::NO_REST: + { auto &items - = static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ()); + = static_cast<HIR::TupleStructItemsNoRest &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h index 94fcecd..6cb87c7 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h @@ -21,6 +21,7 @@ #include "rust-bir-builder-internal.h" #include "rust-bir-builder-expr-stmt.h" +#include "rust-hir-expr.h" namespace Rust { namespace BIR { @@ -133,6 +134,8 @@ protected: void visit (HIR::MethodCallExpr &expr) override { rust_unreachable (); } void visit (HIR::FieldAccessExpr &expr) override { rust_unreachable (); } void visit (HIR::BlockExpr &expr) override { rust_unreachable (); } + void visit (HIR::AnonConst &expr) override { rust_unreachable (); } + void visit (HIR::ConstBlock &expr) override { rust_unreachable (); } void visit (HIR::ClosureExpr &expr) override { rust_unreachable (); } void visit (HIR::ContinueExpr &expr) override { rust_unreachable (); } void visit (HIR::BreakExpr &expr) override { rust_unreachable (); } @@ -153,6 +156,8 @@ protected: void visit (HIR::AwaitExpr &expr) override { rust_unreachable (); } void visit (HIR::AsyncBlockExpr &expr) override { rust_unreachable (); } void visit (HIR::InlineAsm &expr) override { rust_unreachable (); } + void visit (HIR::LlvmInlineAsm &expr) override { rust_unreachable (); } + void visit (HIR::OffsetOf &expr) override { rust_unreachable (); } void visit (HIR::TypeParam ¶m) override { rust_unreachable (); } void visit (HIR::ConstGenericParam ¶m) override { rust_unreachable (); } void visit (HIR::LifetimeWhereClauseItem &item) override @@ -220,11 +225,11 @@ protected: rust_unreachable (); } void visit (HIR::StructPattern &pattern) override { rust_unreachable (); } - void visit (HIR::TupleStructItemsNoRange &tuple_items) override + void visit (HIR::TupleStructItemsNoRest &tuple_items) override { rust_unreachable (); } - void visit (HIR::TupleStructItemsRange &tuple_items) override + void visit (HIR::TupleStructItemsHasRest &tuple_items) override { rust_unreachable (); } @@ -232,15 +237,23 @@ protected: { rust_unreachable (); } - void visit (HIR::TuplePatternItemsMultiple &tuple_items) override + void visit (HIR::TuplePatternItemsNoRest &tuple_items) override { rust_unreachable (); } - void visit (HIR::TuplePatternItemsRanged &tuple_items) override + void visit (HIR::TuplePatternItemsHasRest &tuple_items) override { rust_unreachable (); } void visit (HIR::TuplePattern &pattern) override { rust_unreachable (); } + void visit (HIR::SlicePatternItemsNoRest &tuple_items) override + { + rust_unreachable (); + } + void visit (HIR::SlicePatternItemsHasRest &tuple_items) override + { + rust_unreachable (); + } void visit (HIR::SlicePattern &pattern) override { rust_unreachable (); } void visit (HIR::AltPattern &pattern) override { rust_unreachable (); } void visit (HIR::EmptyStmt &stmt) override { rust_unreachable (); } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc index 3864b81..9a7bb20 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc @@ -182,7 +182,8 @@ Dump::visit (const Statement &stmt) statement_place = stmt.get_place (); switch (stmt.get_kind ()) { - case Statement::Kind::ASSIGNMENT: { + case Statement::Kind::ASSIGNMENT: + { visit_place (stmt.get_place ()); stream << " = "; stmt.get_expr ().accept_vis (*this); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h index 32a4cd7..4462d77 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h @@ -232,42 +232,50 @@ protected: // Main collection entry points (for different categories). { switch (stmt.get_kind ()) { - case Statement::Kind::ASSIGNMENT: { + case Statement::Kind::ASSIGNMENT: + { // TODO: for unwind, must had hadning for non-panic-only assignements issue_write_deep (stmt.get_place ()); visit_assignment_expr (stmt.get_place (), stmt.get_expr ()); break; } - case Statement::Kind::SWITCH: { + case Statement::Kind::SWITCH: + { issue_read_move (stmt.get_place ()); issue_jumps (); } break; - case Statement::Kind::GOTO: { + case Statement::Kind::GOTO: + { issue_jumps (); } break; - case Statement::Kind::RETURN: { + case Statement::Kind::RETURN: + { issue_place_access (RETURN_VALUE_PLACE); issue_locals_dealloc (); break; } - case Statement::Kind::STORAGE_DEAD: { + case Statement::Kind::STORAGE_DEAD: + { facts.path_moved_at_base.emplace_back (stmt.get_place ().value, get_current_point_mid ()); facts.var_defined_at.emplace_back (stmt.get_place ().value, get_current_point_mid ()); break; } - case Statement::Kind::STORAGE_LIVE: { + case Statement::Kind::STORAGE_LIVE: + { issue_write_deep (stmt.get_place (), true); break; } - case Statement::Kind::USER_TYPE_ASCRIPTION: { + case Statement::Kind::USER_TYPE_ASCRIPTION: + { issue_user_type_constraints (stmt.get_place (), stmt.get_type ()); break; } - case Statement::Kind::FAKE_READ: { + case Statement::Kind::FAKE_READ: + { issue_place_access (stmt.get_place ()); break; } @@ -791,7 +799,8 @@ protected: // Subset helpers. type->as<const TyTy::SliceType> ()->get_element_type (), region_start, regions); case TyTy::FNDEF: - case TyTy::TUPLE: { + case TyTy::TUPLE: + { for (auto &field : type->as<const TyTy::TupleType> ()->get_fields ()) sanitize_constraints (field.get_tyty (), region_start, regions); } @@ -815,6 +824,7 @@ protected: // Subset helpers. case TyTy::PLACEHOLDER: case TyTy::INFER: case TyTy::PARAM: + case TyTy::CONST: case TyTy::OPAQUE: rust_unreachable (); } @@ -874,7 +884,7 @@ protected: // Subset helpers. return region_end; } -}; // namespace BIR +}; } // namespace BIR } // namespace Rust diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index 67ca90b..2e9103f 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -53,7 +53,7 @@ using Variance = TyTy::VarianceAnalysis::Variance; /** A unique identifier for a loan in the BIR. */ struct LoanId { - uint32_t value; + size_t value; // some overloads for comparision bool operator== (const LoanId &rhs) const { return value == rhs.value; } bool operator!= (const LoanId &rhs) const { return !(operator== (rhs)); } @@ -204,6 +204,9 @@ template <typename I, typename T> class IndexVec { std::vector<T> internal_vector; + typedef decltype (std::declval<I> ().value) size_type; + static constexpr auto MAX_INDEX = std::numeric_limits<size_type>::max (); + public: IndexVec () = default; IndexVec (size_t size) { internal_vector.reserve (size); } @@ -214,12 +217,16 @@ public: const T &operator[] (I pid) const { return internal_vector[pid.value]; } void push_back (T &¶m) { internal_vector.push_back (std::move (param)); } - template <typename... Args> void emplace_back (Args &&... args) + template <typename... Args> void emplace_back (Args &&...args) { internal_vector.emplace_back (std::forward<Args> (args)...); } - size_t size () const { return internal_vector.size (); } + size_type size () const + { + rust_assert (internal_vector.size () < MAX_INDEX); + return static_cast<size_type> (internal_vector.size ()); + } std::vector<T> &get_vector () { return internal_vector; } }; @@ -418,8 +425,7 @@ public: if (lookup != INVALID_PLACE) return lookup; - add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty}); - return {places.size () - 1}; + return add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty}); }; template <typename FN> void for_each_path_from_root (PlaceId var, FN fn) const @@ -465,14 +471,16 @@ private: case TyTy::FNDEF: case TyTy::NEVER: return true; - case TyTy::TUPLE: { + case TyTy::TUPLE: + { auto &fields = ty->as<TyTy::TupleType> ()->get_fields (); return std::all_of (fields.begin (), fields.end (), [] (const TyTy::TyVar &field) { return is_type_copy (field.get_tyty ()); }); } - case TyTy::ARRAY: { + case TyTy::ARRAY: + { return is_type_copy (ty->as<TyTy::ArrayType> ()->get_element_type ()); } case TyTy::INFER: @@ -485,6 +493,7 @@ private: case TyTy::PROJECTION: // TODO: DUNNO case TyTy::CLOSURE: // TODO: DUNNO case TyTy::DYNAMIC: // TODO: dunno + case TyTy::CONST: case TyTy::OPAQUE: return false; } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h index 5dac89e..d405569 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h @@ -51,7 +51,7 @@ template <typename BASE, typename T> class VisitableImpl : public BASE { public: template <typename... Args> - explicit VisitableImpl (Args &&... args) : BASE (std::forward<Args> (args)...) + explicit VisitableImpl (Args &&...args) : BASE (std::forward<Args> (args)...) {} void accept_vis (Visitor &visitor) override diff --git a/gcc/rust/checks/errors/borrowck/rust-bir.h b/gcc/rust/checks/errors/borrowck/rust-bir.h index e90e508..8a5f7be 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir.h @@ -35,6 +35,26 @@ using BasicBlocks = IndexVec<BasicBlockId, BasicBlock>; class Statement; class AbstractExpr; +/** Unique identifier for a basic block in the BIR. */ +struct BasicBlockId +{ + uint32_t value; + // some overloads for comparision + bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; } + bool operator!= (const BasicBlockId &rhs) const + { + return !(operator== (rhs)); + } + bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; } + bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; } + bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); } + bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); } +}; + +static constexpr BasicBlockId INVALID_BB + = {std::numeric_limits<uint32_t>::max ()}; +static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0}; + /** * Top-level entity of the Borrow-checker IR (BIR). * It represents a single function (method, closure, etc.), which is the @@ -132,26 +152,6 @@ public: WARN_UNUSED_RESULT location_t get_location () const { return location; } }; -/** Unique identifier for a basic block in the BIR. */ -struct BasicBlockId -{ - uint32_t value; - // some overloads for comparision - bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; } - bool operator!= (const BasicBlockId &rhs) const - { - return !(operator== (rhs)); - } - bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; } - bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; } - bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); } - bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); } -}; - -static constexpr BasicBlockId INVALID_BB - = {std::numeric_limits<uint32_t>::max ()}; -static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0}; - struct BasicBlock { // BIR "instructions". diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc index 6c67706..adf1448 100644 --- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc +++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc @@ -142,7 +142,7 @@ BorrowCheckerDiagnostics::get_statement (Polonius::Point point) const BIR::Loan & BorrowCheckerDiagnostics::get_loan (Polonius::Loan loan) { - return bir_function.place_db.get_loans ()[{loan}]; + return bir_function.place_db.get_loans ()[{(uint32_t) loan}]; } const HIR::LifetimeParam * diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h index cdb20e8..63f2a95 100644 --- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h @@ -19,6 +19,7 @@ #ifndef RUST_HIR_FUNCTION_COLLECTOR_H #define RUST_HIR_FUNCTION_COLLECTOR_H +#include "rust-hir-expr.h" #include "rust-hir-item.h" #include "rust-hir-visitor.h" #include "rust-hir.h" @@ -104,6 +105,8 @@ public: void visit (HIR::MethodCallExpr &expr) override {} void visit (HIR::FieldAccessExpr &expr) override {} void visit (HIR::BlockExpr &expr) override {} + void visit (HIR::AnonConst &expr) override {} + void visit (HIR::ConstBlock &expr) override {} void visit (HIR::ContinueExpr &expr) override {} void visit (HIR::BreakExpr &expr) override {} void visit (HIR::RangeFromToExpr &expr) override {} @@ -123,6 +126,8 @@ public: void visit (HIR::AwaitExpr &expr) override {} void visit (HIR::AsyncBlockExpr &expr) override {} void visit (HIR::InlineAsm &expr) override {} + void visit (HIR::LlvmInlineAsm &expr) override {} + void visit (HIR::OffsetOf &expr) override {} void visit (HIR::TypeParam ¶m) override {} void visit (HIR::ConstGenericParam ¶m) override {} void visit (HIR::LifetimeWhereClauseItem &item) override {} @@ -165,12 +170,14 @@ public: void visit (HIR::StructPatternFieldIdentPat &field) override {} void visit (HIR::StructPatternFieldIdent &field) override {} void visit (HIR::StructPattern &pattern) override {} - void visit (HIR::TupleStructItemsNoRange &tuple_items) override {} - void visit (HIR::TupleStructItemsRange &tuple_items) override {} + void visit (HIR::TupleStructItemsNoRest &tuple_items) override {} + void visit (HIR::TupleStructItemsHasRest &tuple_items) override {} void visit (HIR::TupleStructPattern &pattern) override {} - void visit (HIR::TuplePatternItemsMultiple &tuple_items) override {} - void visit (HIR::TuplePatternItemsRanged &tuple_items) override {} + void visit (HIR::TuplePatternItemsNoRest &tuple_items) override {} + void visit (HIR::TuplePatternItemsHasRest &tuple_items) override {} void visit (HIR::TuplePattern &pattern) override {} + void visit (HIR::SlicePatternItemsNoRest &tuple_items) override {} + void visit (HIR::SlicePatternItemsHasRest &tuple_items) override {} void visit (HIR::SlicePattern &pattern) override {} void visit (HIR::AltPattern &pattern) override {} void visit (HIR::EmptyStmt &stmt) override {} diff --git a/gcc/rust/checks/errors/feature/contrib/.gitignore b/gcc/rust/checks/errors/feature/contrib/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/.gitignore @@ -0,0 +1 @@ +/build diff --git a/gcc/rust/checks/errors/feature/contrib/Makefile b/gcc/rust/checks/errors/feature/contrib/Makefile new file mode 100644 index 0000000..7c828ab --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/Makefile @@ -0,0 +1,59 @@ +# Copyright (C) 2025 Free Software Foundation, Inc. + +# This file is part of GCC. + +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. + +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +OUT = ../rust-feature-defs.h + +all: $(OUT) + +mk-build-dir: + mkdir -p build + +build/parse.c: parse.y mk-build-dir + $(YACC) $(YFLAGS) -o $@ --defines=build/parse.h $< + +build/parse.h: build/parse.c; + +build/scan.c: scan.l + $(LEX) $(LFLAGS) -o $@ -Ca --header-file=build/scan.h $< + +build/scan.h: build/scan.c; + +build/%.o: build/%.c build/parse.h build/scan.h + $(CC) $(CFLAGS) -c -Ibuild -o $@ $< + +build/feature-extract: build/parse.o build/scan.o + $(CC) $(LDFLAGS) $(LDLIBS) -o $@ $^ + +build/download.rs: fetch + ./$< $@ + +$(OUT): build/feature-extract build/download.rs + # add copyright header + newline + echo | \ + cat copyright-stub.h - | \ + sed "s/YYYY/$$(date +%Y)/" > build/rust-feature-defs.h + cat build/download.rs | ./$< >> build/rust-feature-defs.h + clang-format -i build/rust-feature-defs.h \ + --style=file:../../../../../../contrib/clang-format + mv build/rust-feature-defs.h $(OUT) + +clean: + $(RM) -r build + +clean-all: clean + $(RM) $(OUT) diff --git a/gcc/rust/checks/errors/feature/contrib/README b/gcc/rust/checks/errors/feature/contrib/README new file mode 100644 index 0000000..e85fe09 --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/README @@ -0,0 +1,3 @@ +This program is intended for use in generating rust-feature-defs.h + +To use, run `./regen` diff --git a/gcc/rust/checks/errors/feature/contrib/copyright-stub.h b/gcc/rust/checks/errors/feature/contrib/copyright-stub.h new file mode 100644 index 0000000..1a5f52c --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/copyright-stub.h @@ -0,0 +1,19 @@ +// Copyright (C) YYYY Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// AUTO-GENERATED -- SEE LOCAL contrib SUBDIRECTORY diff --git a/gcc/rust/checks/errors/feature/contrib/fetch b/gcc/rust/checks/errors/feature/contrib/fetch new file mode 100755 index 0000000..b26ed3c --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/fetch @@ -0,0 +1,30 @@ +#!/bin/sh + +# Copyright (C) 2025 Free Software Foundation, Inc. + +# This file is part of GCC. + +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. + +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +RUST_VERSION="1.49.0" + +[ $# = 1 ] || exit 1 + +# Fetches files from the official rustc git repository + +URL_PREFIX='https://raw.githubusercontent.com/rust-lang/rust/refs/tags' +URL_TEMPLATE="$URL_PREFIX/$RUST_VERSION/compiler/rustc_feature/src" + +wget -O $1 "$URL_TEMPLATE"/{accepted,active,removed}.rs diff --git a/gcc/rust/checks/errors/feature/contrib/parse.y b/gcc/rust/checks/errors/feature/contrib/parse.y new file mode 100644 index 0000000..34c0138 --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/parse.y @@ -0,0 +1,143 @@ +/* Copyright (C) 2025 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +%{ + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +int yylex (void); +void yyerror (char const *); + +#include "scan.h" + +// expands to three %s parameters +#define UNWRAP_OPT_STR(prefix, s) (s ? prefix "_SOME (" : prefix "_NONE"), (s ? s : ""), (s ? ")" : "") + +%} + +%union +{ + char *str; +}; + +%token <str> IDENT STR NUM +%token SCOPE +%token K_SOME K_NONE +%token K_ACTIVE K_ACCEPTED K_REMOVED K_STABLE_REMOVED +%token K_E_START K_E_2018 + +%type <str> issue +%type <str> edition +%type <str> reason + +%% + +multi_database: multi_database database +| database +; + +database: '(' entry_list ')'; + +entry_list: entry_list entry ',' +| entry ',' +; + +entry: '(' K_ACTIVE ',' IDENT ',' STR ',' issue ',' edition ')' { + char *ident_upper = strdup ($4); + for (size_t i = 0; ident_upper[i]; i++) + ident_upper[i] = toupper (ident_upper[i]); + printf ("FEATURE_ACTIVE (\"%s\", %s, %s, %s%s%s, EDITION_%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8), $10 ? $10 : "NONE"); + free ($4); + free (ident_upper); + free ($6); + free ($8); +} +| '(' K_ACCEPTED ',' IDENT ',' STR ',' issue ',' K_NONE ')' { + char *ident_upper = strdup ($4); + for (size_t i = 0; ident_upper[i]; i++) + ident_upper[i] = toupper (ident_upper[i]); + printf ("FEATURE_ACCEPTED (\"%s\", %s, %s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8)); + free ($4); + free (ident_upper); + free ($6); + free ($8); +} +| '(' K_REMOVED ',' IDENT ',' STR ',' issue ',' K_NONE ',' reason ')' { + char *ident_upper; + // HACK: convert no_debug to F_NO_DEBUG instead + // since NO_DEBUG is used as an unrelated macro + if (!strcmp ($4, "no_debug")) + { + ident_upper = strdup ("F_NO_DEBUG"); + } + else + { + ident_upper = strdup ($4); + for (size_t i = 0; ident_upper[i]; i++) + ident_upper[i] = toupper (ident_upper[i]); + } + printf ("FEATURE_REMOVED (\"%s\", %s, %s, %s%s%s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8), UNWRAP_OPT_STR ("REASON", $12)); + free ($4); + free (ident_upper); + free ($6); + free ($8); + free ($12); +} +| '(' K_STABLE_REMOVED ',' IDENT ',' STR ',' issue ',' K_NONE ')' { + char *ident_upper = strdup ($4); + for (size_t i = 0; ident_upper[i]; i++) + ident_upper[i] = toupper (ident_upper[i]); + printf ("FEATURE_STABLE_REMOVED (\"%s\", %s, %s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8)); + free ($4); + free (ident_upper); + free ($6); + free ($8); +} +; + +issue: K_SOME '(' NUM ')' { $$ = $3; } +| K_NONE { $$ = NULL; } +; + +/* TODO: expand this as needed */ +edition: K_NONE { $$ = NULL; } +| K_SOME '(' K_E_START SCOPE K_E_2018 ')' { $$ = "2018"; } +; + +reason: K_SOME '(' STR ')' { $$ = $3; } +| K_NONE { $$ = NULL; } +; + +%% + +void yyerror (const char *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int yywrap (void) +{ + return 1; +} + +int main (void) +{ + return yyparse (); +} diff --git a/gcc/rust/checks/errors/feature/contrib/regen b/gcc/rust/checks/errors/feature/contrib/regen new file mode 100755 index 0000000..0dc6cc5 --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/regen @@ -0,0 +1,23 @@ +#!/bin/sh + +# Copyright (C) 2025 Free Software Foundation, Inc. + +# This file is part of GCC. + +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. + +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +cd "$(dirname "$0")" +rm -f ../rust-feature-defs.h +make all diff --git a/gcc/rust/checks/errors/feature/contrib/scan.l b/gcc/rust/checks/errors/feature/contrib/scan.l new file mode 100644 index 0000000..768f4c7 --- /dev/null +++ b/gcc/rust/checks/errors/feature/contrib/scan.l @@ -0,0 +1,55 @@ +/* Copyright (C) 2025 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +%{ + +#include "parse.h" + +static int p_count = 0; + +%} + +%x INSIDE COMMENT + +%% + +declare_features! BEGIN (INSIDE); +.|\n /* ignore */ + +<INSIDE>\( p_count++; return '('; +<INSIDE>\) if (!--p_count) { BEGIN (0); } return ')'; +<INSIDE>, return ','; +<INSIDE>:: return SCOPE; +<INSIDE>Some return K_SOME; +<INSIDE>None return K_NONE; +<INSIDE>active return K_ACTIVE; +<INSIDE>accepted return K_ACCEPTED; +<INSIDE>removed return K_REMOVED; +<INSIDE>stable_removed return K_STABLE_REMOVED; +<INSIDE>Edition return K_E_START; +<INSIDE>Edition2018 return K_E_2018; + +<INSIDE>[A-Za-z_][A-Za-z0-9_]* yylval.str = strdup (yytext); return IDENT; +<INSIDE>[1-9][0-9]* yylval.str = strdup (yytext); return NUM; +<INSIDE>\"[^"]+\" yylval.str = strdup (yytext); return STR; +<INSIDE>"/""/" BEGIN (COMMENT); +<INSIDE>[ \n] /* ignore */ +<INSIDE>. { fprintf (stderr, "unrecognized character %u\n", (unsigned int) yytext[0]); exit (1); } + +<COMMENT>. /* skip */ +<COMMENT>\n BEGIN (INSIDE); diff --git a/gcc/rust/checks/errors/feature/rust-feature-defs.h b/gcc/rust/checks/errors/feature/rust-feature-defs.h new file mode 100644 index 0000000..d8514e1 --- /dev/null +++ b/gcc/rust/checks/errors/feature/rust-feature-defs.h @@ -0,0 +1,600 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// AUTO-GENERATED -- SEE LOCAL contrib SUBDIRECTORY + +FEATURE_ACCEPTED ("issue_5723_bootstrap", ISSUE_5723_BOOTSTRAP, "1.0.0", + ISSUE_NONE) +FEATURE_ACCEPTED ("test_accepted_feature", TEST_ACCEPTED_FEATURE, "1.0.0", + ISSUE_NONE) +FEATURE_ACCEPTED ("associated_types", ASSOCIATED_TYPES, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("default_type_params", DEFAULT_TYPE_PARAMS, "1.0.0", + ISSUE_NONE) +FEATURE_ACCEPTED ("globs", GLOBS, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("macro_rules", MACRO_RULES, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("slicing_syntax", SLICING_SYNTAX, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("struct_variant", STRUCT_VARIANT, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("tuple_indexing", TUPLE_INDEXING, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("if_let", IF_LET, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("while_let", WHILE_LET, "1.0.0", ISSUE_NONE) +FEATURE_ACCEPTED ("no_std", NO_STD, "1.6.0", ISSUE_NONE) +FEATURE_ACCEPTED ("augmented_assignments", AUGMENTED_ASSIGNMENTS, "1.8.0", + ISSUE_SOME (28235)) +FEATURE_ACCEPTED ("braced_empty_structs", BRACED_EMPTY_STRUCTS, "1.8.0", + ISSUE_SOME (29720)) +FEATURE_ACCEPTED ("deprecated", DEPRECATED, "1.9.0", ISSUE_SOME (29935)) +FEATURE_ACCEPTED ("type_macros", TYPE_MACROS, "1.13.0", ISSUE_SOME (27245)) +FEATURE_ACCEPTED ("question_mark", QUESTION_MARK, "1.13.0", ISSUE_SOME (31436)) +FEATURE_ACCEPTED ("dotdot_in_tuple_patterns", DOTDOT_IN_TUPLE_PATTERNS, + "1.14.0", ISSUE_SOME (33627)) +FEATURE_ACCEPTED ("item_like_imports", ITEM_LIKE_IMPORTS, "1.15.0", + ISSUE_SOME (35120)) +FEATURE_ACCEPTED ("more_struct_aliases", MORE_STRUCT_ALIASES, "1.16.0", + ISSUE_SOME (37544)) +FEATURE_ACCEPTED ("static_in_const", STATIC_IN_CONST, "1.17.0", + ISSUE_SOME (35897)) +FEATURE_ACCEPTED ("field_init_shorthand", FIELD_INIT_SHORTHAND, "1.17.0", + ISSUE_SOME (37340)) +FEATURE_ACCEPTED ("static_recursion", STATIC_RECURSION, "1.17.0", + ISSUE_SOME (29719)) +FEATURE_ACCEPTED ("pub_restricted", PUB_RESTRICTED, "1.18.0", + ISSUE_SOME (32409)) +FEATURE_ACCEPTED ("windows_subsystem", WINDOWS_SUBSYSTEM, "1.18.0", + ISSUE_SOME (37499)) +FEATURE_ACCEPTED ("loop_break_value", LOOP_BREAK_VALUE, "1.19.0", + ISSUE_SOME (37339)) +FEATURE_ACCEPTED ("relaxed_adts", RELAXED_ADTS, "1.19.0", ISSUE_SOME (35626)) +FEATURE_ACCEPTED ("closure_to_fn_coercion", CLOSURE_TO_FN_COERCION, "1.19.0", + ISSUE_SOME (39817)) +FEATURE_ACCEPTED ("struct_field_attributes", STRUCT_FIELD_ATTRIBUTES, "1.20.0", + ISSUE_SOME (38814)) +FEATURE_ACCEPTED ("associated_consts", ASSOCIATED_CONSTS, "1.20.0", + ISSUE_SOME (29646)) +FEATURE_ACCEPTED ("compile_error", COMPILE_ERROR, "1.20.0", ISSUE_SOME (40872)) +FEATURE_ACCEPTED ("rvalue_static_promotion", RVALUE_STATIC_PROMOTION, "1.21.0", + ISSUE_SOME (38865)) +FEATURE_ACCEPTED ("drop_types_in_const", DROP_TYPES_IN_CONST, "1.22.0", + ISSUE_SOME (33156)) +FEATURE_ACCEPTED ("abi_sysv64", ABI_SYSV64, "1.24.0", ISSUE_SOME (36167)) +FEATURE_ACCEPTED ("repr_align", REPR_ALIGN, "1.25.0", ISSUE_SOME (33626)) +FEATURE_ACCEPTED ("match_beginning_vert", MATCH_BEGINNING_VERT, "1.25.0", + ISSUE_SOME (44101)) +FEATURE_ACCEPTED ("use_nested_groups", USE_NESTED_GROUPS, "1.25.0", + ISSUE_SOME (44494)) +FEATURE_ACCEPTED ("const_indexing", CONST_INDEXING, "1.26.0", + ISSUE_SOME (29947)) +FEATURE_ACCEPTED ("inclusive_range_syntax", INCLUSIVE_RANGE_SYNTAX, "1.26.0", + ISSUE_SOME (28237)) +FEATURE_ACCEPTED ("dotdoteq_in_patterns", DOTDOTEQ_IN_PATTERNS, "1.26.0", + ISSUE_SOME (28237)) +FEATURE_ACCEPTED ("termination_trait", TERMINATION_TRAIT, "1.26.0", + ISSUE_SOME (43301)) +FEATURE_ACCEPTED ("clone_closures", CLONE_CLOSURES, "1.26.0", + ISSUE_SOME (44490)) +FEATURE_ACCEPTED ("copy_closures", COPY_CLOSURES, "1.26.0", ISSUE_SOME (44490)) +FEATURE_ACCEPTED ("universal_impl_trait", UNIVERSAL_IMPL_TRAIT, "1.26.0", + ISSUE_SOME (34511)) +FEATURE_ACCEPTED ("conservative_impl_trait", CONSERVATIVE_IMPL_TRAIT, "1.26.0", + ISSUE_SOME (34511)) +FEATURE_ACCEPTED ("i128_type", I128_TYPE, "1.26.0", ISSUE_SOME (35118)) +FEATURE_ACCEPTED ("match_default_bindings", MATCH_DEFAULT_BINDINGS, "1.26.0", + ISSUE_SOME (42640)) +FEATURE_ACCEPTED ("underscore_lifetimes", UNDERSCORE_LIFETIMES, "1.26.0", + ISSUE_SOME (44524)) +FEATURE_ACCEPTED ("generic_param_attrs", GENERIC_PARAM_ATTRS, "1.27.0", + ISSUE_SOME (48848)) +FEATURE_ACCEPTED ("cfg_target_feature", CFG_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (29717)) +FEATURE_ACCEPTED ("target_feature", TARGET_FEATURE, "1.27.0", ISSUE_NONE) +FEATURE_ACCEPTED ("dyn_trait", DYN_TRAIT, "1.27.0", ISSUE_SOME (44662)) +FEATURE_ACCEPTED ("fn_must_use", FN_MUST_USE, "1.27.0", ISSUE_SOME (43302)) +FEATURE_ACCEPTED ("macro_lifetime_matcher", MACRO_LIFETIME_MATCHER, "1.27.0", + ISSUE_SOME (34303)) +FEATURE_ACCEPTED ("termination_trait_test", TERMINATION_TRAIT_TEST, "1.27.0", + ISSUE_SOME (48854)) +FEATURE_ACCEPTED ("global_allocator", GLOBAL_ALLOCATOR, "1.28.0", + ISSUE_SOME (27389)) +FEATURE_ACCEPTED ("repr_transparent", REPR_TRANSPARENT, "1.28.0", + ISSUE_SOME (43036)) +FEATURE_ACCEPTED ("proc_macro", PROC_MACRO, "1.29.0", ISSUE_SOME (38356)) +FEATURE_ACCEPTED ("non_modrs_mods", NON_MODRS_MODS, "1.30.0", + ISSUE_SOME (44660)) +FEATURE_ACCEPTED ("macro_vis_matcher", MACRO_VIS_MATCHER, "1.30.0", + ISSUE_SOME (41022)) +FEATURE_ACCEPTED ("use_extern_macros", USE_EXTERN_MACROS, "1.30.0", + ISSUE_SOME (35896)) +FEATURE_ACCEPTED ("raw_identifiers", RAW_IDENTIFIERS, "1.30.0", + ISSUE_SOME (48589)) +FEATURE_ACCEPTED ("tool_attributes", TOOL_ATTRIBUTES, "1.30.0", + ISSUE_SOME (44690)) +FEATURE_ACCEPTED ("proc_macro_path_invoc", PROC_MACRO_PATH_INVOC, "1.30.0", + ISSUE_SOME (38356)) +FEATURE_ACCEPTED ("attr_literals", ATTR_LITERALS, "1.30.0", ISSUE_SOME (34981)) +FEATURE_ACCEPTED ("infer_outlives_requirements", INFER_OUTLIVES_REQUIREMENTS, + "1.30.0", ISSUE_SOME (44493)) +FEATURE_ACCEPTED ("panic_handler", PANIC_HANDLER, "1.30.0", ISSUE_SOME (44489)) +FEATURE_ACCEPTED ("used", USED, "1.30.0", ISSUE_SOME (40289)) +FEATURE_ACCEPTED ("crate_in_paths", CRATE_IN_PATHS, "1.30.0", + ISSUE_SOME (45477)) +FEATURE_ACCEPTED ("extern_absolute_paths", EXTERN_ABSOLUTE_PATHS, "1.30.0", + ISSUE_SOME (44660)) +FEATURE_ACCEPTED ("extern_prelude", EXTERN_PRELUDE, "1.30.0", + ISSUE_SOME (44660)) +FEATURE_ACCEPTED ("pattern_parentheses", PATTERN_PARENTHESES, "1.31.0", + ISSUE_SOME (51087)) +FEATURE_ACCEPTED ("min_const_fn", MIN_CONST_FN, "1.31.0", ISSUE_SOME (53555)) +FEATURE_ACCEPTED ("tool_lints", TOOL_LINTS, "1.31.0", ISSUE_SOME (44690)) +FEATURE_ACCEPTED ("impl_header_lifetime_elision", IMPL_HEADER_LIFETIME_ELISION, + "1.31.0", ISSUE_SOME (15872)) +FEATURE_ACCEPTED ("extern_crate_item_prelude", EXTERN_CRATE_ITEM_PRELUDE, + "1.31.0", ISSUE_SOME (55599)) +FEATURE_ACCEPTED ("macro_literal_matcher", MACRO_LITERAL_MATCHER, "1.32.0", + ISSUE_SOME (35625)) +FEATURE_ACCEPTED ("macro_at_most_once_rep", MACRO_AT_MOST_ONCE_REP, "1.32.0", + ISSUE_SOME (48075)) +FEATURE_ACCEPTED ("self_struct_ctor", SELF_STRUCT_CTOR, "1.32.0", + ISSUE_SOME (51994)) +FEATURE_ACCEPTED ("self_in_typedefs", SELF_IN_TYPEDEFS, "1.32.0", + ISSUE_SOME (49303)) +FEATURE_ACCEPTED ("uniform_paths", UNIFORM_PATHS, "1.32.0", ISSUE_SOME (53130)) +FEATURE_ACCEPTED ("exhaustive_integer_patterns", EXHAUSTIVE_INTEGER_PATTERNS, + "1.33.0", ISSUE_SOME (50907)) +FEATURE_ACCEPTED ("underscore_imports", UNDERSCORE_IMPORTS, "1.33.0", + ISSUE_SOME (48216)) +FEATURE_ACCEPTED ("repr_packed", REPR_PACKED, "1.33.0", ISSUE_SOME (33158)) +FEATURE_ACCEPTED ("irrefutable_let_patterns", IRREFUTABLE_LET_PATTERNS, + "1.33.0", ISSUE_SOME (44495)) +FEATURE_ACCEPTED ("min_const_unsafe_fn", MIN_CONST_UNSAFE_FN, "1.33.0", + ISSUE_SOME (55607)) +FEATURE_ACCEPTED ("const_let", CONST_LET, "1.33.0", ISSUE_SOME (48821)) +FEATURE_ACCEPTED ("cfg_attr_multi", CFG_ATTR_MULTI, "1.33.0", + ISSUE_SOME (54881)) +FEATURE_ACCEPTED ("if_while_or_patterns", IF_WHILE_OR_PATTERNS, "1.33.0", + ISSUE_SOME (48215)) +FEATURE_ACCEPTED ("cfg_target_vendor", CFG_TARGET_VENDOR, "1.33.0", + ISSUE_SOME (29718)) +FEATURE_ACCEPTED ("extern_crate_self", EXTERN_CRATE_SELF, "1.34.0", + ISSUE_SOME (56409)) +FEATURE_ACCEPTED ("unrestricted_attribute_tokens", + UNRESTRICTED_ATTRIBUTE_TOKENS, "1.34.0", ISSUE_SOME (55208)) +FEATURE_ACCEPTED ("type_alias_enum_variants", TYPE_ALIAS_ENUM_VARIANTS, + "1.37.0", ISSUE_SOME (49683)) +FEATURE_ACCEPTED ("repr_align_enum", REPR_ALIGN_ENUM, "1.37.0", + ISSUE_SOME (57996)) +FEATURE_ACCEPTED ("underscore_const_names", UNDERSCORE_CONST_NAMES, "1.37.0", + ISSUE_SOME (54912)) +FEATURE_ACCEPTED ("async_await", ASYNC_AWAIT, "1.39.0", ISSUE_SOME (50547)) +FEATURE_ACCEPTED ("bind_by_move_pattern_guards", BIND_BY_MOVE_PATTERN_GUARDS, + "1.39.0", ISSUE_SOME (15287)) +FEATURE_ACCEPTED ("param_attrs", PARAM_ATTRS, "1.39.0", ISSUE_SOME (60406)) +FEATURE_ACCEPTED ("macros_in_extern", MACROS_IN_EXTERN, "1.40.0", + ISSUE_SOME (49476)) +FEATURE_ACCEPTED ("non_exhaustive", NON_EXHAUSTIVE, "1.40.0", + ISSUE_SOME (44109)) +FEATURE_ACCEPTED ("const_constructor", CONST_CONSTRUCTOR, "1.40.0", + ISSUE_SOME (61456)) +FEATURE_ACCEPTED ("cfg_doctest", CFG_DOCTEST, "1.40.0", ISSUE_SOME (62210)) +FEATURE_ACCEPTED ("re_rebalance_coherence", RE_REBALANCE_COHERENCE, "1.41.0", + ISSUE_SOME (55437)) +FEATURE_ACCEPTED ("transparent_enums", TRANSPARENT_ENUMS, "1.42.0", + ISSUE_SOME (60405)) +FEATURE_ACCEPTED ("slice_patterns", SLICE_PATTERNS, "1.42.0", + ISSUE_SOME (62254)) +FEATURE_ACCEPTED ("const_if_match", CONST_IF_MATCH, "1.46.0", + ISSUE_SOME (49146)) +FEATURE_ACCEPTED ("const_loop", CONST_LOOP, "1.46.0", ISSUE_SOME (52000)) +FEATURE_ACCEPTED ("track_caller", TRACK_CALLER, "1.46.0", ISSUE_SOME (47809)) +FEATURE_ACCEPTED ("doc_alias", DOC_ALIAS, "1.48.0", ISSUE_SOME (50146)) +FEATURE_ACCEPTED ("move_ref_pattern", MOVE_REF_PATTERN, "1.48.0", + ISSUE_SOME (68354)) +FEATURE_ACTIVE ("rustc_attrs", RUSTC_ATTRS, "1.0.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("rustc_private", RUSTC_PRIVATE, "1.0.0", ISSUE_SOME (27812), + EDITION_NONE) +FEATURE_ACTIVE ("intrinsics", INTRINSICS, "1.0.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("lang_items", LANG_ITEMS, "1.0.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("staged_api", STAGED_API, "1.0.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("allow_internal_unstable", ALLOW_INTERNAL_UNSTABLE, "1.0.0", + ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("allow_internal_unsafe", ALLOW_INTERNAL_UNSAFE, "1.0.0", + ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("link_llvm_intrinsics", LINK_LLVM_INTRINSICS, "1.0.0", + ISSUE_SOME (29602), EDITION_NONE) +FEATURE_ACTIVE ("box_syntax", BOX_SYNTAX, "1.0.0", ISSUE_SOME (49733), + EDITION_NONE) +FEATURE_ACTIVE ("main", MAIN, "1.0.0", ISSUE_SOME (29634), EDITION_NONE) +FEATURE_ACTIVE ("start", START, "1.0.0", ISSUE_SOME (29633), EDITION_NONE) +FEATURE_ACTIVE ("fundamental", FUNDAMENTAL, "1.0.0", ISSUE_SOME (29635), + EDITION_NONE) +FEATURE_ACTIVE ("unboxed_closures", UNBOXED_CLOSURES, "1.0.0", + ISSUE_SOME (29625), EDITION_NONE) +FEATURE_ACTIVE ("linkage", LINKAGE, "1.0.0", ISSUE_SOME (29603), EDITION_NONE) +FEATURE_ACTIVE ("optin_builtin_traits", OPTIN_BUILTIN_TRAITS, "1.0.0", + ISSUE_SOME (13231), EDITION_NONE) +FEATURE_ACTIVE ("box_patterns", BOX_PATTERNS, "1.0.0", ISSUE_SOME (29641), + EDITION_NONE) +FEATURE_ACTIVE ("prelude_import", PRELUDE_IMPORT, "1.2.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("omit_gdb_pretty_printer_section", + OMIT_GDB_PRETTY_PRINTER_SECTION, "1.5.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("abi_vectorcall", ABI_VECTORCALL, "1.7.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("structural_match", STRUCTURAL_MATCH, "1.8.0", + ISSUE_SOME (31434), EDITION_NONE) +FEATURE_ACTIVE ("dropck_eyepatch", DROPCK_EYEPATCH, "1.10.0", + ISSUE_SOME (34761), EDITION_NONE) +FEATURE_ACTIVE ("panic_runtime", PANIC_RUNTIME, "1.10.0", ISSUE_SOME (32837), + EDITION_NONE) +FEATURE_ACTIVE ("needs_panic_runtime", NEEDS_PANIC_RUNTIME, "1.10.0", + ISSUE_SOME (32837), EDITION_NONE) +FEATURE_ACTIVE ("compiler_builtins", COMPILER_BUILTINS, "1.13.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("abi_unadjusted", ABI_UNADJUSTED, "1.16.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("profiler_runtime", PROFILER_RUNTIME, "1.18.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("abi_thiscall", ABI_THISCALL, "1.19.0", ISSUE_NONE, + EDITION_NONE) +FEATURE_ACTIVE ("allocator_internals", ALLOCATOR_INTERNALS, "1.20.0", + ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("test_2018_feature", TEST_2018_FEATURE, "1.31.0", ISSUE_NONE, + EDITION_2018) +FEATURE_ACTIVE ("no_niche", NO_NICHE, "1.42.0", ISSUE_NONE, EDITION_NONE) +FEATURE_ACTIVE ("rustc_allow_const_fn_unstable", RUSTC_ALLOW_CONST_FN_UNSTABLE, + "1.49.0", ISSUE_SOME (69399), EDITION_NONE) +FEATURE_ACTIVE ("arm_target_feature", ARM_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("aarch64_target_feature", AARCH64_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("hexagon_target_feature", HEXAGON_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("powerpc_target_feature", POWERPC_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("mips_target_feature", MIPS_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("avx512_target_feature", AVX512_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("sse4a_target_feature", SSE4A_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("tbm_target_feature", TBM_TARGET_FEATURE, "1.27.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("wasm_target_feature", WASM_TARGET_FEATURE, "1.30.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("adx_target_feature", ADX_TARGET_FEATURE, "1.32.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("cmpxchg16b_target_feature", CMPXCHG16B_TARGET_FEATURE, + "1.32.0", ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("movbe_target_feature", MOVBE_TARGET_FEATURE, "1.34.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("rtm_target_feature", RTM_TARGET_FEATURE, "1.35.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("f16c_target_feature", F16C_TARGET_FEATURE, "1.36.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("riscv_target_feature", RISCV_TARGET_FEATURE, "1.45.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("ermsb_target_feature", ERMSB_TARGET_FEATURE, "1.49.0", + ISSUE_SOME (44839), EDITION_NONE) +FEATURE_ACTIVE ("link_args", LINK_ARGS, "1.0.0", ISSUE_SOME (29596), + EDITION_NONE) +FEATURE_ACTIVE ("non_ascii_idents", NON_ASCII_IDENTS, "1.0.0", + ISSUE_SOME (55467), EDITION_NONE) +FEATURE_ACTIVE ("plugin_registrar", PLUGIN_REGISTRAR, "1.0.0", + ISSUE_SOME (29597), EDITION_NONE) +FEATURE_ACTIVE ("plugin", PLUGIN, "1.0.0", ISSUE_SOME (29597), EDITION_NONE) +FEATURE_ACTIVE ("thread_local", THREAD_LOCAL, "1.0.0", ISSUE_SOME (29594), + EDITION_NONE) +FEATURE_ACTIVE ("simd_ffi", SIMD_FFI, "1.0.0", ISSUE_SOME (27731), EDITION_NONE) +FEATURE_ACTIVE ("nll", NLL, "1.0.0", ISSUE_SOME (43234), EDITION_NONE) +FEATURE_ACTIVE ("const_fn", CONST_FN, "1.2.0", ISSUE_SOME (57563), EDITION_NONE) +FEATURE_ACTIVE ("associated_type_defaults", ASSOCIATED_TYPE_DEFAULTS, "1.2.0", + ISSUE_SOME (29661), EDITION_NONE) +FEATURE_ACTIVE ("no_core", NO_CORE, "1.3.0", ISSUE_SOME (29639), EDITION_NONE) +FEATURE_ACTIVE ("default_type_parameter_fallback", + DEFAULT_TYPE_PARAMETER_FALLBACK, "1.3.0", ISSUE_SOME (27336), + EDITION_NONE) +FEATURE_ACTIVE ("repr_simd", REPR_SIMD, "1.4.0", ISSUE_SOME (27731), + EDITION_NONE) +FEATURE_ACTIVE ("platform_intrinsics", PLATFORM_INTRINSICS, "1.4.0", + ISSUE_SOME (27731), EDITION_NONE) +FEATURE_ACTIVE ("unwind_attributes", UNWIND_ATTRIBUTES, "1.4.0", + ISSUE_SOME (58760), EDITION_NONE) +FEATURE_ACTIVE ("stmt_expr_attributes", STMT_EXPR_ATTRIBUTES, "1.6.0", + ISSUE_SOME (15701), EDITION_NONE) +FEATURE_ACTIVE ("type_ascription", TYPE_ASCRIPTION, "1.6.0", ISSUE_SOME (23416), + EDITION_NONE) +FEATURE_ACTIVE ("cfg_target_thread_local", CFG_TARGET_THREAD_LOCAL, "1.7.0", + ISSUE_SOME (29594), EDITION_NONE) +FEATURE_ACTIVE ("specialization", SPECIALIZATION, "1.7.0", ISSUE_SOME (31844), + EDITION_NONE) +FEATURE_ACTIVE ("min_specialization", MIN_SPECIALIZATION, "1.7.0", + ISSUE_SOME (31844), EDITION_NONE) +FEATURE_ACTIVE ("naked_functions", NAKED_FUNCTIONS, "1.9.0", ISSUE_SOME (32408), + EDITION_NONE) +FEATURE_ACTIVE ("cfg_target_has_atomic", CFG_TARGET_HAS_ATOMIC, "1.9.0", + ISSUE_SOME (32976), EDITION_NONE) +FEATURE_ACTIVE ("exclusive_range_pattern", EXCLUSIVE_RANGE_PATTERN, "1.11.0", + ISSUE_SOME (37854), EDITION_NONE) +FEATURE_ACTIVE ("never_type", NEVER_TYPE, "1.13.0", ISSUE_SOME (35121), + EDITION_NONE) +FEATURE_ACTIVE ("exhaustive_patterns", EXHAUSTIVE_PATTERNS, "1.13.0", + ISSUE_SOME (51085), EDITION_NONE) +FEATURE_ACTIVE ("untagged_unions", UNTAGGED_UNIONS, "1.13.0", + ISSUE_SOME (55149), EDITION_NONE) +FEATURE_ACTIVE ("link_cfg", LINK_CFG, "1.14.0", ISSUE_SOME (37406), + EDITION_NONE) +FEATURE_ACTIVE ("abi_ptx", ABI_PTX, "1.15.0", ISSUE_SOME (38788), EDITION_NONE) +FEATURE_ACTIVE ("repr128", REPR128, "1.16.0", ISSUE_SOME (56071), EDITION_NONE) +FEATURE_ACTIVE ("static_nobundle", STATIC_NOBUNDLE, "1.16.0", + ISSUE_SOME (37403), EDITION_NONE) +FEATURE_ACTIVE ("abi_msp430_interrupt", ABI_MSP430_INTERRUPT, "1.16.0", + ISSUE_SOME (38487), EDITION_NONE) +FEATURE_ACTIVE ("decl_macro", DECL_MACRO, "1.17.0", ISSUE_SOME (39412), + EDITION_NONE) +FEATURE_ACTIVE ("abi_x86_interrupt", ABI_X86_INTERRUPT, "1.17.0", + ISSUE_SOME (40180), EDITION_NONE) +FEATURE_ACTIVE ("allow_fail", ALLOW_FAIL, "1.19.0", ISSUE_SOME (46488), + EDITION_NONE) +FEATURE_ACTIVE ("unsized_tuple_coercion", UNSIZED_TUPLE_COERCION, "1.20.0", + ISSUE_SOME (42877), EDITION_NONE) +FEATURE_ACTIVE ("generators", GENERATORS, "1.21.0", ISSUE_SOME (43122), + EDITION_NONE) +FEATURE_ACTIVE ("doc_cfg", DOC_CFG, "1.21.0", ISSUE_SOME (43781), EDITION_NONE) +FEATURE_ACTIVE ("doc_masked", DOC_MASKED, "1.21.0", ISSUE_SOME (44027), + EDITION_NONE) +FEATURE_ACTIVE ("doc_spotlight", DOC_SPOTLIGHT, "1.22.0", ISSUE_SOME (45040), + EDITION_NONE) +FEATURE_ACTIVE ("external_doc", EXTERNAL_DOC, "1.22.0", ISSUE_SOME (44732), + EDITION_NONE) +FEATURE_ACTIVE ("crate_visibility_modifier", CRATE_VISIBILITY_MODIFIER, + "1.23.0", ISSUE_SOME (53120), EDITION_NONE) +FEATURE_ACTIVE ("extern_types", EXTERN_TYPES, "1.23.0", ISSUE_SOME (43467), + EDITION_NONE) +FEATURE_ACTIVE ("arbitrary_self_types", ARBITRARY_SELF_TYPES, "1.23.0", + ISSUE_SOME (44874), EDITION_NONE) +FEATURE_ACTIVE ("in_band_lifetimes", IN_BAND_LIFETIMES, "1.23.0", + ISSUE_SOME (44524), EDITION_NONE) +FEATURE_ACTIVE ("generic_associated_types", GENERIC_ASSOCIATED_TYPES, "1.23.0", + ISSUE_SOME (44265), EDITION_NONE) +FEATURE_ACTIVE ("trait_alias", TRAIT_ALIAS, "1.24.0", ISSUE_SOME (41517), + EDITION_NONE) +FEATURE_ACTIVE ("infer_static_outlives_requirements", + INFER_STATIC_OUTLIVES_REQUIREMENTS, "1.26.0", + ISSUE_SOME (54185), EDITION_NONE) +FEATURE_ACTIVE ("const_fn_union", CONST_FN_UNION, "1.27.0", ISSUE_SOME (51909), + EDITION_NONE) +FEATURE_ACTIVE ("const_raw_ptr_to_usize_cast", CONST_RAW_PTR_TO_USIZE_CAST, + "1.27.0", ISSUE_SOME (51910), EDITION_NONE) +FEATURE_ACTIVE ("const_raw_ptr_deref", CONST_RAW_PTR_DEREF, "1.27.0", + ISSUE_SOME (51911), EDITION_NONE) +FEATURE_ACTIVE ("trivial_bounds", TRIVIAL_BOUNDS, "1.28.0", ISSUE_SOME (48214), + EDITION_NONE) +FEATURE_ACTIVE ("label_break_value", LABEL_BREAK_VALUE, "1.28.0", + ISSUE_SOME (48594), EDITION_NONE) +FEATURE_ACTIVE ("doc_keyword", DOC_KEYWORD, "1.28.0", ISSUE_SOME (51315), + EDITION_NONE) +FEATURE_ACTIVE ("try_blocks", TRY_BLOCKS, "1.29.0", ISSUE_SOME (31436), + EDITION_NONE) +FEATURE_ACTIVE ("alloc_error_handler", ALLOC_ERROR_HANDLER, "1.29.0", + ISSUE_SOME (51540), EDITION_NONE) +FEATURE_ACTIVE ("abi_amdgpu_kernel", ABI_AMDGPU_KERNEL, "1.29.0", + ISSUE_SOME (51575), EDITION_NONE) +FEATURE_ACTIVE ("const_panic", CONST_PANIC, "1.30.0", ISSUE_SOME (51999), + EDITION_NONE) +FEATURE_ACTIVE ("marker_trait_attr", MARKER_TRAIT_ATTR, "1.30.0", + ISSUE_SOME (29864), EDITION_NONE) +FEATURE_ACTIVE ("proc_macro_hygiene", PROC_MACRO_HYGIENE, "1.30.0", + ISSUE_SOME (54727), EDITION_NONE) +FEATURE_ACTIVE ("unsized_locals", UNSIZED_LOCALS, "1.30.0", ISSUE_SOME (48055), + EDITION_NONE) +FEATURE_ACTIVE ("custom_test_frameworks", CUSTOM_TEST_FRAMEWORKS, "1.30.0", + ISSUE_SOME (50297), EDITION_NONE) +FEATURE_ACTIVE ("custom_inner_attributes", CUSTOM_INNER_ATTRIBUTES, "1.30.0", + ISSUE_SOME (54726), EDITION_NONE) +FEATURE_ACTIVE ("impl_trait_in_bindings", IMPL_TRAIT_IN_BINDINGS, "1.30.0", + ISSUE_SOME (63065), EDITION_NONE) +FEATURE_ACTIVE ("lint_reasons", LINT_REASONS, "1.31.0", ISSUE_SOME (54503), + EDITION_NONE) +FEATURE_ACTIVE ("precise_pointer_size_matching", PRECISE_POINTER_SIZE_MATCHING, + "1.32.0", ISSUE_SOME (56354), EDITION_NONE) +FEATURE_ACTIVE ("ffi_returns_twice", FFI_RETURNS_TWICE, "1.34.0", + ISSUE_SOME (58314), EDITION_NONE) +FEATURE_ACTIVE ("const_generics", CONST_GENERICS, "1.34.0", ISSUE_SOME (44580), + EDITION_NONE) +FEATURE_ACTIVE ("optimize_attribute", OPTIMIZE_ATTRIBUTE, "1.34.0", + ISSUE_SOME (54882), EDITION_NONE) +FEATURE_ACTIVE ("c_variadic", C_VARIADIC, "1.34.0", ISSUE_SOME (44930), + EDITION_NONE) +FEATURE_ACTIVE ("associated_type_bounds", ASSOCIATED_TYPE_BOUNDS, "1.34.0", + ISSUE_SOME (52662), EDITION_NONE) +FEATURE_ACTIVE ("let_chains", LET_CHAINS, "1.37.0", ISSUE_SOME (53667), + EDITION_NONE) +FEATURE_ACTIVE ("transparent_unions", TRANSPARENT_UNIONS, "1.37.0", + ISSUE_SOME (60405), EDITION_NONE) +FEATURE_ACTIVE ("arbitrary_enum_discriminant", ARBITRARY_ENUM_DISCRIMINANT, + "1.37.0", ISSUE_SOME (60553), EDITION_NONE) +FEATURE_ACTIVE ("member_constraints", MEMBER_CONSTRAINTS, "1.37.0", + ISSUE_SOME (61997), EDITION_NONE) +FEATURE_ACTIVE ("async_closure", ASYNC_CLOSURE, "1.37.0", ISSUE_SOME (62290), + EDITION_NONE) +FEATURE_ACTIVE ("const_in_array_repeat_expressions", + CONST_IN_ARRAY_REPEAT_EXPRESSIONS, "1.37.0", ISSUE_SOME (49147), + EDITION_NONE) +FEATURE_ACTIVE ("type_alias_impl_trait", TYPE_ALIAS_IMPL_TRAIT, "1.38.0", + ISSUE_SOME (63063), EDITION_NONE) +FEATURE_ACTIVE ("or_patterns", OR_PATTERNS, "1.38.0", ISSUE_SOME (54883), + EDITION_NONE) +FEATURE_ACTIVE ("const_extern_fn", CONST_EXTERN_FN, "1.40.0", + ISSUE_SOME (64926), EDITION_NONE) +FEATURE_ACTIVE ("raw_dylib", RAW_DYLIB, "1.40.0", ISSUE_SOME (58713), + EDITION_NONE) +FEATURE_ACTIVE ("object_safe_for_dispatch", OBJECT_SAFE_FOR_DISPATCH, "1.40.0", + ISSUE_SOME (43561), EDITION_NONE) +FEATURE_ACTIVE ("abi_efiapi", ABI_EFIAPI, "1.40.0", ISSUE_SOME (65815), + EDITION_NONE) +FEATURE_ACTIVE ("raw_ref_op", RAW_REF_OP, "1.41.0", ISSUE_SOME (64490), + EDITION_NONE) +FEATURE_ACTIVE ("never_type_fallback", NEVER_TYPE_FALLBACK, "1.41.0", + ISSUE_SOME (65992), EDITION_NONE) +FEATURE_ACTIVE ("register_attr", REGISTER_ATTR, "1.41.0", ISSUE_SOME (66080), + EDITION_NONE) +FEATURE_ACTIVE ("register_tool", REGISTER_TOOL, "1.41.0", ISSUE_SOME (66079), + EDITION_NONE) +FEATURE_ACTIVE ("cfg_sanitize", CFG_SANITIZE, "1.41.0", ISSUE_SOME (39699), + EDITION_NONE) +FEATURE_ACTIVE ("half_open_range_patterns", HALF_OPEN_RANGE_PATTERNS, "1.41.0", + ISSUE_SOME (67264), EDITION_NONE) +FEATURE_ACTIVE ("const_mut_refs", CONST_MUT_REFS, "1.41.0", ISSUE_SOME (57349), + EDITION_NONE) +FEATURE_ACTIVE ("bindings_after_at", BINDINGS_AFTER_AT, "1.41.0", + ISSUE_SOME (65490), EDITION_NONE) +FEATURE_ACTIVE ("const_trait_impl", CONST_TRAIT_IMPL, "1.42.0", + ISSUE_SOME (67792), EDITION_NONE) +FEATURE_ACTIVE ("const_trait_bound_opt_out", CONST_TRAIT_BOUND_OPT_OUT, + "1.42.0", ISSUE_SOME (67794), EDITION_NONE) +FEATURE_ACTIVE ("no_sanitize", NO_SANITIZE, "1.42.0", ISSUE_SOME (39699), + EDITION_NONE) +FEATURE_ACTIVE ("const_eval_limit", CONST_EVAL_LIMIT, "1.43.0", + ISSUE_SOME (67217), EDITION_NONE) +FEATURE_ACTIVE ("negative_impls", NEGATIVE_IMPLS, "1.44.0", ISSUE_SOME (68318), + EDITION_NONE) +FEATURE_ACTIVE ("target_feature_11", TARGET_FEATURE_11, "1.45.0", + ISSUE_SOME (69098), EDITION_NONE) +FEATURE_ACTIVE ("cfg_version", CFG_VERSION, "1.45.0", ISSUE_SOME (64796), + EDITION_NONE) +FEATURE_ACTIVE ("ffi_pure", FFI_PURE, "1.45.0", ISSUE_SOME (58329), + EDITION_NONE) +FEATURE_ACTIVE ("ffi_const", FFI_CONST, "1.45.0", ISSUE_SOME (58328), + EDITION_NONE) +FEATURE_ACTIVE ("unsafe_block_in_unsafe_fn", UNSAFE_BLOCK_IN_UNSAFE_FN, + "1.45.0", ISSUE_SOME (71668), EDITION_NONE) +FEATURE_ACTIVE ("abi_avr_interrupt", ABI_AVR_INTERRUPT, "1.45.0", + ISSUE_SOME (69664), EDITION_NONE) +FEATURE_ACTIVE ("const_precise_live_drops", CONST_PRECISE_LIVE_DROPS, "1.46.0", + ISSUE_SOME (73255), EDITION_NONE) +FEATURE_ACTIVE ("format_args_capture", FORMAT_ARGS_CAPTURE, "1.46.0", + ISSUE_SOME (67984), EDITION_NONE) +FEATURE_ACTIVE ("lazy_normalization_consts", LAZY_NORMALIZATION_CONSTS, + "1.46.0", ISSUE_SOME (72219), EDITION_NONE) +FEATURE_ACTIVE ("const_fn_transmute", CONST_FN_TRANSMUTE, "1.46.0", + ISSUE_SOME (53605), EDITION_NONE) +FEATURE_ACTIVE ("min_const_generics", MIN_CONST_GENERICS, "1.47.0", + ISSUE_SOME (74878), EDITION_NONE) +FEATURE_ACTIVE ("if_let_guard", IF_LET_GUARD, "1.47.0", ISSUE_SOME (51114), + EDITION_NONE) +FEATURE_ACTIVE ("const_evaluatable_checked", CONST_EVALUATABLE_CHECKED, + "1.48.0", ISSUE_SOME (76560), EDITION_NONE) +FEATURE_ACTIVE ("const_fn_floating_point_arithmetic", + CONST_FN_FLOATING_POINT_ARITHMETIC, "1.48.0", + ISSUE_SOME (57241), EDITION_NONE) +FEATURE_ACTIVE ("const_fn_fn_ptr_basics", CONST_FN_FN_PTR_BASICS, "1.48.0", + ISSUE_SOME (57563), EDITION_NONE) +FEATURE_ACTIVE ("cmse_nonsecure_entry", CMSE_NONSECURE_ENTRY, "1.48.0", + ISSUE_SOME (75835), EDITION_NONE) +FEATURE_ACTIVE ("default_alloc_error_handler", DEFAULT_ALLOC_ERROR_HANDLER, + "1.48.0", ISSUE_SOME (66741), EDITION_NONE) +FEATURE_ACTIVE ("const_impl_trait", CONST_IMPL_TRAIT, "1.48.0", + ISSUE_SOME (77463), EDITION_NONE) +FEATURE_ACTIVE ("isa_attribute", ISA_ATTRIBUTE, "1.48.0", ISSUE_SOME (74727), + EDITION_NONE) +FEATURE_ACTIVE ("inline_const", INLINE_CONST, "1.49.0", ISSUE_SOME (76001), + EDITION_NONE) +FEATURE_ACTIVE ("unsized_fn_params", UNSIZED_FN_PARAMS, "1.49.0", + ISSUE_SOME (48055), EDITION_NONE) +FEATURE_ACTIVE ("destructuring_assignment", DESTRUCTURING_ASSIGNMENT, "1.49.0", + ISSUE_SOME (71126), EDITION_NONE) +FEATURE_ACTIVE ("cfg_panic", CFG_PANIC, "1.49.0", ISSUE_SOME (77443), + EDITION_NONE) +FEATURE_REMOVED ("import_shadowing", IMPORT_SHADOWING, "1.0.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("managed_boxes", MANAGED_BOXES, "1.0.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("negate_unsigned", NEGATE_UNSIGNED, "1.0.0", + ISSUE_SOME (29645), REASON_NONE) +FEATURE_REMOVED ("reflect", REFLECT, "1.0.0", ISSUE_SOME (27749), REASON_NONE) +FEATURE_REMOVED ("opt_out_copy", OPT_OUT_COPY, "1.0.0", ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("quad_precision_float", QUAD_PRECISION_FLOAT, "1.0.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("struct_inherit", STRUCT_INHERIT, "1.0.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("test_removed_feature", TEST_REMOVED_FEATURE, "1.0.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("visible_private_types", VISIBLE_PRIVATE_TYPES, "1.0.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("unsafe_no_drop_flag", UNSAFE_NO_DROP_FLAG, "1.0.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("unmarked_api", UNMARKED_API, "1.0.0", ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("allocator", ALLOCATOR, "1.0.0", ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("simd", SIMD, "1.0.0", ISSUE_SOME (27731), + REASON_SOME ("removed in favor of `#[repr(simd)]`")) +FEATURE_REMOVED ("advanced_slice_patterns", ADVANCED_SLICE_PATTERNS, "1.0.0", + ISSUE_SOME (62254), + REASON_SOME ("merged into `#![feature(slice_patterns)]`")) +FEATURE_REMOVED ("macro_reexport", MACRO_REEXPORT, "1.0.0", ISSUE_SOME (29638), + REASON_SOME ("subsumed by `pub use`")) +FEATURE_REMOVED ( + "custom_attribute", CUSTOM_ATTRIBUTE, "1.0.0", ISSUE_SOME (29642), + REASON_SOME ( + "removed in favor of `#![register_tool]` and `#![register_attr]`")) +FEATURE_REMOVED ("pushpop_unsafe", PUSHPOP_UNSAFE, "1.2.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("needs_allocator", NEEDS_ALLOCATOR, "1.4.0", + ISSUE_SOME (27389), + REASON_SOME ("subsumed by `#![feature(allocator_internals)]`")) +FEATURE_REMOVED ("sanitizer_runtime", SANITIZER_RUNTIME, "1.17.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ("proc_macro_mod", PROC_MACRO_MOD, "1.27.0", ISSUE_SOME (54727), + REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`")) +FEATURE_REMOVED ("proc_macro_expr", PROC_MACRO_EXPR, "1.27.0", + ISSUE_SOME (54727), + REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`")) +FEATURE_REMOVED ("proc_macro_non_items", PROC_MACRO_NON_ITEMS, "1.27.0", + ISSUE_SOME (54727), + REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`")) +FEATURE_REMOVED ("proc_macro_gen", PROC_MACRO_GEN, "1.27.0", ISSUE_SOME (54727), + REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`")) +FEATURE_REMOVED ("panic_implementation", PANIC_IMPLEMENTATION, "1.28.0", + ISSUE_SOME (44489), + REASON_SOME ("subsumed by `#[panic_handler]`")) +FEATURE_REMOVED ("custom_derive", CUSTOM_DERIVE, "1.32.0", ISSUE_SOME (29644), + REASON_SOME ("subsumed by `#[proc_macro_derive]`")) +FEATURE_REMOVED ("extern_in_paths", EXTERN_IN_PATHS, "1.33.0", + ISSUE_SOME (55600), + REASON_SOME ("subsumed by `::foo::bar` paths")) +FEATURE_REMOVED ("quote", QUOTE, "1.33.0", ISSUE_SOME (29601), REASON_NONE) +FEATURE_REMOVED ("dropck_parametricity", DROPCK_PARAMETRICITY, "1.38.0", + ISSUE_SOME (28498), REASON_NONE) +FEATURE_REMOVED ("await_macro", AWAIT_MACRO, "1.38.0", ISSUE_SOME (50547), + REASON_SOME ("subsumed by `.await` syntax")) +FEATURE_REMOVED ( + "existential_type", EXISTENTIAL_TYPE, "1.38.0", ISSUE_SOME (63063), + REASON_SOME ("removed in favor of `#![feature(type_alias_impl_trait)]`")) +FEATURE_REMOVED ("rustc_diagnostic_macros", RUSTC_DIAGNOSTIC_MACROS, "1.38.0", + ISSUE_NONE, REASON_NONE) +FEATURE_REMOVED ("on_unimplemented", ON_UNIMPLEMENTED, "1.40.0", ISSUE_NONE, + REASON_NONE) +FEATURE_REMOVED ( + "overlapping_marker_traits", OVERLAPPING_MARKER_TRAITS, "1.42.0", + ISSUE_SOME (29864), + REASON_SOME ("removed in favor of `#![feature(marker_trait_attr)]`")) +FEATURE_REMOVED ("no_debug", F_NO_DEBUG, "1.43.0", ISSUE_SOME (29721), + REASON_SOME ("removed due to lack of demand")) +FEATURE_REMOVED ( + "const_compare_raw_pointers", CONST_COMPARE_RAW_POINTERS, "1.46.0", + ISSUE_SOME (53020), + REASON_SOME ("cannot be allowed in const eval in any meaningful way")) +FEATURE_STABLE_REMOVED ("no_stack_check", NO_STACK_CHECK, "1.0.0", ISSUE_NONE) diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/feature/rust-feature-gate.cc index f3daa61..9df822b 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.cc +++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc @@ -34,12 +34,22 @@ 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) { if (attr.get_path ().as_string () == "feature") { + // check for empty feature, such as `#![feature], this is an error + if (attr.empty_input ()) + { + rust_error_at (attr.get_locus (), ErrorCode::E0556, + "malformed %<feature%> attribute input"); + continue; + } const auto &attr_input = attr.get_attr_input (); auto type = attr_input.get_attr_input_type (); if (type == AST::AttrInput::AttrInputType::TOKEN_TREE) @@ -51,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 (); @@ -140,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 @@ -151,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); } @@ -177,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); } @@ -236,4 +335,32 @@ FeatureGate::visit (AST::UseTreeGlob &use) // #[feature(prelude_import)] } +void +FeatureGate::visit (AST::StructStruct &struct_item) +{ + check_lang_item_attribute (struct_item.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (struct_item); +} + +void +FeatureGate::visit (AST::TraitItemType &trait_item_type) +{ + check_lang_item_attribute (trait_item_type.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (trait_item_type); +} + +void +FeatureGate::visit (AST::Enum &enum_item) +{ + check_lang_item_attribute (enum_item.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (enum_item); +} + +void +FeatureGate::visit (AST::EnumItem &enum_variant) +{ + check_lang_item_attribute (enum_variant.get_outer_attrs ()); + AST::DefaultASTVisitor::visit (enum_variant); +} + } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/feature/rust-feature-gate.h index f1011e5..8ff491c 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.h +++ b/gcc/rust/checks/errors/feature/rust-feature-gate.h @@ -47,13 +47,30 @@ public: void visit (AST::ExternBlock &block) override; void visit (AST::MacroRulesDefinition &rules_def) override; void visit (AST::RangePattern &pattern) override; + void visit (AST::StructStruct &struct_item) override; + void visit (AST::TraitItemType &trait_item_type) override; + void visit (AST::Enum &enum_item) override; + void visit (AST::EnumItem &enum_variant) override; private: void gate (Feature::Name name, location_t loc, const std::string &error_msg); void check_rustc_attri (const std::vector<AST::Attribute> &attributes); void check_may_dangle_attribute (const std::vector<AST::Attribute> &attributes); - std::set<Feature::Name> valid_features; + void + check_lang_item_attribute (const std::vector<AST::Attribute> &attributes); + void note_stability_attribute (const std::vector<AST::Attribute> &attributes); + + std::set<Feature::Name> valid_lang_features; + std::map<std::string, location_t> valid_lib_features; + + enum class Stability + { + STABLE, + UNSTABLE, + }; + + std::map<std::string, Stability> defined_lib_features; }; } // namespace Rust #endif diff --git a/gcc/rust/checks/errors/feature/rust-feature.cc b/gcc/rust/checks/errors/feature/rust-feature.cc new file mode 100644 index 0000000..1a967aa --- /dev/null +++ b/gcc/rust/checks/errors/feature/rust-feature.cc @@ -0,0 +1,100 @@ +// Copyright (C) 2020-2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-feature.h" + +namespace Rust { + +Feature Feature::feature_list[] = { +#define ISSUE_SOME(n) n +#define ISSUE_NONE tl::nullopt +#define EDITION_2018 Edition::E2018 +#define EDITION_NONE tl::nullopt +#define REASON_SOME(r) r +#define REASON_NONE tl::nullopt + +#define FEATURE_BASE(state, name_str, name, rust_since, issue, ...) \ + Feature (Feature::Name::name, Feature::State::state, name_str, rust_since, \ + issue, __VA_ARGS__), + +#define FEATURE_ACTIVE(a, b, c, d, edition) \ + FEATURE_BASE (ACTIVE, a, b, c, d, edition, tl::nullopt) + +#define FEATURE_ACCEPTED(a, b, c, d) \ + FEATURE_BASE (ACCEPTED, a, b, c, d, tl::nullopt, tl::nullopt) + +#define FEATURE_REMOVED(a, b, c, d, reason) \ + FEATURE_BASE (REMOVED, a, b, c, d, tl::nullopt, reason) + +#define FEATURE_STABLE_REMOVED(a, b, c, d) \ + FEATURE_BASE (ACCEPTED, a, b, c, d, tl::nullopt, tl::nullopt) + +#include "rust-feature-defs.h" + +#undef ISSUE_SOME +#undef ISSUE_NONE +#undef EDITION_2018 +#undef EDITION_NONE +#undef REASON_SOME +#undef REASON_NONE + +#undef FEATURE_BASE +#undef FEATURE_ACTIVE +#undef FEATURE_ACCEPTED +#undef FEATURE_REMOVED +#undef FEATURE_STABLE_REMOVED +}; + +const std::map<std::string, Feature::Name> Feature::name_hash_map = { +#define FEATURE(s, name, ...) {s, Feature::Name::name}, +#define FEATURE_ACTIVE(...) FEATURE (__VA_ARGS__) +#define FEATURE_ACCEPTED(...) FEATURE (__VA_ARGS__) +#define FEATURE_REMOVED(...) FEATURE (__VA_ARGS__) +#define FEATURE_STABLE_REMOVED(...) FEATURE (__VA_ARGS__) +#include "rust-feature-defs.h" +#undef FEATURE +#undef FEATURE_ACTIVE +#undef FEATURE_ACCEPTED +#undef FEATURE_REMOVED +#undef FEATURE_STABLE_REMOVED +}; + +tl::optional<Feature::Name> +Feature::as_name (const std::string &name) +{ + auto it = Feature::name_hash_map.find (name); + if (it == Feature::name_hash_map.end ()) + return tl::nullopt; + else + return it->second; +} + +tl::optional<std::reference_wrapper<const Feature>> +Feature::lookup (const std::string &name) +{ + return as_name (name).map ( + [] (Name n) { return std::ref (Feature::lookup (n)); }); +} + +const Feature & +Feature::lookup (Feature::Name name) +{ + return feature_list[static_cast<size_t> (name)]; +} + +} // namespace Rust diff --git a/gcc/rust/checks/errors/feature/rust-feature.h b/gcc/rust/checks/errors/feature/rust-feature.h new file mode 100644 index 0000000..8686cf4 --- /dev/null +++ b/gcc/rust/checks/errors/feature/rust-feature.h @@ -0,0 +1,85 @@ +// Copyright (C) 2020-2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_FEATURE_H +#define RUST_FEATURE_H + +#include "rust-edition.h" +#include "optional.h" + +namespace Rust { + +class Feature +{ +public: + enum class State + { + ACCEPTED, // stabilized + ACTIVE, // unstable + REMOVED, // removed + STABILIZED, // removed after stabilization + }; + + enum class Name + { +#define FEATURE_ACTIVE(x, name, ...) name, +#define FEATURE_ACCEPTED(x, name, ...) name, +#define FEATURE_REMOVED(x, name, ...) name, +#define FEATURE_STABLE_REMOVED(x, name, ...) name, +#include "rust-feature-defs.h" +#undef FEATURE_ACTIVE +#undef FEATURE_ACCEPTED +#undef FEATURE_REMOVED +#undef FEATURE_STABLE_REMOVED + }; + + const std::string &as_string () const { return m_name_str; } + + Name name () const { return m_name; } + State state () const { return m_state; } + tl::optional<unsigned> issue () const { return m_issue; } + + static tl::optional<Name> as_name (const std::string &name); + + static tl::optional<std::reference_wrapper<const Feature>> + lookup (const std::string &name); + static const Feature &lookup (Name name); + +private: + Feature (Name name, State state, const char *name_str, const char *rust_since, + tl::optional<unsigned> issue_number, tl::optional<Edition> edition, + tl::optional<const char *> reason) + : m_name (name), m_state (state), m_name_str (name_str), + m_rust_since (rust_since), m_issue (issue_number), edition (edition), + m_reason (reason) + {} + + Name m_name; + State m_state; + std::string m_name_str; + std::string m_rust_since; + tl::optional<unsigned> m_issue; + tl::optional<Edition> edition; + tl::optional<const char *> m_reason; + + static Feature feature_list[]; + static const std::map<std::string, Name> name_hash_map; +}; + +} // namespace Rust +#endif diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc index 3d25459..90248d3 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc @@ -20,13 +20,12 @@ #include "rust-reachability.h" #include "rust-hir-type-check.h" #include "rust-hir-map.h" -#include "rust-name-resolver.h" +#include "rust-immutable-name-resolution-context.h" #include "rust-visibility-resolver.h" #include "rust-pub-restricted-visitor.h" #include "rust-privacy-reporter.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); namespace Rust { namespace Privacy { @@ -36,12 +35,13 @@ Resolver::resolve (HIR::Crate &crate) { PrivacyContext ctx; auto &mappings = Analysis::Mappings::get (); - auto resolver = Rust::Resolver::Resolver::get (); + auto &resolver + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get (); - VisibilityResolver (mappings, *resolver).go (crate); + VisibilityResolver (mappings, resolver).go (crate); PubRestrictedVisitor (mappings).go (crate); - PrivacyReporter (mappings, *resolver, *ty_ctx).go (crate); + PrivacyReporter (mappings, resolver, *ty_ctx).go (crate); auto visitor = ReachabilityVisitor (ctx, *ty_ctx); diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h index a506613f..9699ac4 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h @@ -71,8 +71,7 @@ private: #if CHECKING_P namespace selftest { -void -rust_privacy_ctx_test (void); +void rust_privacy_ctx_test (void); } #endif // !CHECKING_P diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index a537c42..c1a3d45 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -28,7 +28,8 @@ namespace Rust { namespace Privacy { PrivacyReporter::PrivacyReporter ( - Analysis::Mappings &mappings, Resolver::Resolver &resolver, + Analysis::Mappings &mappings, + const Resolver2_0::NameResolutionContext &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx) : mappings (mappings), resolver (resolver), ty_ctx (ty_ctx), current_module (tl::nullopt) @@ -90,59 +91,18 @@ PrivacyReporter::go (HIR::Crate &crate) } } -static bool -is_child_module (Analysis::Mappings &mappings, NodeId parent, - NodeId possible_child) -{ - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - return nr_ctx.values.is_module_descendant (parent, possible_child); - } - - auto children = mappings.lookup_module_children (parent); - - if (!children) - return false; - - // Visit all toplevel children - for (auto &child : *children) - if (child == possible_child) - return true; - - // Now descend recursively in the child module tree - for (auto &child : *children) - if (is_child_module (mappings, child, possible_child)) - return true; - - return false; -} - // FIXME: This function needs a lot of refactoring void PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, const location_t locus) { - NodeId ref_node_id = UNKNOWN_NODEID; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (use_id)) - ref_node_id = *id; - } - // FIXME: Don't assert here - we might be dealing with a type - else if (!resolver.lookup_resolved_name (use_id, &ref_node_id)) - resolver.lookup_resolved_type (use_id, &ref_node_id); + NodeId ref_node_id; // FIXME: Assert here. For now, we return since this causes issues when // checking inferred types (#1260) - // rust_assert (ref_node_id != UNKNOWN_NODEID); - if (ref_node_id == UNKNOWN_NODEID) + if (auto id = resolver.lookup (use_id)) + ref_node_id = *id; + else return; auto vis = mappings.lookup_visibility (ref_node_id); @@ -157,7 +117,8 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, { case ModuleVisibility::Public: break; - case ModuleVisibility::Restricted: { + case ModuleVisibility::Restricted: + { // If we are in the crate, everything is restricted correctly, but we // can't get a module for it if (!current_module.has_value ()) @@ -174,7 +135,9 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, // FIXME: This needs a LOT of TLC: hinting about the definition, a // string to say if it's a module, function, type, etc... - if (!is_child_module (mappings, mod_node_id, current_module.value ())) + + if (!resolver.values.is_module_descendant (mod_node_id, + current_module.value ())) valid = false; } break; @@ -215,12 +178,14 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings, case TyTy::USIZE: case TyTy::ISIZE: case TyTy::ADT: - case TyTy::STR: { + case TyTy::STR: + { auto ref_id = ty->get_ref (); if (auto lookup_id = mappings.lookup_hir_to_node (ref_id)) return check_for_privacy_violation (*lookup_id, locus); - rust_unreachable (); } + break; + case TyTy::REF: return recursive_check ( static_cast<const TyTy::ReferenceType *> (ty)->get_base ()); @@ -243,7 +208,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings, static_cast<const TyTy::TupleType *> (ty)->get_fields ()) recursive_check (param.get_tyty ()); return; - case TyTy::PLACEHOLDER: { + case TyTy::PLACEHOLDER: + { const auto p = static_cast<const TyTy::PlaceholderType *> (ty); if (!p->can_resolve ()) return; @@ -273,6 +239,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings, return; case TyTy::OPAQUE: return; + case TyTy::CONST: + return; case TyTy::ERROR: return; } @@ -306,6 +274,16 @@ PrivacyReporter::visit (HIR::InlineAsm &) {} void +PrivacyReporter::visit (HIR::LlvmInlineAsm &) +{} + +void +PrivacyReporter::visit (HIR::OffsetOf &expr) +{ + // TODO: Do we have to do anything? +} + +void PrivacyReporter::visit (HIR::TypePath &path) { check_for_privacy_violation (path.get_mappings ().get_nodeid (), @@ -409,7 +387,8 @@ PrivacyReporter::visit (HIR::ArrayExpr &expr) HIR::ArrayElems &elements = expr.get_internal_elements (); switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { auto &elems = static_cast<HIR::ArrayElemsValues &> (elements); for (auto &value : elems.get_values ()) value->accept_vis (*this); @@ -514,6 +493,18 @@ PrivacyReporter::visit (HIR::BlockExpr &expr) } void +PrivacyReporter::visit (HIR::AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +PrivacyReporter::visit (HIR::ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void PrivacyReporter::visit (HIR::ContinueExpr &) {} diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h index 5111a3e..d64b7a7 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h @@ -19,10 +19,12 @@ #ifndef RUST_PRIVACY_REPORTER_H #define RUST_PRIVACY_REPORTER_H +#include "rust-hir-expr.h" #include "rust-hir-map.h" #include "rust-hir-visitor.h" +#include "rust-hir-type-check.h" #include "rust-mapping-common.h" -#include "rust-name-resolver.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Privacy { @@ -37,7 +39,7 @@ class PrivacyReporter : public HIR::HIRExpressionVisitor, { public: PrivacyReporter (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver, + const Resolver2_0::NameResolutionContext &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx); /** @@ -106,6 +108,8 @@ types virtual void visit (HIR::MethodCallExpr &expr); virtual void visit (HIR::FieldAccessExpr &expr); virtual void visit (HIR::BlockExpr &expr); + virtual void visit (HIR::AnonConst &expr); + virtual void visit (HIR::ConstBlock &expr); virtual void visit (HIR::ContinueExpr &expr); virtual void visit (HIR::BreakExpr &expr); virtual void visit (HIR::RangeFromToExpr &expr); @@ -125,6 +129,8 @@ types virtual void visit (HIR::AwaitExpr &expr); virtual void visit (HIR::AsyncBlockExpr &expr); virtual void visit (HIR::InlineAsm &expr); + virtual void visit (HIR::LlvmInlineAsm &expr); + virtual void visit (HIR::OffsetOf &expr); virtual void visit (HIR::EnumItemTuple &); virtual void visit (HIR::EnumItemStruct &); @@ -152,7 +158,7 @@ types virtual void visit (HIR::ExprStmt &stmt); Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; const Rust::Resolver::TypeCheckContext &ty_ctx; // `None` means we're in the root module - the crate diff --git a/gcc/rust/checks/errors/privacy/rust-reachability.cc b/gcc/rust/checks/errors/privacy/rust-reachability.cc index 1e57674..223c77b 100644 --- a/gcc/rust/checks/errors/privacy/rust-reachability.cc +++ b/gcc/rust/checks/errors/privacy/rust-reachability.cc @@ -158,7 +158,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item) switch (variant->get_enum_item_kind ()) { - case HIR::EnumItem::Tuple: { + case HIR::EnumItem::Tuple: + { // Should we update the fields only if they are public? Similarly to // what we do in the ReachabilityVisitor for HIR::TupleStruct? auto tuple_variant @@ -167,7 +168,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item) ctx.update_reachability (field.get_mappings (), variant_reach); break; } - case HIR::EnumItem::Struct: { + case HIR::EnumItem::Struct: + { // Should we update the fields only if they are public? Similarly to // what we do in the ReachabilityVisitor for HIR::StructStruct? auto struct_variant diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc index f0da745..4240673 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc @@ -20,16 +20,14 @@ #include "rust-ast.h" #include "rust-hir.h" #include "rust-hir-item.h" -#include "rust-immutable-name-resolution-context.h" - -// for flag_name_resolution_2_0 -#include "options.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Privacy { -VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings, - Resolver::Resolver &resolver) +VisibilityResolver::VisibilityResolver ( + Analysis::Mappings &mappings, + const Resolver2_0::NameResolutionContext &resolver) : mappings (mappings), resolver (resolver) {} @@ -64,23 +62,12 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction, = Error (restriction.get_locus (), "cannot use non-module path as privacy restrictor"); - NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) + NodeId ref_node_id; + if (auto id = resolver.lookup (ast_node_id)) { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (ast_node_id)) - { - ref_node_id = *id; - } - else - { - invalid_path.emit (); - return false; - } + ref_node_id = *id; } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + else { invalid_path.emit (); return false; @@ -127,7 +114,8 @@ VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility, case HIR::Visibility::PUBLIC: to_resolve = ModuleVisibility::create_public (); return true; - case HIR::Visibility::RESTRICTED: { + case HIR::Visibility::RESTRICTED: + { // FIXME: We also need to handle 2015 vs 2018 edition conflicts auto id = UNKNOWN_DEFID; auto result = resolve_module_path (visibility.get_path (), id); diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h index 4dfba4c..ddd70a8 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h @@ -24,7 +24,7 @@ #include "rust-hir-stmt.h" #include "rust-hir-item.h" #include "rust-hir-map.h" -#include "rust-name-resolver.h" +#include "rust-name-resolution-context.h" #include "rust-hir-visitor.h" namespace Rust { @@ -34,7 +34,7 @@ class VisibilityResolver : public HIR::HIRVisItemVisitor { public: VisibilityResolver (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver); + const Resolver2_0::NameResolutionContext &resolver); /** * Perform visibility resolving on an entire crate @@ -93,7 +93,7 @@ public: private: Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; DefId current_module; }; diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc index 4904322..782d694 100644 --- a/gcc/rust/checks/errors/rust-const-checker.cc +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -417,6 +417,26 @@ ConstChecker::visit (BlockExpr &expr) } void +ConstChecker::visit (AnonConst &expr) +{ + const_context.enter (expr.get_mappings ().get_hirid ()); + + expr.get_inner_expr ().accept_vis (*this); + + const_context.exit (); +} + +void +ConstChecker::visit (ConstBlock &expr) +{ + const_context.enter (expr.get_mappings ().get_hirid ()); + + expr.get_const_expr ().accept_vis (*this); + + const_context.exit (); +} + +void ConstChecker::visit (ContinueExpr &) {} @@ -537,6 +557,14 @@ ConstChecker::visit (InlineAsm &) {} void +ConstChecker::visit (LlvmInlineAsm &) +{} + +void +ConstChecker::visit (OffsetOf &) +{} + +void ConstChecker::visit (TypeParam &) {} @@ -646,6 +674,9 @@ ConstChecker::visit (Enum &enum_item) { check_default_const_generics (enum_item.get_generic_params (), ConstGenericCtx::Enum); + + for (auto &item : enum_item.get_variants ()) + item->accept_vis (*this); } void @@ -782,11 +813,11 @@ ConstChecker::visit (StructPattern &) {} void -ConstChecker::visit (TupleStructItemsNoRange &) +ConstChecker::visit (TupleStructItemsNoRest &) {} void -ConstChecker::visit (TupleStructItemsRange &) +ConstChecker::visit (TupleStructItemsHasRest &) {} void @@ -794,11 +825,11 @@ ConstChecker::visit (TupleStructPattern &) {} void -ConstChecker::visit (TuplePatternItemsMultiple &) +ConstChecker::visit (TuplePatternItemsNoRest &) {} void -ConstChecker::visit (TuplePatternItemsRanged &) +ConstChecker::visit (TuplePatternItemsHasRest &) {} void @@ -806,6 +837,14 @@ ConstChecker::visit (TuplePattern &) {} void +ConstChecker::visit (SlicePatternItemsNoRest &) +{} + +void +ConstChecker::visit (SlicePatternItemsHasRest &) +{} + +void ConstChecker::visit (SlicePattern &) {} diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h index 00f57988..d464b7b 100644 --- a/gcc/rust/checks/errors/rust-const-checker.h +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -113,6 +113,8 @@ private: virtual void visit (FieldAccessExpr &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; virtual void visit (RangeFromToExpr &expr) override; @@ -132,6 +134,8 @@ private: virtual void visit (AwaitExpr &expr) override; virtual void visit (AsyncBlockExpr &expr) override; virtual void visit (InlineAsm &expr) override; + virtual void visit (LlvmInlineAsm &expr) override; + virtual void visit (OffsetOf &expr) override; virtual void visit (TypeParam ¶m) override; virtual void visit (ConstGenericParam ¶m) override; @@ -176,12 +180,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc deleted file mode 100644 index 25af46c..0000000 --- a/gcc/rust/checks/errors/rust-feature.cc +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-feature.h" - -namespace Rust { - -Feature -Feature::create (Feature::Name f) -{ - switch (f) - { - case Feature::Name::ASSOCIATED_TYPE_BOUNDS: - return Feature (Feature::Name::ASSOCIATED_TYPE_BOUNDS, - Feature::State::ACCEPTED, "associated_type_bounds", - "1.34.0", 52662); - case Feature::Name::INTRINSICS: - return Feature (f, Feature::State::ACCEPTED, "intrinsics", "1.0.0"); - case Feature::Name::RUSTC_ATTRS: - return Feature (f, Feature::State::ACCEPTED, "rustc_attrs", "1.0.0"); - case Feature::Name::DECL_MACRO: - return Feature (f, Feature::State::ACCEPTED, "decl_macro", "1.0.0", - 39412); - case Feature::Name::EXTERN_TYPES: - return Feature (f, Feature::State::ACTIVE, "extern_types", "1.23.0", - 43467); - case Feature::Name::NEGATIVE_IMPLS: - return Feature (f, Feature::State::ACTIVE, "negative_impls", "1.0.0", - 68318); - case Feature::Name::BOX_SYNTAX: - return Feature (f, Feature::State::ACTIVE, "box_syntax", "1.0.0", 49733); - case Feature::Name::DROPCK_EYEPATCH: - return Feature (f, Feature::State::ACTIVE, "dropck_eyepatch", "1.10.0", - 34761); - case Feature::Name::RAW_REF_OP: - return Feature (f, Feature::State::ACTIVE, "raw_ref_op", "1.41.0", 64490); - case Feature::Name::EXCLUSIVE_RANGE_PATTERN: - return Feature (Feature::Name::EXCLUSIVE_RANGE_PATTERN, - Feature::State::ACTIVE, "exclusive_range_pattern", - "1.11.0", 37854); - case Feature::Name::PRELUDE_IMPORT: - return Feature (f, Feature::State::ACTIVE, "prelude_import", "1.0.0"); - case Feature::Name::AUTO_TRAITS: - return Feature (f, Feature::State::ACTIVE, "optin_builtin_traits", - "1.0.0", 13231); - default: - rust_unreachable (); - } -} - -const std::map<std::string, Feature::Name> Feature::name_hash_map = { - {"associated_type_bounds", Feature::Name::ASSOCIATED_TYPE_BOUNDS}, - {"intrinsics", Feature::Name::INTRINSICS}, - {"rustc_attrs", Feature::Name::RUSTC_ATTRS}, - {"decl_macro", Feature::Name::DECL_MACRO}, - {"negative_impls", Feature::Name::NEGATIVE_IMPLS}, - // TODO: Rename to "auto_traits" when supporting - // later Rust versions - {"optin_builtin_traits", Feature::Name::AUTO_TRAITS}, - {"extern_types", Feature::Name::EXTERN_TYPES}, - {"lang_items", Feature::Name::LANG_ITEMS}, - {"no_core", Feature::Name::NO_CORE}, - {"box_syntax", Feature::Name::BOX_SYNTAX}, - {"dropck_eyepatch", Feature::Name::DROPCK_EYEPATCH}, - {"raw_ref_op", Feature::Name::RAW_REF_OP}, - {"exclusive_range_pattern", Feature::Name::EXCLUSIVE_RANGE_PATTERN}, - {"prelude_import", Feature::Name::PRELUDE_IMPORT}, -}; // namespace Rust - -tl::optional<Feature::Name> -Feature::as_name (const std::string &name) -{ - if (Feature::name_hash_map.count (name)) - return Feature::name_hash_map.at (name); - - return tl::nullopt; -} - -} // namespace Rust diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h deleted file mode 100644 index 9edae6d..0000000 --- a/gcc/rust/checks/errors/rust-feature.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_FEATURE_H -#define RUST_FEATURE_H - -#include "rust-edition.h" -#include "optional.h" - -namespace Rust { - -class Feature -{ -public: - enum class State - { - ACCEPTED, - ACTIVE, - REMOVED, - STABILIZED, - }; - - enum class Name - { - ASSOCIATED_TYPE_BOUNDS, - INTRINSICS, - NEGATIVE_IMPLS, - RUSTC_ATTRS, - DECL_MACRO, - AUTO_TRAITS, - EXTERN_TYPES, - LANG_ITEMS, - NO_CORE, - BOX_SYNTAX, - DROPCK_EYEPATCH, - RAW_REF_OP, - EXCLUSIVE_RANGE_PATTERN, - PRELUDE_IMPORT, - }; - - const std::string &as_string () { return m_name_str; } - Name name () { return m_name; } - const std::string &description () { return m_description; } - State state () { return m_state; } - tl::optional<unsigned> issue () { return m_issue; } - - static tl::optional<Name> as_name (const std::string &name); - static Feature create (Name name); - -private: - Feature (Name name, State state, const char *name_str, - const char *rustc_since, - tl::optional<unsigned> issue_number = tl::nullopt, - const tl::optional<Edition> &edition = tl::nullopt, - const char *description = "") - : m_state (state), m_name (name), m_name_str (name_str), - m_rustc_since (rustc_since), m_issue (issue_number), edition (edition), - m_description (description) - {} - - State m_state; - Name m_name; - std::string m_name_str; - std::string m_rustc_since; - tl::optional<unsigned> m_issue; - tl::optional<Edition> edition; - std::string m_description; // TODO: Switch to optional? - - static const std::map<std::string, Name> name_hash_map; -}; - -} // namespace Rust -#endif diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 257f4cd..f132e04 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -28,15 +28,12 @@ #include "rust-tyty.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Analysis { PatternChecker::PatternChecker () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()), + resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()), mappings (Analysis::Mappings::get ()) {} @@ -238,17 +235,9 @@ PatternChecker::visit (CallExpr &expr) NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid (); NodeId ref_node_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (ast_node_id)) - ref_node_id = *id; - else - return; - } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + if (auto id = resolver.lookup (ast_node_id)) + ref_node_id = *id; + else return; if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id)) @@ -295,6 +284,18 @@ PatternChecker::visit (BlockExpr &expr) } void +PatternChecker::visit (AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +PatternChecker::visit (ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void PatternChecker::visit (ContinueExpr &) {} @@ -423,6 +424,14 @@ PatternChecker::visit (InlineAsm &expr) {} void +PatternChecker::visit (LlvmInlineAsm &expr) +{} + +void +PatternChecker::visit (OffsetOf &expr) +{} + +void PatternChecker::visit (TypeParam &) {} @@ -620,11 +629,11 @@ PatternChecker::visit (StructPattern &) {} void -PatternChecker::visit (TupleStructItemsNoRange &) +PatternChecker::visit (TupleStructItemsNoRest &) {} void -PatternChecker::visit (TupleStructItemsRange &) +PatternChecker::visit (TupleStructItemsHasRest &) {} void @@ -632,11 +641,11 @@ PatternChecker::visit (TupleStructPattern &) {} void -PatternChecker::visit (TuplePatternItemsMultiple &) +PatternChecker::visit (TuplePatternItemsNoRest &) {} void -PatternChecker::visit (TuplePatternItemsRanged &) +PatternChecker::visit (TuplePatternItemsHasRest &) {} void @@ -644,6 +653,14 @@ PatternChecker::visit (TuplePattern &) {} void +PatternChecker::visit (SlicePatternItemsNoRest &) +{} + +void +PatternChecker::visit (SlicePatternItemsHasRest &) +{} + +void PatternChecker::visit (SlicePattern &) {} @@ -724,23 +741,27 @@ Constructor::is_covered_by (const Constructor &o) const switch (kind) { - case ConstructorKind::VARIANT: { + case ConstructorKind::VARIANT: + { rust_assert (kind == ConstructorKind::VARIANT); return variant_idx == o.variant_idx; } break; - case ConstructorKind::INT_RANGE: { + case ConstructorKind::INT_RANGE: + { rust_assert (kind == ConstructorKind::INT_RANGE); return int_range.lo >= o.int_range.lo && int_range.hi <= o.int_range.hi; } break; - case ConstructorKind::WILDCARD: { + case ConstructorKind::WILDCARD: + { // TODO: wildcard is covered by a variant of enum with a single // variant return false; } break; - case ConstructorKind::STRUCT: { + case ConstructorKind::STRUCT: + { // Struct pattern is always covered by a other struct constructor. return true; } @@ -896,19 +917,22 @@ PlaceInfo::specialize (const Constructor &c) const switch (c.get_kind ()) { case Constructor::ConstructorKind::WILDCARD: - case Constructor::ConstructorKind::INT_RANGE: { + case Constructor::ConstructorKind::INT_RANGE: + { return {}; } break; case Constructor::ConstructorKind::STRUCT: - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { rust_assert (ty->get_kind () == TyTy::TypeKind::ADT); TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty); switch (adt->get_adt_kind ()) { case TyTy::ADTType::ADTKind::ENUM: case TyTy::ADTType::ADTKind::STRUCT_STRUCT: - case TyTy::ADTType::ADTKind::TUPLE_STRUCT: { + case TyTy::ADTType::ADTKind::TUPLE_STRUCT: + { TyTy::VariantDef *variant = adt->get_variants ().at (c.get_variant_index ()); if (variant->get_variant_type () @@ -922,14 +946,16 @@ PlaceInfo::specialize (const Constructor &c) const return new_place_infos; } break; - case TyTy::ADTType::ADTKind::UNION: { + case TyTy::ADTType::ADTKind::UNION: + { // TODO: support unions rust_unreachable (); } } } break; - default: { + default: + { rust_unreachable (); } break; @@ -951,7 +977,7 @@ Matrix::specialize (const Constructor &ctor) const if (ctor.is_covered_by (hd.ctor ())) { pats.pop_head_constructor (ctor, subfields_place_info.size ()); - new_rows.push_back (MatrixRow (pats, row.is_under_guard ())); + new_rows.emplace_back (pats, row.is_under_guard ()); } } @@ -987,7 +1013,8 @@ WitnessPat::to_string () const { switch (ctor.get_kind ()) { - case Constructor::ConstructorKind::STRUCT: { + case Constructor::ConstructorKind::STRUCT: + { TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty); TyTy::VariantDef *variant = adt->get_variants ().at (ctor.get_variant_index ()); @@ -1012,7 +1039,8 @@ WitnessPat::to_string () const return buf; } break; - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { std::string buf; TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty); buf += adt->get_identifier (); @@ -1022,11 +1050,13 @@ WitnessPat::to_string () const switch (variant->get_variant_type ()) { - case TyTy::VariantDef::VariantType::NUM: { + case TyTy::VariantDef::VariantType::NUM: + { return buf; } break; - case TyTy::VariantDef::VariantType::TUPLE: { + case TyTy::VariantDef::VariantType::TUPLE: + { buf += "("; for (size_t i = 0; i < fields.size (); i++) { @@ -1038,7 +1068,8 @@ WitnessPat::to_string () const return buf; } break; - case TyTy::VariantDef::VariantType::STRUCT: { + case TyTy::VariantDef::VariantType::STRUCT: + { buf += " {"; if (!fields.empty ()) buf += " "; @@ -1057,7 +1088,8 @@ WitnessPat::to_string () const buf += "}"; } break; - default: { + default: + { rust_unreachable (); } break; @@ -1065,21 +1097,25 @@ WitnessPat::to_string () const return buf; } break; - case Constructor::ConstructorKind::INT_RANGE: { + case Constructor::ConstructorKind::INT_RANGE: + { // TODO: implement rust_unreachable (); } break; - case Constructor::ConstructorKind::WILDCARD: { + case Constructor::ConstructorKind::WILDCARD: + { return "_"; } break; - case Constructor::ConstructorKind::REFERENCE: { + case Constructor::ConstructorKind::REFERENCE: + { // TODO: implement rust_unreachable (); } break; - default: { + default: + { rust_unreachable (); } break; @@ -1096,12 +1132,14 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, // TODO: only support struct and variant ctor for now. switch (ctor.get_kind ()) { - case Constructor::ConstructorKind::WILDCARD: { + case Constructor::ConstructorKind::WILDCARD: + { arity = 0; } break; case Constructor::ConstructorKind::STRUCT: - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { if (ty->get_kind () == TyTy::TypeKind::ADT) { TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty); @@ -1114,7 +1152,8 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, } } break; - default: { + default: + { rust_unreachable (); } } @@ -1144,7 +1183,7 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, } } - stack.push_back (WitnessPat (ctor, subfield, ty)); + stack.emplace_back (ctor, subfield, ty); } } @@ -1156,9 +1195,9 @@ WitnessMatrix::extend (const WitnessMatrix &other) } // forward declarations -static DeconstructedPat -lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, - TyTy::BaseType *scrutinee_ty); +static DeconstructedPat lower_pattern (Resolver::TypeCheckContext *ctx, + HIR::Pattern &pattern, + TyTy::BaseType *scrutinee_ty); static DeconstructedPat lower_tuple_pattern (Resolver::TypeCheckContext *ctx, @@ -1171,28 +1210,58 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx, std::vector<DeconstructedPat> fields; switch (elems.get_item_type ()) { - case HIR::TupleStructItems::ItemType::MULTIPLE: { - HIR::TupleStructItemsNoRange &multiple - = static_cast<HIR::TupleStructItemsNoRange &> (elems); + case HIR::TupleStructItems::ItemType::NO_REST: + { + HIR::TupleStructItemsNoRest &items_no_rest + = static_cast<HIR::TupleStructItemsNoRest &> (elems); rust_assert (variant->get_fields ().size () - == multiple.get_patterns ().size ()); + == items_no_rest.get_patterns ().size ()); - for (size_t i = 0; i < multiple.get_patterns ().size (); i++) + for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++) { fields.push_back ( - lower_pattern (ctx, *multiple.get_patterns ().at (i), + lower_pattern (ctx, *items_no_rest.get_patterns ().at (i), variant->get_fields ().at (i)->get_field_type ())); } return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; - case HIR::TupleStructItems::ItemType::RANGED: { - // TODO: ranged tuple struct items - rust_unreachable (); + case HIR::TupleStructItems::ItemType::HAS_REST: + { + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (elems); + + size_t num_patterns = items_has_rest.get_lower_patterns ().size () + + items_has_rest.get_upper_patterns ().size (); + + rust_assert (num_patterns <= variant->num_fields ()); + + size_t i = 0; + for (auto &pattern_member : items_has_rest.get_lower_patterns ()) + { + fields.push_back (lower_pattern ( + ctx, *pattern_member, + variant->get_fields ().at (i++)->get_field_type ())); + } + while (i < variant->num_fields () + - items_has_rest.get_upper_patterns ().size ()) + { + fields.push_back ( + DeconstructedPat::make_wildcard (pattern.get_locus ())); + i++; + } + for (auto &pattern_member : items_has_rest.get_upper_patterns ()) + { + fields.push_back (lower_pattern ( + ctx, *pattern_member, + variant->get_fields ().at (i++)->get_field_type ())); + } + return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; - default: { + default: + { rust_unreachable (); } } @@ -1223,7 +1292,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, { switch (elem->get_item_type ()) { - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { HIR::StructPatternFieldIdent *ident = static_cast<HIR::StructPatternFieldIdent *> (elem.get ()); int field_idx @@ -1232,7 +1302,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, = DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat *ident_pat = static_cast<HIR::StructPatternFieldIdentPat *> (elem.get ()); int field_idx @@ -1242,12 +1313,14 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, variant->get_fields ().at (field_idx)->get_field_type ()); } break; - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO: tuple: pat rust_unreachable (); } break; - default: { + default: + { rust_unreachable (); } } @@ -1264,11 +1337,13 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, switch (pat_type) { case HIR::Pattern::PatternType::WILDCARD: - case HIR::Pattern::PatternType::IDENTIFIER: { + case HIR::Pattern::PatternType::IDENTIFIER: + { return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::PATH: { + case HIR::Pattern::PatternType::PATH: + { // TODO: support constants, associated constants, enum variants and // structs // https://doc.rust-lang.org/reference/patterns.html#path-patterns @@ -1276,13 +1351,15 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::REFERENCE: { + case HIR::Pattern::PatternType::REFERENCE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; case HIR::Pattern::PatternType::STRUCT: - case HIR::Pattern::PatternType::TUPLE_STRUCT: { + case HIR::Pattern::PatternType::TUPLE_STRUCT: + { HirId path_id = UNKNOWN_HIRID; if (pat_type == HIR::Pattern::PatternType::STRUCT) { @@ -1339,37 +1416,44 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, } } break; - case HIR::Pattern::PatternType::TUPLE: { + case HIR::Pattern::PatternType::TUPLE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::SLICE: { + case HIR::Pattern::PatternType::SLICE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::ALT: { + case HIR::Pattern::PatternType::ALT: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::LITERAL: { + case HIR::Pattern::PatternType::LITERAL: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::RANGE: { + case HIR::Pattern::PatternType::RANGE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::GROUPED: { + case HIR::Pattern::PatternType::GROUPED: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - default: { + default: + { rust_unreachable (); } } @@ -1537,7 +1621,7 @@ check_match_usefulness (Resolver::TypeCheckContext *ctx, MatchArm lowered = lower_arm (ctx, arm, scrutinee_ty); PatOrWild pat = PatOrWild::make_pattern (lowered.get_pat ()); pats.push (pat); - rows.push_back (MatrixRow (pats, lowered.has_guard ())); + rows.emplace_back (pats, lowered.has_guard ()); } std::vector<PlaceInfo> place_infos = {{PlaceInfo (scrutinee_ty)}}; diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h index 2171340..645e61d 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h @@ -26,16 +26,16 @@ #include "rust-tyty.h" #include "optional.h" #include "rust-hir-visitor.h" -#include "rust-name-resolver.h" +#include "rust-immutable-name-resolution-context.h" namespace Rust { namespace Analysis { using namespace HIR; -void -check_match_usefulness (Resolver::TypeCheckContext *ctx, - TyTy::BaseType *scrutinee_ty, HIR::MatchExpr &expr); +void check_match_usefulness (Resolver::TypeCheckContext *ctx, + TyTy::BaseType *scrutinee_ty, + HIR::MatchExpr &expr); class PatternChecker : public HIR::HIRFullVisitor { @@ -46,7 +46,7 @@ public: private: Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; Analysis::Mappings &mappings; virtual void visit (Lifetime &lifetime) override; @@ -86,6 +86,8 @@ private: virtual void visit (MethodCallExpr &expr) override; virtual void visit (FieldAccessExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; @@ -106,6 +108,8 @@ private: virtual void visit (AwaitExpr &expr) override; virtual void visit (AsyncBlockExpr &expr) override; virtual void visit (InlineAsm &expr) override; + virtual void visit (LlvmInlineAsm &expr) override; + virtual void visit (OffsetOf &expr) override; virtual void visit (TypeParam ¶m) override; virtual void visit (ConstGenericParam ¶m) override; virtual void visit (LifetimeWhereClauseItem &item) override; @@ -149,12 +153,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/errors/rust-readonly-check.cc b/gcc/rust/checks/errors/rust-readonly-check.cc index c128933..f484047 100644 --- a/gcc/rust/checks/errors/rust-readonly-check.cc +++ b/gcc/rust/checks/errors/rust-readonly-check.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -17,184 +17,252 @@ // <http://www.gnu.org/licenses/>. #include "rust-readonly-check.h" -#include "rust-tree.h" -#include "rust-gcc.h" -#include "print-tree.h" +#include "rust-hir-expr.h" +#include "rust-hir-node.h" +#include "rust-hir-path.h" +#include "rust-hir-map.h" +#include "rust-hir-pattern.h" +#include "rust-mapping-common.h" +#include "rust-system.h" +#include "rust-immutable-name-resolution-context.h" +#include "rust-tyty.h" namespace Rust { -namespace Analysis { +namespace HIR { -static std::map<tree, int> assignment_map = {}; +static std::set<HirId> already_assigned_variables = {}; + +ReadonlyChecker::ReadonlyChecker () + : resolver (*Resolver::Resolver::get ()), + mappings (Analysis::Mappings::get ()), + context (*Resolver::TypeCheckContext::get ()) +{} + +void +ReadonlyChecker::go (Crate &crate) +{ + for (auto &item : crate.get_items ()) + item->accept_vis (*this); +} -// ported over from c-family/c-warn.cc void -readonly_error (location_t loc, tree arg, enum lvalue_use use) +ReadonlyChecker::visit (AssignmentExpr &expr) { - gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement - || use == lv_asm); - STRIP_ANY_LOCATION_WRAPPER (arg); - /* Using this macro rather than (for example) arrays of messages - ensures that all the format strings are checked at compile - time. */ -#define READONLY_MSG(A, I, D, AS) \ - (use == lv_assign \ - ? (A) \ - : (use == lv_increment ? (I) : (use == lv_decrement ? (D) : (AS)))) - if (TREE_CODE (arg) == COMPONENT_REF) + Expr &lhs = expr.get_lhs (); + mutable_context.enter (expr.get_mappings ().get_hirid ()); + lhs.accept_vis (*this); + mutable_context.exit (); +} + +void +ReadonlyChecker::visit (PathInExpression &expr) +{ + if (!mutable_context.is_in_context ()) + return; + + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + NodeId def_id; + + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + if (auto id = nr_ctx.lookup (ast_node_id)) + def_id = *id; + else + return; + + auto hir_id = mappings.lookup_node_to_hir (def_id); + if (!hir_id) + return; + + // Check if the local variable is mutable. + auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id); + if (maybe_pattern + && maybe_pattern.value ()->get_pattern_type () + == HIR::Pattern::PatternType::IDENTIFIER) + check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()), + expr.get_locus ()); + + // Check if the static item is mutable. + auto maybe_item = mappings.lookup_hir_item (*hir_id); + if (maybe_item + && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static) { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - error_at (loc, - READONLY_MSG (G_ ("assignment of member " - "%qD in read-only object"), - G_ ("increment of member " - "%qD in read-only object"), - G_ ("decrement of member " - "%qD in read-only object"), - G_ ("member %qD in read-only object " - "used as %<asm%> output")), - TREE_OPERAND (arg, 1)); - else - error_at ( - loc, - READONLY_MSG (G_ ("assignment of read-only member %qD"), - G_ ("increment of read-only member %qD"), - G_ ("decrement of read-only member %qD"), - G_ ("read-only member %qD used as %<asm%> output")), - TREE_OPERAND (arg, 1)); + auto static_item = static_cast<HIR::StaticItem *> (*maybe_item); + if (!static_item->is_mut ()) + rust_error_at (expr.get_locus (), + "assignment of read-only location '%s'", + static_item->get_identifier ().as_string ().c_str ()); } - else if (VAR_P (arg)) - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only variable %qD"), - G_ ("increment of read-only variable %qD"), - G_ ("decrement of read-only variable %qD"), - G_ ( - "read-only variable %qD used as %<asm%> output")), - arg); - else if (TREE_CODE (arg) == PARM_DECL) - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only parameter %qD"), - G_ ("increment of read-only parameter %qD"), - G_ ("decrement of read-only parameter %qD"), - G_ ( - "read-only parameter %qD use as %<asm%> output")), - arg); - else if (TREE_CODE (arg) == RESULT_DECL) + + // Check if the constant item is mutable. + if (maybe_item + && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant) { - error_at (loc, - READONLY_MSG (G_ ("assignment of " - "read-only named return value %qD"), - G_ ("increment of " - "read-only named return value %qD"), - G_ ("decrement of " - "read-only named return value %qD"), - G_ ("read-only named return value %qD " - "used as %<asm%>output")), - arg); + auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item); + rust_error_at (expr.get_locus (), "assignment of read-only location '%s'", + const_item->get_identifier ().as_string ().c_str ()); } - else if (TREE_CODE (arg) == FUNCTION_DECL) - error_at (loc, - READONLY_MSG (G_ ("assignment of function %qD"), - G_ ("increment of function %qD"), - G_ ("decrement of function %qD"), - G_ ("function %qD used as %<asm%> output")), - arg); - else - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only location %qE"), - G_ ("increment of read-only location %qE"), - G_ ("decrement of read-only location %qE"), - G_ ( - "read-only location %qE used as %<asm%> output")), - arg); } -static void -emit_error (tree *t, tree lhs, enum lvalue_use use) +void +ReadonlyChecker::check_variable (IdentifierPattern *pattern, + location_t assigned_loc) { - readonly_error (EXPR_LOCATION (*t), lhs, use); - TREE_OPERAND (*t, 0) = error_mark_node; + if (!mutable_context.is_in_context ()) + return; + + TyTy::BaseType *type; + if (context.lookup_type (pattern->get_mappings ().get_hirid (), &type) + && is_mutable_type (type)) + return; + if (pattern->is_mut ()) + return; + + auto hir_id = pattern->get_mappings ().get_hirid (); + if (already_assigned_variables.count (hir_id) > 0) + rust_error_at (assigned_loc, "assignment of read-only variable '%s'", + pattern->as_string ().c_str ()); + already_assigned_variables.insert (hir_id); } -static void -check_modify_expr (tree *t) +void +ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern, + bool has_init_expr) { - tree lhs = TREE_OPERAND (*t, 0); - if (TREE_CODE (lhs) == ARRAY_REF || TREE_CODE (lhs) == COMPONENT_REF) - lhs = TREE_OPERAND (lhs, 0); - - tree lhs_type = TREE_TYPE (lhs); - if (TYPE_READONLY (lhs_type) || TREE_READONLY (lhs) || TREE_CONSTANT (lhs)) + if (has_init_expr) { - if (TREE_CODE (lhs) != VAR_DECL) - emit_error (t, lhs, lv_assign); - else if (!DECL_ARTIFICIAL (lhs)) - { - if (DECL_INITIAL (lhs) != NULL) - emit_error (t, lhs, lv_assign); - else - { - if (assignment_map.find (lhs) == assignment_map.end ()) - { - assignment_map.insert ({lhs, 0}); - } - assignment_map[lhs]++; - - if (assignment_map[lhs] > 1) - emit_error (t, lhs, lv_assign); - } - } + HirId pattern_id = pattern.get_mappings ().get_hirid (); + already_assigned_variables.insert (pattern_id); } } -static void -check_decl (tree *t) +void +ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern, + bool has_init_expr) { - switch (TREE_CODE (*t)) + switch (tuple_pattern.get_items ().get_item_type ()) { - case MODIFY_EXPR: - check_modify_expr (t); + case HIR::TuplePatternItems::ItemType::NO_REST: + { + auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> ( + tuple_pattern.get_items ()); + for (auto &sub : items_no_rest.get_patterns ()) + { + collect_assignment (*sub, has_init_expr); + } + } + break; + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> ( + tuple_pattern.get_items ()); + for (auto &sub : items_has_rest.get_lower_patterns ()) + collect_assignment (*sub, has_init_expr); + for (auto &sub : items_has_rest.get_upper_patterns ()) + collect_assignment (*sub, has_init_expr); + } + break; + default: break; + } +} +void +ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr) +{ + switch (pattern.get_pattern_type ()) + { + case HIR::Pattern::PatternType::IDENTIFIER: + { + collect_assignment_identifier (static_cast<IdentifierPattern &> ( + pattern), + has_init_expr); + } + break; + case HIR::Pattern::PatternType::TUPLE: + { + auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern); + collect_assignment_tuple (tuple_pattern, has_init_expr); + } + break; default: break; } } -static tree -readonly_walk_fn (tree *t, int *, void *) +void +ReadonlyChecker::visit (LetStmt &stmt) +{ + HIR::Pattern &pattern = stmt.get_pattern (); + collect_assignment (pattern, stmt.has_init_expr ()); +} + +void +ReadonlyChecker::visit (FieldAccessExpr &expr) { - check_decl (t); - return NULL_TREE; + if (mutable_context.is_in_context ()) + { + expr.get_receiver_expr ().accept_vis (*this); + } } void -ReadonlyCheck::Lint (Compile::Context &ctx) +ReadonlyChecker::visit (TupleIndexExpr &expr) { - assignment_map.clear (); - for (auto &fndecl : ctx.get_func_decls ()) + if (mutable_context.is_in_context ()) { - for (tree p = DECL_ARGUMENTS (fndecl); p != NULL_TREE; p = DECL_CHAIN (p)) - { - check_decl (&p); - } + expr.get_tuple_expr ().accept_vis (*this); + } +} - walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl), - &readonly_walk_fn, &ctx); +void +ReadonlyChecker::visit (ArrayIndexExpr &expr) +{ + if (mutable_context.is_in_context ()) + { + expr.get_array_expr ().accept_vis (*this); } +} - assignment_map.clear (); - for (auto &var : ctx.get_var_decls ()) +void +ReadonlyChecker::visit (TupleExpr &expr) +{ + if (mutable_context.is_in_context ()) { - tree decl = var->get_decl (); - check_decl (&decl); + // TODO: Add check for tuple expression } +} - assignment_map.clear (); - for (auto &const_decl : ctx.get_const_decls ()) +void +ReadonlyChecker::visit (LiteralExpr &expr) +{ + if (mutable_context.is_in_context ()) { - check_decl (&const_decl); + rust_error_at (expr.get_locus (), "assignment of read-only location"); } } -} // namespace Analysis +void +ReadonlyChecker::visit (DereferenceExpr &expr) +{ + if (!mutable_context.is_in_context ()) + return; + TyTy::BaseType *to_deref_type; + auto to_deref = expr.get_expr ().get_mappings ().get_hirid (); + if (!context.lookup_type (to_deref, &to_deref_type)) + return; + if (!is_mutable_type (to_deref_type)) + rust_error_at (expr.get_locus (), "assignment of read-only location"); +} + +bool +ReadonlyChecker::is_mutable_type (TyTy::BaseType *type) +{ + if (type->get_kind () == TyTy::TypeKind::REF) + return static_cast<TyTy::ReferenceType *> (type)->is_mutable (); + if (type->get_kind () == TyTy::TypeKind::POINTER) + return static_cast<TyTy::PointerType *> (type)->is_mutable (); + return false; +} +} // namespace HIR } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-readonly-check.h b/gcc/rust/checks/errors/rust-readonly-check.h index b39eee3..3525620 100644 --- a/gcc/rust/checks/errors/rust-readonly-check.h +++ b/gcc/rust/checks/errors/rust-readonly-check.h @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -16,21 +16,54 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#ifndef RUST_READONLY_CHECK -#define RUST_READONLY_CHECK - -#include "rust-compile-context.h" +#include "rust-hir-visitor.h" +#include "rust-name-resolver.h" +#include "rust-stacked-contexts.h" +#include "rust-hir-type-check.h" namespace Rust { -namespace Analysis { - -class ReadonlyCheck +namespace HIR { +class ReadonlyChecker : public DefaultHIRVisitor { public: - static void Lint (Compile::Context &ctx); -}; + ReadonlyChecker (); + + void go (HIR::Crate &crate); + +private: + enum class lvalue_use + { + assign, + increment, + decrement, + }; + + Resolver::Resolver &resolver; + Analysis::Mappings &mappings; + Resolver::TypeCheckContext &context; + StackedContexts<HirId> mutable_context; -} // namespace Analysis -} // namespace Rust + using DefaultHIRVisitor::visit; + + virtual void visit (AssignmentExpr &expr) override; + virtual void visit (PathInExpression &expr) override; + virtual void visit (FieldAccessExpr &expr) override; + virtual void visit (ArrayIndexExpr &expr) override; + virtual void visit (TupleExpr &expr) override; + virtual void visit (TupleIndexExpr &expr) override; + virtual void visit (LetStmt &stmt) override; + virtual void visit (LiteralExpr &expr) override; + virtual void visit (DereferenceExpr &expr) override; + + void collect_assignment (Pattern &pattern, bool has_init_expr); + void collect_assignment_identifier (IdentifierPattern &pattern, + bool has_init_expr); + void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr); + + void check_variable (IdentifierPattern *pattern, location_t assigned_loc); + + bool is_mutable_type (TyTy::BaseType *type); +}; -#endif // RUST_READONLY_CHECK +} // namespace HIR +} // namespace Rust
\ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index 8aa59ee..607d20f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -481,9 +481,14 @@ UnsafeChecker::visit (MethodCallExpr &expr) TyTy::BaseType *method_type; context.lookup_type (expr.get_method_name ().get_mappings ().get_hirid (), &method_type); + if (!method_type || !method_type->is<TyTy::FnType> ()) + return; auto &fn = static_cast<TyTy::FnType &> (*method_type); + // FIXME + // should probably use the defid lookup instead + // tl::optional<HIR::Item *> lookup_defid (DefId id); auto method = mappings.lookup_hir_implitem (fn.get_ref ()); if (!unsafe_context.is_in_context () && method) check_unsafe_call (static_cast<Function *> (method->first), @@ -535,6 +540,18 @@ UnsafeChecker::visit (BlockExpr &expr) } void +UnsafeChecker::visit (AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +UnsafeChecker::visit (ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void UnsafeChecker::visit (ContinueExpr &) {} @@ -666,6 +683,23 @@ UnsafeChecker::visit (InlineAsm &expr) } void +UnsafeChecker::visit (LlvmInlineAsm &expr) +{ + if (unsafe_context.is_in_context ()) + return; + + rust_error_at ( + expr.get_locus (), ErrorCode::E0133, + "use of inline assembly is unsafe and requires unsafe function or block"); +} + +void +UnsafeChecker::visit (OffsetOf &expr) +{ + // nothing to do, offset_of!() is safe +} + +void UnsafeChecker::visit (TypeParam &) {} @@ -892,11 +926,11 @@ UnsafeChecker::visit (StructPattern &) {} void -UnsafeChecker::visit (TupleStructItemsNoRange &) +UnsafeChecker::visit (TupleStructItemsNoRest &) {} void -UnsafeChecker::visit (TupleStructItemsRange &) +UnsafeChecker::visit (TupleStructItemsHasRest &) {} void @@ -904,11 +938,11 @@ UnsafeChecker::visit (TupleStructPattern &) {} void -UnsafeChecker::visit (TuplePatternItemsMultiple &) +UnsafeChecker::visit (TuplePatternItemsNoRest &) {} void -UnsafeChecker::visit (TuplePatternItemsRanged &) +UnsafeChecker::visit (TuplePatternItemsHasRest &) {} void @@ -916,6 +950,14 @@ UnsafeChecker::visit (TuplePattern &) {} void +UnsafeChecker::visit (SlicePatternItemsNoRest &) +{} + +void +UnsafeChecker::visit (SlicePatternItemsHasRest &) +{} + +void UnsafeChecker::visit (SlicePattern &) {} diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h index 63098fe..420668f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.h +++ b/gcc/rust/checks/errors/rust-unsafe-checker.h @@ -95,6 +95,8 @@ private: virtual void visit (FieldAccessExpr &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; virtual void visit (RangeFromToExpr &expr) override; @@ -114,6 +116,8 @@ private: virtual void visit (AwaitExpr &expr) override; virtual void visit (AsyncBlockExpr &expr) override; virtual void visit (InlineAsm &expr) override; + virtual void visit (LlvmInlineAsm &expr) override; + virtual void visit (OffsetOf &expr) override; virtual void visit (TypeParam ¶m) override; virtual void visit (ConstGenericParam ¶m) override; virtual void visit (LifetimeWhereClauseItem &item) override; @@ -157,12 +161,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/lints/rust-lint-marklive-base.h b/gcc/rust/checks/lints/rust-lint-marklive-base.h index 2a97577..dec9396 100644 --- a/gcc/rust/checks/lints/rust-lint-marklive-base.h +++ b/gcc/rust/checks/lints/rust-lint-marklive-base.h @@ -19,9 +19,6 @@ #ifndef RUST_HIR_LIVENESS_BASE #define RUST_HIR_LIVENESS_BASE -#include "rust-diagnostics.h" -#include "rust-lint-marklive.h" -#include "rust-lint-marklive-base.h" #include "rust-hir-visitor.h" #include "rust-hir-map.h" diff --git a/gcc/rust/checks/lints/rust-lint-unused-var.cc b/gcc/rust/checks/lints/rust-lint-unused-var.cc index 896eeb0..08596f1 100644 --- a/gcc/rust/checks/lints/rust-lint-unused-var.cc +++ b/gcc/rust/checks/lints/rust-lint-unused-var.cc @@ -31,6 +31,7 @@ check_decl (tree *t) tree var_name = DECL_NAME (*t); const char *var_name_ptr = IDENTIFIER_POINTER (var_name); bool starts_with_under_score = strncmp (var_name_ptr, "_", 1) == 0; + bool is_self = strcmp (var_name_ptr, "self") == 0; bool is_constant = TREE_CODE (*t) == CONST_DECL; // if (!is_constant) @@ -43,7 +44,8 @@ check_decl (tree *t) // starts_with_under_score ? "true" : "false", var_name_ptr); // } - if (!TREE_USED (*t) && !DECL_ARTIFICIAL (*t) && !starts_with_under_score) + if (!TREE_USED (*t) && !DECL_ARTIFICIAL (*t) && !starts_with_under_score + && !is_self) { warning_at (DECL_SOURCE_LOCATION (*t), is_constant ? OPT_Wunused_const_variable_ diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index a8c3ca5..3c5e74e 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -22,6 +22,7 @@ #include "rust-path.h" #include "rust-session-manager.h" #include "rust-attribute-values.h" +#include "rust-macro-expand.h" namespace Rust { @@ -30,7 +31,7 @@ namespace Rust { * should be stripped. Note that attributes must be expanded before calling. */ bool -fails_cfg (const AST::AttrVec &attrs) +CfgStrip::fails_cfg (const AST::AttrVec &attrs) const { auto &session = Session::get_instance (); @@ -39,6 +40,9 @@ fails_cfg (const AST::AttrVec &attrs) if (attr.get_path () == Values::Attributes::CFG && !attr.check_cfg_predicate (session)) return true; + else if (!expansion_cfg.should_test + && attr.get_path () == Values::Attributes::TEST) + return true; } return false; } @@ -48,7 +52,7 @@ fails_cfg (const AST::AttrVec &attrs) * should be stripped. Will expand attributes as well. */ bool -fails_cfg_with_expand (AST::AttrVec &attrs) +CfgStrip::fails_cfg_with_expand (AST::AttrVec &attrs) const { auto &session = Session::get_instance (); @@ -85,6 +89,9 @@ fails_cfg_with_expand (AST::AttrVec &attrs) attr.as_string ().c_str ()); } } + else if (!expansion_cfg.should_test + && attr.get_path () == Values::Attributes::TEST) + return true; } return false; } @@ -289,7 +296,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args) { switch (arg.get_kind ()) { - case AST::GenericArg::Kind::Type: { + case AST::GenericArg::Kind::Type: + { auto &type = arg.get_type (); type.accept_vis (*this); @@ -298,7 +306,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args) "cannot strip type in this position"); break; } - case AST::GenericArg::Kind::Const: { + case AST::GenericArg::Kind::Const: + { auto &expr = arg.get_expression (); expr.accept_vis (*this); @@ -1190,7 +1199,7 @@ CfgStrip::visit (AST::ClosureExprInnerTyped &expr) rust_error_at (type.get_locus (), "cannot strip type in this position"); // can't strip expression itself, but can strip sub-expressions - auto &definition_block = expr.get_definition_block (); + auto &definition_block = expr.get_definition_expr (); definition_block.accept_vis (*this); if (definition_block.is_marked_for_strip ()) rust_error_at (definition_block.get_locus (), @@ -1763,16 +1772,17 @@ CfgStrip::visit (AST::Module &module) return; } - // A loaded module might have inner attributes - if (module.get_kind () == AST::Module::ModuleKind::LOADED) + if (module.get_kind () == AST::Module::UNLOADED) { - // strip test based on inner attrs - expand_cfg_attrs (module.get_inner_attrs ()); - if (fails_cfg_with_expand (module.get_inner_attrs ())) - { - module.mark_for_strip (); - return; - } + module.load_items (); + } + + // strip test based on inner attrs + expand_cfg_attrs (module.get_inner_attrs ()); + if (fails_cfg_with_expand (module.get_inner_attrs ())) + { + module.mark_for_strip (); + return; } // strip items if required @@ -2059,38 +2069,6 @@ CfgStrip::visit (AST::StaticItem &static_item) } void -CfgStrip::visit (AST::TraitItemConst &item) -{ - // initial test based on outer attrs - expand_cfg_attrs (item.get_outer_attrs ()); - if (fails_cfg_with_expand (item.get_outer_attrs ())) - { - item.mark_for_strip (); - return; - } - - AST::DefaultASTVisitor::visit (item); - - // strip any sub-types - auto &type = item.get_type (); - - if (type.is_marked_for_strip ()) - rust_error_at (type.get_locus (), "cannot strip type in this position"); - - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped */ - if (item.has_expression ()) - { - auto &expr = item.get_expr (); - if (expr.is_marked_for_strip ()) - rust_error_at (expr.get_locus (), - "cannot strip expression in this position - outer " - "attributes not allowed"); - } -} - -void CfgStrip::visit (AST::TraitItemType &item) { // initial test based on outer attrs @@ -2260,12 +2238,12 @@ void CfgStrip::visit (AST::IdentifierPattern &pattern) { // can only strip sub-patterns of the inner pattern to bind - if (!pattern.has_pattern_to_bind ()) + if (!pattern.has_subpattern ()) return; AST::DefaultASTVisitor::visit (pattern); - auto &sub_pattern = pattern.get_pattern_to_bind (); + auto &sub_pattern = pattern.get_subpattern (); if (sub_pattern.is_marked_for_strip ()) rust_error_at (sub_pattern.get_locus (), "cannot strip pattern in this position"); @@ -2371,7 +2349,7 @@ CfgStrip::visit (AST::StructPattern &pattern) maybe_strip_pointer_allow_strip (elems.get_struct_pattern_fields ()); // assuming you can strip the ".." part - if (elems.has_etc ()) + if (elems.has_rest ()) { expand_cfg_attrs (elems.get_etc_outer_attrs ()); if (fails_cfg_with_expand (elems.get_etc_outer_attrs ())) @@ -2380,7 +2358,7 @@ CfgStrip::visit (AST::StructPattern &pattern) } void -CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items) +CfgStrip::visit (AST::TupleStructItemsNoRest &tuple_items) { AST::DefaultASTVisitor::visit (tuple_items); // can't strip individual patterns, only sub-patterns @@ -2393,7 +2371,7 @@ CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items) } } void -CfgStrip::visit (AST::TupleStructItemsRange &tuple_items) +CfgStrip::visit (AST::TupleStructItemsHasRest &tuple_items) { AST::DefaultASTVisitor::visit (tuple_items); // can't strip individual patterns, only sub-patterns @@ -2426,7 +2404,7 @@ CfgStrip::visit (AST::TupleStructPattern &pattern) } void -CfgStrip::visit (AST::TuplePatternItemsMultiple &tuple_items) +CfgStrip::visit (AST::TuplePatternItemsNoRest &tuple_items) { AST::DefaultASTVisitor::visit (tuple_items); @@ -2441,7 +2419,7 @@ CfgStrip::visit (AST::TuplePatternItemsMultiple &tuple_items) } void -CfgStrip::visit (AST::TuplePatternItemsRanged &tuple_items) +CfgStrip::visit (AST::TuplePatternItemsHasRest &tuple_items) { AST::DefaultASTVisitor::visit (tuple_items); @@ -2475,20 +2453,44 @@ CfgStrip::visit (AST::GroupedPattern &pattern) } void -CfgStrip::visit (AST::SlicePattern &pattern) +CfgStrip::visit (AST::SlicePatternItemsNoRest &items) { - AST::DefaultASTVisitor::visit (pattern); + AST::DefaultASTVisitor::visit (items); // can't strip individual patterns, only sub-patterns - for (auto &item : pattern.get_items ()) + for (auto &pattern : items.get_patterns ()) { - if (item->is_marked_for_strip ()) - rust_error_at (item->get_locus (), + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? } } void +CfgStrip::visit (AST::SlicePatternItemsHasRest &items) +{ + AST::DefaultASTVisitor::visit (items); + // can't strip individual patterns, only sub-patterns + for (auto &pattern : items.get_lower_patterns ()) + { + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), + "cannot strip pattern in this position"); + } + for (auto &pattern : items.get_upper_patterns ()) + { + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), + "cannot strip pattern in this position"); + } +} + +void +CfgStrip::visit (AST::SlicePattern &pattern) +{ + AST::DefaultASTVisitor::visit (pattern); +} + +void CfgStrip::visit (AST::AltPattern &pattern) { AST::DefaultASTVisitor::visit (pattern); diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h index 4900ae8..42cd266 100644 --- a/gcc/rust/expand/rust-cfg-strip.h +++ b/gcc/rust/expand/rust-cfg-strip.h @@ -23,14 +23,23 @@ #include "rust-item.h" namespace Rust { + +// forward declare +struct ExpansionCfg; + // Visitor used to maybe_strip attributes. class CfgStrip : public AST::DefaultASTVisitor { private: + bool fails_cfg (const AST::AttrVec &attrs) const; + + bool fails_cfg_with_expand (AST::AttrVec &attrs) const; + public: using DefaultASTVisitor::visit; - CfgStrip () {} + CfgStrip (const ExpansionCfg &expansion_cfg) : expansion_cfg (expansion_cfg) + {} /* Run the AttrVisitor on an entire crate */ void go (AST::Crate &crate); @@ -147,7 +156,6 @@ public: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemConst &item) override; void visit (AST::TraitItemType &item) override; void visit (AST::Trait &trait) override; void visit (AST::InherentImpl &impl) override; @@ -166,12 +174,14 @@ public: void visit (AST::StructPatternFieldIdentPat &field) override; void visit (AST::StructPatternFieldIdent &field) override; void visit (AST::StructPattern &pattern) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; + void visit (AST::TupleStructItemsNoRest &tuple_items) override; + void visit (AST::TupleStructItemsHasRest &tuple_items) override; void visit (AST::TupleStructPattern &pattern) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; + void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + void visit (AST::TuplePatternItemsHasRest &tuple_items) override; void visit (AST::GroupedPattern &pattern) override; + void visit (AST::SlicePatternItemsNoRest &items) override; + void visit (AST::SlicePatternItemsHasRest &items) override; void visit (AST::SlicePattern &pattern) override; void visit (AST::AltPattern &pattern) override; @@ -192,6 +202,9 @@ public: { DefaultASTVisitor::visit (item); } + +private: + const ExpansionCfg &expansion_cfg; }; } // namespace Rust diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index 074ea01..27dcc66 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -61,15 +61,13 @@ std::unique_ptr<AssociatedItem> DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr) { auto block = std::unique_ptr<BlockExpr> ( - new BlockExpr ({}, std::move (clone_expr), {}, {}, AST::LoopLabel::error (), - loc, loc)); + new BlockExpr ({}, std::move (clone_expr), {}, {}, tl::nullopt, loc, loc)); auto big_self_type = builder.single_type_path ("Self"); - std::unique_ptr<SelfParam> self (new SelfParam (Lifetime::error (), - /* is_mut */ false, loc)); - std::vector<std::unique_ptr<Param>> params; - params.push_back (std::move (self)); + + params.emplace_back (new SelfParam (tl::nullopt, + /* is_mut */ false, loc)); return std::unique_ptr<AssociatedItem> ( new Function ({"clone"}, builder.fn_qualifiers (), /* generics */ {}, @@ -212,7 +210,7 @@ DeriveClone::clone_enum_tuple (PathInExpression variant_path, } auto pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (patterns))); + new TupleStructItemsNoRest (std::move (patterns))); auto pattern = std::unique_ptr<Pattern> (new ReferencePattern ( std::unique_ptr<Pattern> (new TupleStructPattern ( @@ -294,8 +292,14 @@ DeriveClone::clone_enum_struct (PathInExpression variant_path, new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern ( variant_path, loc, pattern_elts)), false, false, loc)); + + PathInExpression new_path (variant_path.get_segments (), + variant_path.get_outer_attrs (), + variant_path.get_locus (), + variant_path.opening_scope_resolution ()); + auto expr = std::unique_ptr<Expr> ( - new StructExprStructFields (variant_path, std::move (cloned_fields), loc)); + new StructExprStructFields (new_path, std::move (cloned_fields), loc)); return builder.match_case (std::move (pattern), std::move (expr)); } diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h index 61224ba..a3320c7 100644 --- a/gcc/rust/expand/rust-derive-clone.h +++ b/gcc/rust/expand/rust-derive-clone.h @@ -29,7 +29,7 @@ class DeriveClone : DeriveVisitor public: DeriveClone (location_t loc); - std::unique_ptr<AST::Item> go (Item &item); + std::unique_ptr<Item> go (Item &item); private: std::unique_ptr<Item> expanded; @@ -80,10 +80,10 @@ private: MatchCase clone_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc new file mode 100644 index 0000000..9890bb7 --- /dev/null +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -0,0 +1,191 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-derive-cmp-common.h" +#include "rust-ast-builder.h" +#include "rust-item.h" + +namespace Rust { +namespace AST { + +SelfOther +SelfOther::index (Builder builder, int idx) +{ + return SelfOther{ + builder.tuple_idx ("self", idx), + builder.tuple_idx ("other", idx), + }; +} + +std::vector<SelfOther> +SelfOther::indexes (Builder builder, const std::vector<TupleField> &fields) +{ + std::vector<SelfOther> vec; + + for (size_t i = 0; i < fields.size (); i++) + vec.emplace_back (SelfOther::index (builder, i)); + + return vec; +} + +SelfOther +SelfOther::field (Builder builder, const std::string &field_name) +{ + return SelfOther{ + builder.field_access (builder.identifier ("self"), field_name), + builder.field_access (builder.identifier ("other"), field_name), + }; +} + +std::vector<SelfOther> +SelfOther::fields (Builder builder, const std::vector<StructField> &fields) +{ + std::vector<SelfOther> vec; + + for (const auto &field : fields) + vec.emplace_back ( + SelfOther::field (builder, field.get_field_name ().as_string ())); + + return vec; +} + +MatchCase +EnumMatchBuilder::tuple (EnumItem &variant_raw) +{ + auto &variant = static_cast<EnumItemTuple &> (variant_raw); + + auto self_patterns = std::vector<std::unique_ptr<Pattern>> (); + auto other_patterns = std::vector<std::unique_ptr<Pattern>> (); + + auto self_other_exprs = std::vector<SelfOther> (); + + for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++) + { + // The patterns we're creating for each field are `self_<i>` and + // `other_<i>` where `i` is the index of the field. It doesn't actually + // matter what we use, as long as it's ordered, unique, and that we can + // reuse it in the match case's return expression to check that they are + // equal. + + auto self_pattern_str = "__self_" + std::to_string (i); + auto other_pattern_str = "__other_" + std::to_string (i); + + self_patterns.emplace_back ( + builder.identifier_pattern (self_pattern_str)); + other_patterns.emplace_back ( + builder.identifier_pattern (other_pattern_str)); + + self_other_exprs.emplace_back (SelfOther{ + builder.identifier (self_pattern_str), + builder.identifier (other_pattern_str), + }); + } + + // TODO: Replace with `reconstruct()` instead of building these twice + auto self_variant_path = builder.variant_path (enum_path, variant_path); + auto other_variant_path = builder.variant_path (enum_path, variant_path); + + auto self_pattern_items = std::unique_ptr<TupleStructItems> ( + new TupleStructItemsNoRest (std::move (self_patterns))); + auto other_pattern_items = std::unique_ptr<TupleStructItems> ( + new TupleStructItemsNoRest (std::move (other_patterns))); + + auto self_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern ( + self_variant_path, std::move (self_pattern_items))), + false, false, builder.loc)); + auto other_pattern = std::unique_ptr<Pattern> (new ReferencePattern ( + std::unique_ptr<Pattern> (new TupleStructPattern ( + other_variant_path, std::move (other_pattern_items))), + false, false, builder.loc)); + + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern + = std::make_unique<TuplePattern> (std::move (tuple_items), builder.loc); + + auto expr = fn (std::move (self_other_exprs)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + +MatchCase +EnumMatchBuilder::strukt (EnumItem &variant_raw) +{ + auto &variant = static_cast<EnumItemStruct &> (variant_raw); + + auto self_fields = std::vector<std::unique_ptr<StructPatternField>> (); + auto other_fields = std::vector<std::unique_ptr<StructPatternField>> (); + + auto self_other_exprs = std::vector<SelfOther> (); + + for (auto &field : variant.get_struct_fields ()) + { + // The patterns we're creating for each field are `self_<field>` and + // `other_<field>` where `field` is the name of the field. It doesn't + // actually matter what we use, as long as it's ordered, unique, and that + // we can reuse it in the match case's return expression to check that + // they are equal. + + auto field_name = field.get_field_name ().as_string (); + + auto self_pattern_str = "__self_" + field_name; + auto other_pattern_str = "__other_" + field_name; + + self_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (self_pattern_str))); + other_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (other_pattern_str))); + + self_other_exprs.emplace_back (SelfOther{ + builder.identifier (self_pattern_str), + builder.identifier (other_pattern_str), + }); + } + + // TODO: Replace with `reconstruct()` instead of building these twice + auto self_variant_path = builder.variant_path (enum_path, variant_path); + auto other_variant_path = builder.variant_path (enum_path, variant_path); + + auto self_elts = StructPatternElements (std::move (self_fields)); + auto other_elts = StructPatternElements (std::move (other_fields)); + + auto self_pattern = std::unique_ptr<Pattern> (new ReferencePattern ( + std::unique_ptr<Pattern> (new StructPattern (self_variant_path, builder.loc, + std::move (self_elts))), + false, false, builder.loc)); + auto other_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> ( + new StructPattern (other_variant_path, builder.loc, + std::move (other_elts))), + false, false, builder.loc)); + + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern + = std::make_unique<TuplePattern> (std::move (tuple_items), builder.loc); + + auto expr = fn (std::move (self_other_exprs)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/expand/rust-derive-cmp-common.h b/gcc/rust/expand/rust-derive-cmp-common.h new file mode 100644 index 0000000..4efbed8 --- /dev/null +++ b/gcc/rust/expand/rust-derive-cmp-common.h @@ -0,0 +1,99 @@ +// 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/>. + +#ifndef RUST_DERIVE_CMP_COMMON_H +#define RUST_DERIVE_CMP_COMMON_H + +#include "rust-ast.h" +#include "rust-ast-builder.h" +#include "rust-item.h" +#include "rust-path.h" + +namespace Rust { +namespace AST { + +/** + * A pair of two expressions from each instance being compared. E.g. this + * could be `self.0` and `other.0`, or `self.field` and `other.field` + */ +struct SelfOther +{ + std::unique_ptr<Expr> self_expr; + std::unique_ptr<Expr> other_expr; + + /* Create a <self.i> and an <other.i> expression */ + static SelfOther index (Builder builder, int idx); + static std::vector<SelfOther> indexes (Builder builder, + const std::vector<TupleField> &fields); + + /* Create a <self.field> and an <other.field> expression */ + static SelfOther field (Builder builder, const std::string &field_name); + static std::vector<SelfOther> fields (Builder builder, + const std::vector<StructField> &fields); +}; + +/** + * Builder for common match cases used when comparing two enum instances. This + * builder takes care of creating the unique patterns for the `self` instance + * and `other` instance, as well as the entire `MatchCase` required for building + * a proper comparision expression for an implementation of a comparision trait + * for an enum type. The functions take a lambda to use when creating the + * expression of the generated `MatchCase`. + */ +class EnumMatchBuilder +{ +public: + /** + * The type of functions to call when creating the resulting expression in the + * generated `MatchCase` + */ + using ExprFn + = std::function<std::unique_ptr<Expr> (std::vector<SelfOther> &&)>; + + EnumMatchBuilder (const std::string &enum_path, + const std::string &variant_path, ExprFn fn, + Builder &builder) + : enum_path (enum_path), variant_path (variant_path), fn (fn), + builder (builder) + {} + + /** + * Generate a `MatchCase` for an enum tuple variant + * + * (&Enum::Tuple(self0, self1), &Enum::Tuple(other0, other1)) => <fn> + */ + MatchCase tuple (EnumItem &variant); + + /** + * Generate a `MatchCase` for an enum struct variant + * + * (&Enum::Struct { a: self_a }, &Enum::Struct { a: other_a }) => <fn> + */ + MatchCase strukt (EnumItem &variant); + +private: + const std::string &enum_path; + const std::string &variant_path; + ExprFn fn; + Builder &builder; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DERIVE_CMP_COMMON_H diff --git a/gcc/rust/expand/rust-derive-copy.h b/gcc/rust/expand/rust-derive-copy.h index 71972eb..664a8e0 100644 --- a/gcc/rust/expand/rust-derive-copy.h +++ b/gcc/rust/expand/rust-derive-copy.h @@ -44,10 +44,10 @@ private: copy_impl (std::string name, const std::vector<std::unique_ptr<GenericParam>> &type_generics); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-debug.cc b/gcc/rust/expand/rust-derive-debug.cc index 7ad3908..a0bf9d8 100644 --- a/gcc/rust/expand/rust-derive-debug.cc +++ b/gcc/rust/expand/rust-derive-debug.cc @@ -50,8 +50,7 @@ DeriveDebug::stub_debug_fn () // we can't use builder.block() here as it returns a unique_ptr<Expr> and // Function's constructor expects a unique_ptr<BlockExpr> auto block = std::unique_ptr<BlockExpr> ( - new BlockExpr ({}, std::move (stub_return), {}, {}, - AST::LoopLabel::error (), loc, loc)); + new BlockExpr ({}, std::move (stub_return), {}, {}, tl::nullopt, loc, loc)); auto self = builder.self_ref_param (); diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc index c54f8c3..26ee546 100644 --- a/gcc/rust/expand/rust-derive-default.cc +++ b/gcc/rust/expand/rust-derive-default.cc @@ -58,8 +58,7 @@ DeriveDefault::default_fn (std::unique_ptr<Expr> &&return_expr) = std::unique_ptr<Type> (new TypePath (builder.type_path ("Self"))); auto block = std::unique_ptr<BlockExpr> ( - new BlockExpr ({}, std::move (return_expr), {}, {}, - AST::LoopLabel::error (), loc, loc)); + new BlockExpr ({}, std::move (return_expr), {}, {}, tl::nullopt, loc, loc)); return builder.function ("default", {}, std::move (self_ty), std::move (block)); @@ -99,7 +98,8 @@ DeriveDefault::visit_struct (StructStruct &item) for (auto &field : item.get_fields ()) { auto name = field.get_field_name ().as_string (); - auto expr = default_call (field.get_field_type ().clone_type ()); + auto type = field.get_field_type ().reconstruct (); + auto expr = default_call (std::move (type)); cloned_fields.emplace_back ( builder.struct_expr_field (std::move (name), std::move (expr))); @@ -120,7 +120,7 @@ DeriveDefault::visit_tuple (TupleStruct &tuple_item) for (auto &field : tuple_item.get_fields ()) { - auto type = field.get_field_type ().clone_type (); + auto type = field.get_field_type ().reconstruct (); defaulted_fields.emplace_back (default_call (std::move (type))); } diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc index dc173de..17332a4 100644 --- a/gcc/rust/expand/rust-derive-eq.cc +++ b/gcc/rust/expand/rust-derive-eq.cc @@ -49,8 +49,7 @@ DeriveEq::assert_receiver_is_total_eq_fn ( stmts.emplace_back (assert_type_is_eq (std::move (type))); auto block = std::unique_ptr<BlockExpr> ( - new BlockExpr (std::move (stmts), nullptr, {}, {}, AST::LoopLabel::error (), - loc, loc)); + new BlockExpr (std::move (stmts), nullptr, {}, {}, tl::nullopt, loc, loc)); auto self = builder.self_ref_param (); @@ -129,9 +128,13 @@ DeriveEq::eq_impls ( auto eq_impl = builder.trait_impl (eq, std::move (eq_generics.self_type), std::move (trait_items), std::move (eq_generics.impl)); + + // StructuralEq is a marker trait + decltype (trait_items) steq_trait_items = {}; + auto steq_impl = builder.trait_impl (steq, std::move (steq_generics.self_type), - std::move (trait_items), + std::move (steq_trait_items), std::move (steq_generics.impl)); return vec (std::move (eq_impl), std::move (steq_impl)); @@ -143,7 +146,7 @@ DeriveEq::visit_tuple (TupleStruct &item) auto types = std::vector<std::unique_ptr<Type>> (); for (auto &field : item.get_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + types.emplace_back (field.get_field_type ().reconstruct ()); expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), @@ -156,7 +159,7 @@ DeriveEq::visit_struct (StructStruct &item) auto types = std::vector<std::unique_ptr<Type>> (); for (auto &field : item.get_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + types.emplace_back (field.get_field_type ().reconstruct ()); expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), @@ -176,19 +179,20 @@ DeriveEq::visit_enum (Enum &item) case EnumItem::Kind::Discriminant: // nothing to do as they contain no inner types continue; - case EnumItem::Kind::Tuple: { + case EnumItem::Kind::Tuple: + { auto &tuple = static_cast<EnumItemTuple &> (*variant); for (auto &field : tuple.get_tuple_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); - + types.emplace_back (field.get_field_type ().reconstruct ()); break; } - case EnumItem::Kind::Struct: { + case EnumItem::Kind::Struct: + { auto &tuple = static_cast<EnumItemStruct &> (*variant); for (auto &field : tuple.get_struct_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + types.emplace_back (field.get_field_type ().reconstruct ()); break; } @@ -206,7 +210,7 @@ DeriveEq::visit_union (Union &item) auto types = std::vector<std::unique_ptr<Type>> (); for (auto &field : item.get_variants ()) - types.emplace_back (field.get_field_type ().clone_type ()); + types.emplace_back (field.get_field_type ().reconstruct ()); expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), diff --git a/gcc/rust/expand/rust-derive-eq.h b/gcc/rust/expand/rust-derive-eq.h index 17af526..fb187cc 100644 --- a/gcc/rust/expand/rust-derive-eq.h +++ b/gcc/rust/expand/rust-derive-eq.h @@ -31,7 +31,7 @@ class DeriveEq : DeriveVisitor public: DeriveEq (location_t loc); - std::vector<std::unique_ptr<AST::Item>> go (Item &item); + std::vector<std::unique_ptr<Item>> go (Item &item); private: std::vector<std::unique_ptr<Item>> expanded; @@ -70,10 +70,10 @@ private: */ std::unique_ptr<Stmt> assert_type_is_eq (std::unique_ptr<Type> &&type); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-hash.cc b/gcc/rust/expand/rust-derive-hash.cc index 0c9b0f7..616bfdb 100644 --- a/gcc/rust/expand/rust-derive-hash.cc +++ b/gcc/rust/expand/rust-derive-hash.cc @@ -151,7 +151,7 @@ DeriveHash::match_enum_tuple (PathInExpression variant_path, } auto patterns_elts = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (self_patterns))); + new TupleStructItemsNoRest (std::move (self_patterns))); auto pattern = std::unique_ptr<Pattern> ( new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern ( variant_path, std::move (patterns_elts))), @@ -231,14 +231,7 @@ DeriveHash::visit_enum (Enum &item) auto cases = std::vector<MatchCase> (); auto type_name = item.get_identifier ().as_string (); - auto intrinsic = ptrify ( - builder.path_in_expression ({"core", "intrinsics", "discriminant_value"}, - true)); - - auto let_discr - = builder.let (builder.identifier_pattern (DeriveHash::discr), nullptr, - builder.call (std::move (intrinsic), - builder.identifier ("self"))); + auto let_discr = builder.discriminant_value (DeriveHash::discr); auto discr_hash = builder.statementify ( hash_call (builder.ref (builder.identifier (DeriveHash::discr)))); diff --git a/gcc/rust/expand/rust-derive-hash.h b/gcc/rust/expand/rust-derive-hash.h index 02b0bee..67170d0 100644 --- a/gcc/rust/expand/rust-derive-hash.h +++ b/gcc/rust/expand/rust-derive-hash.h @@ -29,7 +29,7 @@ class DeriveHash : DeriveVisitor public: DeriveHash (location_t loc); - std::unique_ptr<AST::Item> go (Item &item); + std::unique_ptr<Item> go (Item &item); private: std::unique_ptr<Item> expanded; @@ -49,10 +49,10 @@ private: MatchCase match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc new file mode 100644 index 0000000..6f3981f --- /dev/null +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -0,0 +1,323 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-derive-ord.h" +#include "rust-ast.h" +#include "rust-derive-cmp-common.h" +#include "rust-derive.h" +#include "rust-item.h" +#include "rust-system.h" + +namespace Rust { +namespace AST { + +DeriveOrd::DeriveOrd (Ordering ordering, location_t loc) + : DeriveVisitor (loc), ordering (ordering) +{} + +std::unique_ptr<Item> +DeriveOrd::go (Item &item) +{ + item.accept_vis (*this); + + return std::move (expanded); +} + +std::unique_ptr<Expr> +DeriveOrd::cmp_call (std::unique_ptr<Expr> &&self_expr, + std::unique_ptr<Expr> &&other_expr) +{ + auto cmp_fn_path = builder.path_in_expression ( + {"core", "cmp", trait (ordering), fn (ordering)}, true); + + return builder.call (ptrify (cmp_fn_path), + vec (builder.ref (std::move (self_expr)), + builder.ref (std::move (other_expr)))); +} + +std::unique_ptr<Item> +DeriveOrd::cmp_impl ( + std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name, + const std::vector<std::unique_ptr<GenericParam>> &type_generics) +{ + auto fn = cmp_fn (std::move (fn_block), type_name); + + auto trait = ordering == Ordering::Partial ? "PartialOrd" : "Ord"; + auto trait_path = builder.type_path ({"core", "cmp", trait}, true); + + auto trait_bound + = builder.trait_bound (builder.type_path ({"core", "cmp", trait}, true)); + + auto trait_items = vec (std::move (fn)); + + auto cmp_generics + = setup_impl_generics (type_name.as_string (), type_generics, + std::move (trait_bound)); + + return builder.trait_impl (trait_path, std::move (cmp_generics.self_type), + std::move (trait_items), + std::move (cmp_generics.impl)); +} + +std::unique_ptr<AssociatedItem> +DeriveOrd::cmp_fn (std::unique_ptr<BlockExpr> &&block, Identifier type_name) +{ + // Ordering + auto return_type = builder.type_path ({"core", "cmp", "Ordering"}, true); + + // In the case of PartialOrd, we return an Option<Ordering> + if (ordering == Ordering::Partial) + { + auto generic = GenericArg::create_type (ptrify (return_type)); + + auto generic_seg = builder.type_path_segment_generic ( + "Option", GenericArgs ({}, {generic}, {}, loc)); + auto core = builder.type_path_segment ("core"); + auto option = builder.type_path_segment ("option"); + + return_type + = builder.type_path (vec (std::move (core), std::move (option), + std::move (generic_seg)), + true); + } + + // &self, other: &Self + auto params = vec ( + builder.self_ref_param (), + builder.function_param (builder.identifier_pattern ("other"), + builder.reference_type (ptrify ( + builder.type_path (type_name.as_string ()))))); + + auto function_name = fn (ordering); + + return builder.function (function_name, std::move (params), + ptrify (return_type), std::move (block)); +} + +std::unique_ptr<Pattern> +DeriveOrd::make_equal () +{ + std::unique_ptr<Pattern> equal = ptrify ( + builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, true)); + + // We need to wrap the pattern in Option::Some if we are doing partial + // ordering + if (ordering == Ordering::Partial) + { + auto pattern_items = std::unique_ptr<TupleStructItems> ( + new TupleStructItemsNoRest (vec (std::move (equal)))); + + equal + = std::make_unique<TupleStructPattern> (builder.path_in_expression ( + LangItem::Kind::OPTION_SOME), + std::move (pattern_items)); + } + + return equal; +} + +std::pair<MatchArm, MatchArm> +DeriveOrd::make_cmp_arms () +{ + // All comparison results other than Ordering::Equal + auto non_equal = builder.identifier_pattern (DeriveOrd::not_equal); + auto equal = make_equal (); + + return {builder.match_arm (std::move (equal)), + builder.match_arm (std::move (non_equal))}; +} + +std::unique_ptr<Expr> +DeriveOrd::recursive_match (std::vector<SelfOther> &&members) +{ + if (members.empty ()) + { + std::unique_ptr<Expr> value = ptrify ( + builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, + true)); + + if (ordering == Ordering::Partial) + value = builder.call (ptrify (builder.path_in_expression ( + LangItem::Kind::OPTION_SOME)), + std::move (value)); + + return value; + } + + std::unique_ptr<Expr> final_expr = nullptr; + + for (auto it = members.rbegin (); it != members.rend (); it++) + { + auto &member = *it; + + auto call = cmp_call (std::move (member.self_expr), + std::move (member.other_expr)); + + // For the last member (so the first iterator), we just create a call + // expression + if (it == members.rbegin ()) + { + final_expr = std::move (call); + continue; + } + + // If we aren't dealing with the last member, then we need to wrap all of + // that in a big match expression and keep going + auto match_arms = make_cmp_arms (); + + auto match_cases + = {builder.match_case (std::move (match_arms.first), + std::move (final_expr)), + builder.match_case (std::move (match_arms.second), + builder.identifier (DeriveOrd::not_equal))}; + + final_expr = builder.match (std::move (call), std::move (match_cases)); + } + + return final_expr; +} + +// we need to do a recursive match expression for all of the fields used in a +// struct so for something like struct Foo { a: i32, b: i32, c: i32 } we must +// first compare each `a` field, then `b`, then `c`, like this: +// +// match cmp_fn(self.<field>, other.<field>) { +// Ordering::Equal => <recurse>, +// cmp => cmp, +// } +// +// and the recurse will be the exact same expression, on the next field. so that +// our result looks like this: +// +// match cmp_fn(self.a, other.a) { +// Ordering::Equal => match cmp_fn(self.b, other.b) { +// Ordering::Equal =>cmp_fn(self.c, other.c), +// cmp => cmp, +// } +// cmp => cmp, +// } +// +// the last field comparison needs not to be a match but just the function call. +// this is going to be annoying lol +void +DeriveOrd::visit_struct (StructStruct &item) +{ + auto fields = SelfOther::fields (builder, item.get_fields ()); + + auto match_expr = recursive_match (std::move (fields)); + + expanded = cmp_impl (builder.block (std::move (match_expr)), + item.get_identifier (), item.get_generic_params ()); +} + +// same as structs, but for each field index instead of each field name - +// straightforward once we have `visit_struct` working +void +DeriveOrd::visit_tuple (TupleStruct &item) +{ + auto fields = SelfOther::indexes (builder, item.get_fields ()); + + auto match_expr = recursive_match (std::move (fields)); + + expanded = cmp_impl (builder.block (std::move (match_expr)), + item.get_identifier (), item.get_generic_params ()); +} + +// for enums, we need to generate a match for each of the enum's variant that +// contains data and then do the same thing as visit_struct or visit_enum. if +// the two aren't the same variant, then compare the two discriminant values for +// all the dataless enum variants and in the general case. +// +// so for enum Foo { A(i32, i32), B, C } we need to do the following +// +// match (self, other) { +// (A(self_0, self_1), A(other_0, other_1)) => { +// match cmp_fn(self_0, other_0) { +// Ordering::Equal => cmp_fn(self_1, other_1), +// cmp => cmp, +// }, +// _ => cmp_fn(discr_value(self), discr_value(other)) +// } +void +DeriveOrd::visit_enum (Enum &item) +{ + // NOTE: We can factor this even further with DerivePartialEq, but this is + // getting out of scope for this PR surely + + auto cases = std::vector<MatchCase> (); + auto type_name = item.get_identifier ().as_string (); + + auto let_sd = builder.discriminant_value (DeriveOrd::self_discr, "self"); + auto let_od = builder.discriminant_value (DeriveOrd::other_discr, "other"); + + auto discr_cmp = cmp_call (builder.identifier (DeriveOrd::self_discr), + builder.identifier (DeriveOrd::other_discr)); + + auto recursive_match_fn = [this] (std::vector<SelfOther> &&fields) { + return recursive_match (std::move (fields)); + }; + + for (auto &variant : item.get_variants ()) + { + auto enum_builder + = EnumMatchBuilder (type_name, variant->get_identifier ().as_string (), + recursive_match_fn, builder); + + switch (variant->get_enum_item_kind ()) + { + case EnumItem::Kind::Struct: + cases.emplace_back (enum_builder.strukt (*variant)); + break; + case EnumItem::Kind::Tuple: + cases.emplace_back (enum_builder.tuple (*variant)); + break; + case EnumItem::Kind::Identifier: + case EnumItem::Kind::Discriminant: + // We don't need to do anything for these, as they are handled by the + // discriminant value comparison + break; + } + } + + // Add the last case which compares the discriminant values in case `self` and + // `other` are actually different variants of the enum + cases.emplace_back ( + builder.match_case (builder.wildcard (), std::move (discr_cmp))); + + auto match + = builder.match (builder.tuple (vec (builder.identifier ("self"), + builder.identifier ("other"))), + std::move (cases)); + + expanded + = cmp_impl (builder.block (vec (std::move (let_sd), std::move (let_od)), + std::move (match)), + type_name, item.get_generic_params ()); +} + +void +DeriveOrd::visit_union (Union &item) +{ + auto trait_name = trait (ordering); + + rust_error_at (item.get_locus (), "derive(%s) cannot be used on unions", + trait_name.c_str ()); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h new file mode 100644 index 0000000..90ce9c8 --- /dev/null +++ b/gcc/rust/expand/rust-derive-ord.h @@ -0,0 +1,122 @@ +// 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/>. + +#ifndef RUST_DERIVE_ORD_H +#define RUST_DERIVE_ORD_H + +#include "rust-ast.h" +#include "rust-derive-cmp-common.h" +#include "rust-derive.h" + +namespace Rust { +namespace AST { + +/** + * DeriveOrd is a bit special as the expansion of both `PartialOrd` and `Ord` + * is extremely similar. The only difference is that `PartialOrd` concerns + * partial-ordering, and thus its main method returns an `Option<Ordering>`, + * while `Ord` concerns total-ordering, and its main method returns an + * `Ordering`. Otherwise, the expansion logic is the same, so we factor both + * derives into one. + */ +class DeriveOrd : public DeriveVisitor +{ +public: + enum class Ordering + { + Total, + Partial + }; + + std::string fn (Ordering ordering) + { + if (ordering == Ordering::Total) + return "cmp"; + else + return "partial_cmp"; + } + + std::string trait (Ordering ordering) + { + if (ordering == Ordering::Total) + return "Ord"; + else + return "PartialOrd"; + } + + DeriveOrd (Ordering ordering, location_t loc); + + std::unique_ptr<Item> go (Item &item); + +private: + std::unique_ptr<Item> expanded; + + Ordering ordering; + + /* Identifier patterns for the non-equal match arms */ + constexpr static const char *not_equal = "#non_eq"; + constexpr static const char *self_discr = "#self_discr"; + constexpr static const char *other_discr = "#other_discr"; + + /** + * Create the recursive matching structure used when implementing the + * comparison function on multiple sub items (fields, tuple indexes...) + */ + std::unique_ptr<Expr> recursive_match (std::vector<SelfOther> &&members); + + /** + * Create a pattern for the `Ordering::Equal` case. In the case of partial + * ordering, `Option::Some(Ordering::Equal)`. + */ + std::unique_ptr<Pattern> make_equal (); + + /** + * Make the match arms for one inner match in a comparison function block. + * This returns the "equal" match arm and the "rest" match arm, so something + * like `Ordering::Equal` and `non_eq` in the following match expression: + * + * match cmp(...) { + * Ordering::Equal => match cmp(...) { ... } + * non_eq => non_eq, + * } + */ + std::pair<MatchArm, MatchArm> make_cmp_arms (); + + /** + * Generate a call to the proper trait function, based on the ordering, in + * order to compare two given expressions + */ + std::unique_ptr<Expr> cmp_call (std::unique_ptr<Expr> &&self_expr, + std::unique_ptr<Expr> &&other_expr); + + std::unique_ptr<Item> + cmp_impl (std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name, + const std::vector<std::unique_ptr<GenericParam>> &type_generics); + std::unique_ptr<AssociatedItem> cmp_fn (std::unique_ptr<BlockExpr> &&block, + Identifier type_name); + + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DERIVE_ORD_H diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index ff66faa..287d8a7 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -64,11 +64,9 @@ DerivePartialEq::partialeq_impls ( } std::unique_ptr<AssociatedItem> -DerivePartialEq::eq_fn (std::unique_ptr<Expr> &&cmp_expression, +DerivePartialEq::eq_fn (std::unique_ptr<BlockExpr> &&block, std::string type_name) { - auto block = builder.block (tl::nullopt, std::move (cmp_expression)); - auto self_type = std::unique_ptr<TypeNoBounds> (new TypePath (builder.type_path ("Self"))); @@ -83,24 +81,6 @@ DerivePartialEq::eq_fn (std::unique_ptr<Expr> &&cmp_expression, std::move (block)); } -DerivePartialEq::SelfOther -DerivePartialEq::tuple_indexes (int idx) -{ - return SelfOther{ - builder.tuple_idx ("self", idx), - builder.tuple_idx ("other", idx), - }; -} - -DerivePartialEq::SelfOther -DerivePartialEq::field_acccesses (const std::string &field_name) -{ - return SelfOther{ - builder.field_access (builder.identifier ("self"), field_name), - builder.field_access (builder.identifier ("other"), field_name), - }; -} - std::unique_ptr<Expr> DerivePartialEq::build_eq_expression ( std::vector<SelfOther> &&field_expressions) @@ -134,12 +114,10 @@ void DerivePartialEq::visit_tuple (TupleStruct &item) { auto type_name = item.get_struct_name ().as_string (); - auto fields = std::vector<SelfOther> (); - - for (size_t idx = 0; idx < item.get_fields ().size (); idx++) - fields.emplace_back (tuple_indexes (idx)); + auto fields = SelfOther::indexes (builder, item.get_fields ()); - auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name); + auto fn = eq_fn (builder.block (build_eq_expression (std::move (fields))), + type_name); expanded = partialeq_impls (std::move (fn), type_name, item.get_generic_params ()); @@ -149,13 +127,10 @@ void DerivePartialEq::visit_struct (StructStruct &item) { auto type_name = item.get_struct_name ().as_string (); - auto fields = std::vector<SelfOther> (); + auto fields = SelfOther::fields (builder, item.get_fields ()); - for (auto &field : item.get_fields ()) - fields.emplace_back ( - field_acccesses (field.get_field_name ().as_string ())); - - auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name); + auto fn = eq_fn (builder.block (build_eq_expression (std::move (fields))), + type_name); expanded = partialeq_impls (std::move (fn), type_name, item.get_generic_params ()); @@ -171,7 +146,7 @@ DerivePartialEq::match_enum_identifier ( builder.ref_pattern ( std::unique_ptr<Pattern> (new PathInExpression (variant_path)))); - auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( std::move (inner_ref_patterns)); auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc); @@ -199,8 +174,6 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path, auto self_pattern_str = "__self_" + std::to_string (i); auto other_pattern_str = "__other_" + std::to_string (i); - rust_debug ("]ARTHUR[ %s", self_pattern_str.c_str ()); - self_patterns.emplace_back ( builder.identifier_pattern (self_pattern_str)); other_patterns.emplace_back ( @@ -213,9 +186,9 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path, } auto self_pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (self_patterns))); + new TupleStructItemsNoRest (std::move (self_patterns))); auto other_pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (other_patterns))); + new TupleStructItemsNoRest (std::move (other_patterns))); auto self_pattern = std::unique_ptr<Pattern> ( new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern ( @@ -226,7 +199,7 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path, variant_path, std::move (other_pattern_items))), false, false, loc)); - auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( vec (std::move (self_pattern), std::move (other_pattern))); auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc); @@ -240,15 +213,55 @@ MatchCase DerivePartialEq::match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant) { - // NOTE: We currently do not support compiling struct patterns where an - // identifier is assigned a new pattern, e.g. Bloop { f0: x } - // This is what we should be using to compile PartialEq for enum struct - // variants, as we need to be comparing the field of each instance meaning we - // need to give two different names to two different instances of the same - // field. We cannot just use the field's name like we do when deriving - // `Clone`. - - rust_unreachable (); + auto self_fields = std::vector<std::unique_ptr<StructPatternField>> (); + auto other_fields = std::vector<std::unique_ptr<StructPatternField>> (); + + auto self_other_exprs = std::vector<SelfOther> (); + + for (auto &field : variant.get_struct_fields ()) + { + // The patterns we're creating for each field are `self_<field>` and + // `other_<field>` where `field` is the name of the field. It doesn't + // actually matter what we use, as long as it's ordered, unique, and that + // we can reuse it in the match case's return expression to check that + // they are equal. + + auto field_name = field.get_field_name ().as_string (); + + auto self_pattern_str = "__self_" + field_name; + auto other_pattern_str = "__other_" + field_name; + + self_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (self_pattern_str))); + other_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (other_pattern_str))); + + self_other_exprs.emplace_back (SelfOther{ + builder.identifier (self_pattern_str), + builder.identifier (other_pattern_str), + }); + } + + auto self_elts = StructPatternElements (std::move (self_fields)); + auto other_elts = StructPatternElements (std::move (other_fields)); + + auto self_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern ( + variant_path, loc, std::move (self_elts))), + false, false, loc)); + auto other_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern ( + variant_path, loc, std::move (other_elts))), + false, false, loc)); + + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc); + + auto expr = build_eq_expression (std::move (self_other_exprs)); + + return builder.match_case (std::move (pattern), std::move (expr)); } void @@ -257,46 +270,56 @@ DerivePartialEq::visit_enum (Enum &item) auto cases = std::vector<MatchCase> (); auto type_name = item.get_identifier ().as_string (); + auto eq_expr_fn = [this] (std::vector<SelfOther> &&fields) { + return build_eq_expression (std::move (fields)); + }; + + auto let_sd + = builder.discriminant_value (DerivePartialEq::self_discr, "self"); + auto let_od + = builder.discriminant_value (DerivePartialEq::other_discr, "other"); + + auto discr_cmp + = builder.comparison_expr (builder.identifier (DerivePartialEq::self_discr), + builder.identifier ( + DerivePartialEq::other_discr), + ComparisonOperator::EQUAL); + for (auto &variant : item.get_variants ()) { - auto variant_path - = builder.variant_path (type_name, - variant->get_identifier ().as_string ()); + auto enum_builder + = EnumMatchBuilder (type_name, variant->get_identifier ().as_string (), + eq_expr_fn, builder); switch (variant->get_enum_item_kind ()) { - case EnumItem::Kind::Identifier: - case EnumItem::Kind::Discriminant: - cases.emplace_back (match_enum_identifier (variant_path, variant)); - break; case EnumItem::Kind::Tuple: - cases.emplace_back ( - match_enum_tuple (variant_path, - static_cast<EnumItemTuple &> (*variant))); + cases.emplace_back (enum_builder.tuple (*variant)); break; case EnumItem::Kind::Struct: - rust_sorry_at ( - item.get_locus (), - "cannot derive(PartialEq) for enum struct variants yet"); + cases.emplace_back (enum_builder.strukt (*variant)); + break; + case EnumItem::Kind::Identifier: + case EnumItem::Kind::Discriminant: + // We don't need to do anything for these, as they are handled by the + // discriminant value comparison break; } } - // NOTE: Mention using discriminant_value and skipping that last case, and - // instead skipping all identifiers/discriminant enum items and returning - // `true` in the wildcard case - // In case the two instances of `Self` don't have the same discriminant, // automatically return false. cases.emplace_back ( - builder.match_case (builder.wildcard (), builder.literal_bool (false))); + builder.match_case (builder.wildcard (), std::move (discr_cmp))); auto match = builder.match (builder.tuple (vec (builder.identifier ("self"), builder.identifier ("other"))), std::move (cases)); - auto fn = eq_fn (std::move (match), type_name); + auto fn = eq_fn (builder.block (vec (std::move (let_sd), std::move (let_od)), + std::move (match)), + type_name); expanded = partialeq_impls (std::move (fn), type_name, item.get_generic_params ()); diff --git a/gcc/rust/expand/rust-derive-partial-eq.h b/gcc/rust/expand/rust-derive-partial-eq.h index ac963a6..7985414 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.h +++ b/gcc/rust/expand/rust-derive-partial-eq.h @@ -21,6 +21,7 @@ #include "rust-derive.h" #include "rust-path.h" +#include "rust-derive-cmp-common.h" namespace Rust { namespace AST { @@ -30,7 +31,7 @@ class DerivePartialEq : DeriveVisitor public: DerivePartialEq (location_t loc); - std::vector<std::unique_ptr<AST::Item>> go (Item &item); + std::vector<std::unique_ptr<Item>> go (Item &item); private: std::vector<std::unique_ptr<Item>> expanded; @@ -43,23 +44,10 @@ private: std::unique_ptr<AssociatedItem> &&eq_fn, std::string name, const std::vector<std::unique_ptr<GenericParam>> &type_generics); - std::unique_ptr<AssociatedItem> eq_fn (std::unique_ptr<Expr> &&cmp_expression, + std::unique_ptr<AssociatedItem> eq_fn (std::unique_ptr<BlockExpr> &&block, std::string type_name); /** - * A pair of two expressions from each instance being compared. E.g. this - * could be `self.0` and `other.0`, or `self.field` and `other.field` - */ - struct SelfOther - { - std::unique_ptr<Expr> self_expr; - std::unique_ptr<Expr> other_expr; - }; - - SelfOther tuple_indexes (int idx); - SelfOther field_acccesses (const std::string &field_name); - - /** * Build a suite of equality arithmetic expressions chained together by a * boolean AND operator */ @@ -73,10 +61,13 @@ private: MatchCase match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + constexpr static const char *self_discr = "#self_discr"; + constexpr static const char *other_discr = "#other_discr"; + + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index 015b81e..2777f07 100644 --- a/gcc/rust/expand/rust-derive.cc +++ b/gcc/rust/expand/rust-derive.cc @@ -22,8 +22,10 @@ #include "rust-derive-debug.h" #include "rust-derive-default.h" #include "rust-derive-eq.h" +#include "rust-derive-ord.h" #include "rust-derive-partial-eq.h" #include "rust-derive-hash.h" +#include "rust-system.h" namespace Rust { namespace AST { @@ -38,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: @@ -59,10 +71,11 @@ DeriveVisitor::derive (Item &item, const Attribute &attr, case BuiltinMacro::Hash: return vec (DeriveHash (loc).go (item)); case BuiltinMacro::Ord: + return vec (DeriveOrd (DeriveOrd::Ordering::Total, loc).go (item)); case BuiltinMacro::PartialOrd: + return vec (DeriveOrd (DeriveOrd::Ordering::Partial, loc).go (item)); default: - rust_sorry_at (loc, "unimplemented builtin derive macro"); - return {}; + rust_unreachable (); }; } @@ -79,7 +92,8 @@ DeriveVisitor::setup_impl_generics ( { switch (generic->get_kind ()) { - case GenericParam::Kind::Lifetime: { + case GenericParam::Kind::Lifetime: + { LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get (); Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ()); @@ -91,7 +105,8 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Type: { + case GenericParam::Kind::Type: + { TypeParam &type_param = (TypeParam &) *generic.get (); std::unique_ptr<Type> associated_type = builder.single_type_path ( @@ -104,7 +119,8 @@ DeriveVisitor::setup_impl_generics ( std::vector<std::unique_ptr<TypeParamBound>> extra_bounds; if (extra_bound) - extra_bounds.emplace_back (std::move (*extra_bound)); + extra_bounds.emplace_back ( + extra_bound.value ()->clone_type_param_bound ()); auto impl_type_param = builder.new_type_param (type_param, std::move (extra_bounds)); @@ -113,17 +129,20 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Const: { - rust_unreachable (); + case GenericParam::Kind::Const: + { + ConstGenericParam &const_param + = (ConstGenericParam &) *generic.get (); - // TODO - // const ConstGenericParam *const_param - // = (const ConstGenericParam *) generic.get (); - // std::unique_ptr<Expr> const_expr = nullptr; + std::unique_ptr<Type> associated_type + = builder.single_type_path (const_param.get_name ().as_string ()); + + GenericArg type_arg + = GenericArg::create_type (std::move (associated_type)); + generic_args.push_back (std::move (type_arg)); - // GenericArg type_arg - // = GenericArg::create_const (std::move (const_expr)); - // generic_args.push_back (std::move (type_arg)); + auto impl_const_param = builder.new_const_param (const_param); + impl_generics.push_back (std::move (impl_const_param)); } break; } diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index d8cc0a4..d28bba9 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -118,7 +118,7 @@ private: virtual void visit (LiteralExpr &expr) override final{}; virtual void visit (AttrInputLiteral &attr_input) override final{}; virtual void visit (MetaItemLitExpr &meta_item) override final{}; - virtual void visit (MetaItemPathLit &meta_item) override final{}; + virtual void visit (MetaItemPathExpr &meta_item) override final{}; virtual void visit (BorrowExpr &expr) override final{}; virtual void visit (DereferenceExpr &expr) override final{}; virtual void visit (ErrorPropagationExpr &expr) override final{}; @@ -147,6 +147,8 @@ private: virtual void visit (FieldAccessExpr &expr) override final{}; virtual void visit (ClosureExprInner &expr) override final{}; virtual void visit (BlockExpr &expr) override final{}; + virtual void visit (AnonConst &expr) override final{}; + virtual void visit (ConstBlock &expr) override final{}; virtual void visit (ClosureExprInnerTyped &expr) override final{}; virtual void visit (ContinueExpr &expr) override final{}; virtual void visit (BreakExpr &expr) override final{}; @@ -157,6 +159,7 @@ private: virtual void visit (RangeFromToInclExpr &expr) override final{}; virtual void visit (RangeToInclExpr &expr) override final{}; virtual void visit (ReturnExpr &expr) override final{}; + virtual void visit (TryExpr &expr) override final{}; virtual void visit (BoxExpr &expr) override final{}; virtual void visit (UnsafeBlockExpr &expr) override final{}; virtual void visit (LoopExpr &expr) override final{}; @@ -171,6 +174,7 @@ private: virtual void visit (AwaitExpr &expr) override final{}; virtual void visit (AsyncBlockExpr &expr) override final{}; virtual void visit (InlineAsm &expr) override final{}; + virtual void visit (LlvmInlineAsm &expr) override final{}; virtual void visit (TypeParam ¶m) override final{}; virtual void visit (LifetimeWhereClauseItem &item) override final{}; virtual void visit (TypeBoundWhereClauseItem &item) override final{}; @@ -188,7 +192,6 @@ private: virtual void visit (EnumItemDiscriminant &item) override final{}; virtual void visit (ConstantItem &const_item) override final{}; virtual void visit (StaticItem &static_item) override final{}; - virtual void visit (TraitItemConst &item) override final{}; virtual void visit (TraitItemType &item) override final{}; virtual void visit (Trait &trait) override final{}; virtual void visit (InherentImpl &impl) override final{}; @@ -220,13 +223,15 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override final{}; virtual void visit (StructPatternFieldIdent &field) override final{}; virtual void visit (StructPattern &pattern) override final{}; - virtual void visit (TupleStructItemsNoRange &tuple_items) override final{}; - virtual void visit (TupleStructItemsRange &tuple_items) override final{}; + virtual void visit (TupleStructItemsNoRest &tuple_items) override final{}; + virtual void visit (TupleStructItemsHasRest &tuple_items) override final{}; virtual void visit (TupleStructPattern &pattern) override final{}; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override final{}; - virtual void visit (TuplePatternItemsRanged &tuple_items) override final{}; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override final{}; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override final{}; virtual void visit (TuplePattern &pattern) override final{}; virtual void visit (GroupedPattern &pattern) override final{}; + virtual void visit (SlicePatternItemsNoRest &items) override final{}; + virtual void visit (SlicePatternItemsHasRest &items) override final{}; virtual void visit (SlicePattern &pattern) override final{}; virtual void visit (AltPattern &pattern) override final{}; virtual void visit (EmptyStmt &stmt) override final{}; @@ -250,9 +255,10 @@ private: virtual void visit (FunctionParam ¶m) override final{}; virtual void visit (VariadicParam ¶m) override final{}; virtual void visit (FormatArgs ¶m) override final{}; + virtual void visit (OffsetOf ¶m) override final{}; }; } // namespace AST } // namespace Rust -#endif // DERIVE_VISITOR_H +#endif // DERIVE_VISITOR_H
\ No newline at end of file diff --git a/gcc/rust/expand/rust-expand-format-args.cc b/gcc/rust/expand/rust-expand-format-args.cc index af6182f..bda28dd 100644 --- a/gcc/rust/expand/rust-expand-format-args.cc +++ b/gcc/rust/expand/rust-expand-format-args.cc @@ -85,11 +85,13 @@ expand_format_args (AST::FormatArgs &fmt, static_pieces.emplace_back ( builder.literal_string (node.string._0.to_string ())); break; - case ffi::Piece::Tag::NextArgument: { + case ffi::Piece::Tag::NextArgument: + { auto next_argument = node.next_argument._0; switch (node.next_argument._0.position.tag) { - case ffi::Position::Tag::ArgumentImplicitlyIs: { + case ffi::Position::Tag::ArgumentImplicitlyIs: + { auto idx = next_argument.position.argument_implicitly_is._0; auto trait = next_argument.format; auto arg = arguments.at (idx); diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index d4db313..6e98a5c 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -18,6 +18,8 @@ #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" #include "rust-ast.h" @@ -47,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>> @@ -62,7 +67,9 @@ derive_item (AST::Item &item, AST::SimplePath &to_derive, { switch (node.get_kind ()) { - case AST::SingleASTNode::ITEM: + 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: @@ -85,7 +92,7 @@ expand_item_attribute (AST::Item &item, AST::SimplePath &name, { switch (node.get_kind ()) { - case AST::SingleASTNode::ITEM: + case AST::SingleASTNode::Kind::Item: result.push_back (node.take_item ()); break; default: @@ -114,7 +121,7 @@ expand_stmt_attribute (T &statement, AST::SimplePath &attribute, { switch (node.get_kind ()) { - case AST::SingleASTNode::STMT: + case AST::SingleASTNode::Kind::Stmt: result.push_back (node.take_stmt ()); break; default: @@ -233,10 +240,7 @@ ExpandVisitor::expand_inner_items ( } } - std::function<std::unique_ptr<AST::Item> (AST::SingleASTNode)> extractor - = [] (AST::SingleASTNode node) { return node.take_item (); }; - - expand_macro_children (items, extractor); + expand_macro_children (items, &AST::SingleASTNode::take_item); expander.pop_context (); } @@ -324,10 +328,7 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr) if (!expr.has_tail_expr ()) expr.normalize_tail_expr (); - std::function<std::unique_ptr<AST::Stmt> (AST::SingleASTNode)> extractor - = [] (AST::SingleASTNode node) { return node.take_stmt (); }; - - expand_macro_children (stmts, extractor); + expand_macro_children (stmts, &AST::SingleASTNode::take_stmt); expander.pop_context (); } @@ -335,10 +336,15 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr) void ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr) { + NodeId old_expect = expr->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); + expander.push_context (MacroExpander::ContextType::EXPR); expr->accept_vis (*this); expander.pop_context (); + std::swap (macro_invoc_expect_id, old_expect); + auto final_fragment = expander.take_expanded_fragment (); if (final_fragment.should_expand () && final_fragment.is_expression_fragment ()) @@ -348,14 +354,54 @@ ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr) void ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type) { - expander.push_context (MacroExpander::ContextType::TYPE); + NodeId old_expect = type->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); + expander.push_context (MacroExpander::ContextType::TYPE); type->accept_vis (*this); + expander.pop_context (); + + std::swap (macro_invoc_expect_id, old_expect); + auto final_fragment = expander.take_expanded_fragment (); if (final_fragment.should_expand () && final_fragment.is_type_fragment ()) type = final_fragment.take_type_fragment (); +} + +// HACK: maybe we shouldn't have TypeNoBounds as a base class +void +ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type) +{ + NodeId old_expect = type->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); + + expander.push_context (MacroExpander::ContextType::TYPE); + type->accept_vis (*this); + expander.pop_context (); + + std::swap (macro_invoc_expect_id, old_expect); + + auto final_fragment = expander.take_expanded_fragment (); + if (final_fragment.should_expand () && final_fragment.is_type_fragment ()) + type = std::make_unique<AST::ParenthesisedType> ( + final_fragment.take_type_fragment (), BUILTINS_LOCATION); +} + +void +ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern) +{ + NodeId old_expect = pattern->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); + expander.push_context (MacroExpander::ContextType::PATTERN); + pattern->accept_vis (*this); expander.pop_context (); + + std::swap (macro_invoc_expect_id, old_expect); + + auto final_fragment = expander.take_expanded_fragment (); + if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ()) + pattern = final_fragment.take_pattern_fragment (); } // FIXME: Can this be refactored into a `scoped` method? Which takes a @@ -430,6 +476,8 @@ ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> ¶ms) { for (auto ¶m : params) { + maybe_expand_pattern (param.get_pattern_ptr ()); + if (param.has_type_given ()) maybe_expand_type (param.get_type_ptr ()); } @@ -471,6 +519,14 @@ ExpandVisitor::visit (AST::ConstGenericParam &) void ExpandVisitor::visit (AST::MacroInvocation ¯o_invoc) { + if (macro_invoc_expect_id != macro_invoc.get_node_id ()) + { + rust_internal_error_at ( + macro_invoc.get_locus (), + "attempting to expand node with id %d into position with node id %d", + (int) macro_invoc.get_node_id (), (int) macro_invoc_expect_id); + } + // TODO: Can we do the AST fragment replacing here? Probably not, right? expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon () ? AST::InvocKind::Semicoloned @@ -489,7 +545,8 @@ ExpandVisitor::visit (AST::PathInExpression &path) void ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment) { - expand_generic_args (segment.get_generic_args ()); + if (segment.has_generic_args ()) + expand_generic_args (segment.get_generic_args ()); } void @@ -543,16 +600,10 @@ ExpandVisitor::visit (AST::MetaItemLitExpr &) {} void -ExpandVisitor::visit (AST::MetaItemPathLit &) +ExpandVisitor::visit (AST::MetaItemPathExpr &) {} void -ExpandVisitor::visit (AST::ErrorPropagationExpr &expr) -{ - visit (expr.get_propagating_expr ()); -} - -void ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr) { maybe_expand_expr (expr.get_left_expr_ptr ()); @@ -574,6 +625,13 @@ ExpandVisitor::visit (AST::LazyBooleanExpr &expr) } void +ExpandVisitor::visit (AST::TypeCastExpr &expr) +{ + maybe_expand_expr (expr.get_casted_expr_ptr ()); + maybe_expand_type (expr.get_type_to_cast_to_ptr ()); +} + +void ExpandVisitor::visit (AST::AssignmentExpr &expr) { maybe_expand_expr (expr.get_left_expr_ptr ()); @@ -607,20 +665,11 @@ ExpandVisitor::visit (AST::CallExpr &expr) } void -ExpandVisitor::visit (AST::MethodCallExpr &expr) -{ - visit (expr.get_receiver_expr ()); - - for (auto ¶m : expr.get_params ()) - maybe_expand_expr (param); -} - -void ExpandVisitor::visit (AST::ClosureExprInner &expr) { expand_closure_params (expr.get_params ()); - visit (expr.get_definition_expr ()); + maybe_expand_expr (expr.get_definition_expr_ptr ()); } void @@ -640,7 +689,7 @@ ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr) maybe_expand_type (expr.get_return_type_ptr ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void @@ -682,22 +731,10 @@ ExpandVisitor::visit (AST::IfLetExprConseqElse &expr) } void -ExpandVisitor::visit (AST::MatchExpr &expr) +ExpandVisitor::visit (AST::TupleExpr &expr) { - visit (expr.get_scrutinee_expr ()); - - for (auto &match_case : expr.get_match_cases ()) - { - auto &arm = match_case.get_arm (); - - for (auto &pattern : arm.get_patterns ()) - visit (pattern); - - if (arm.has_match_arm_guard ()) - maybe_expand_expr (arm.get_guard_expr_ptr ()); - - maybe_expand_expr (match_case.get_expr_ptr ()); - } + for (auto &sub : expr.get_tuple_elems ()) + maybe_expand_expr (sub); } void @@ -843,15 +880,6 @@ ExpandVisitor::visit (AST::StaticItem &static_item) } void -ExpandVisitor::visit (AST::TraitItemConst &const_item) -{ - maybe_expand_type (const_item.get_type_ptr ()); - - if (const_item.has_expr ()) - maybe_expand_expr (const_item.get_expr_ptr ()); -} - -void ExpandVisitor::visit (AST::Trait &trait) { for (auto &generic : trait.get_generic_params ()) @@ -865,12 +893,9 @@ ExpandVisitor::visit (AST::Trait &trait) expander.push_context (MacroExpander::ContextType::TRAIT); - std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)> - extractor - = [] (AST::SingleASTNode node) { return node.take_assoc_item (); }; - expand_macro_children (MacroExpander::ContextType::TRAIT, - trait.get_trait_items (), extractor); + trait.get_trait_items (), + &AST::SingleASTNode::take_assoc_item); expander.pop_context (); } @@ -893,12 +918,9 @@ ExpandVisitor::visit (AST::InherentImpl &impl) if (impl.has_where_clause ()) expand_where_clause (impl.get_where_clause ()); - std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)> - extractor - = [] (AST::SingleASTNode node) { return node.take_assoc_item (); }; - expand_macro_children (MacroExpander::ContextType::IMPL, - impl.get_impl_items (), extractor); + impl.get_impl_items (), + &AST::SingleASTNode::take_assoc_item); } void @@ -921,12 +943,9 @@ ExpandVisitor::visit (AST::TraitImpl &impl) if (impl.has_where_clause ()) expand_where_clause (impl.get_where_clause ()); - std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)> - extractor - = [] (AST::SingleASTNode node) { return node.take_assoc_item (); }; - expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL, - impl.get_impl_items (), extractor); + impl.get_impl_items (), + &AST::SingleASTNode::take_assoc_item); } void @@ -943,12 +962,10 @@ void ExpandVisitor::visit (AST::ExternBlock &block) { visit_inner_attrs (block); - std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)> - extractor - = [] (AST::SingleASTNode node) { return node.take_external_item (); }; expand_macro_children (MacroExpander::ContextType::EXTERN, - block.get_extern_items (), extractor); + block.get_extern_items (), + &AST::SingleASTNode::take_external_item); } void @@ -986,13 +1003,70 @@ ExpandVisitor::visit (AST::StructPatternFieldIdent &field) void ExpandVisitor::visit (AST::GroupedPattern &pattern) { - visit (pattern.get_pattern_in_parens ()); + maybe_expand_pattern (pattern.get_pattern_in_parens_ptr ()); +} + +void +ExpandVisitor::visit (AST::SlicePatternItemsNoRest &items) +{ + for (auto &sub : items.get_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::SlicePatternItemsHasRest &items) +{ + for (auto &sub : items.get_lower_patterns ()) + maybe_expand_pattern (sub); + for (auto &sub : items.get_upper_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::AltPattern &pattern) +{ + for (auto &alt : pattern.get_alts ()) + maybe_expand_pattern (alt); +} + +void +ExpandVisitor::visit (AST::TupleStructItemsNoRest &tuple_items) +{ + for (auto &sub : tuple_items.get_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::TupleStructItemsHasRest &tuple_items) +{ + for (auto &sub : tuple_items.get_lower_patterns ()) + maybe_expand_pattern (sub); + + for (auto &sub : tuple_items.get_upper_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items) +{ + for (auto &sub : tuple_items.get_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items) +{ + for (auto &sub : tuple_items.get_lower_patterns ()) + maybe_expand_pattern (sub); + + for (auto &sub : tuple_items.get_upper_patterns ()) + maybe_expand_pattern (sub); } void ExpandVisitor::visit (AST::LetStmt &stmt) { - visit (stmt.get_pattern ()); + maybe_expand_pattern (stmt.get_pattern_ptr ()); if (stmt.has_type ()) maybe_expand_type (stmt.get_type_ptr ()); @@ -1022,10 +1096,18 @@ ExpandVisitor::visit (AST::BareFunctionType &type) void ExpandVisitor::visit (AST::FunctionParam ¶m) { + maybe_expand_pattern (param.get_pattern_ptr ()); maybe_expand_type (param.get_type_ptr ()); } void +ExpandVisitor::visit (AST::VariadicParam ¶m) +{ + if (param.has_pattern ()) + maybe_expand_pattern (param.get_pattern_ptr ()); +} + +void ExpandVisitor::visit (AST::SelfParam ¶m) { /* TODO: maybe check for invariants being violated - e.g. both type and diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index ad237c0..b79eb66 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -19,7 +19,9 @@ #ifndef RUST_EXPAND_VISITOR_H #define RUST_EXPAND_VISITOR_H +#include "rust-ast-pointer-visitor.h" #include "rust-ast-visitor.h" +#include "rust-item.h" #include "rust-macro-expand.h" #include "rust-proc-macro.h" @@ -28,36 +30,55 @@ namespace Rust { /** * Whether or not an attribute is a derive attribute */ -bool -is_derive (AST::Attribute &attr); +bool is_derive (AST::Attribute &attr); /** * Whether or not an attribute is builtin */ -bool -is_builtin (AST::Attribute &attr); +bool is_builtin (AST::Attribute &attr); -class ExpandVisitor : public AST::DefaultASTVisitor +class ExpandVisitor : public AST::PointerVisitor { public: - ExpandVisitor (MacroExpander &expander) : expander (expander) {} + ExpandVisitor (MacroExpander &expander) + : expander (expander), macro_invoc_expect_id (UNKNOWN_NODEID) + {} /* Expand all of the macro invocations currently contained in a crate */ void go (AST::Crate &crate); - using AST::DefaultASTVisitor::visit; + using AST::PointerVisitor::reseat; + using AST::PointerVisitor::visit; - /* - Maybe expand a macro invocation in lieu of an expression - expr : Core guidelines R33, this function reseat the pointer. - */ - void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr); + void reseat (std::unique_ptr<AST::Expr> &ptr) override + { + maybe_expand_expr (ptr); + } - /* - Maybe expand a macro invocation in lieu of a type - type : Core guidelines R33, this function reseat the pointer. + void reseat (std::unique_ptr<AST::Type> &ptr) override + { + maybe_expand_type (ptr); + } + + void reseat (std::unique_ptr<AST::TypeNoBounds> &ptr) override + { + maybe_expand_type (ptr); + } + + void reseat (std::unique_ptr<AST::Pattern> &ptr) override + { + maybe_expand_pattern (ptr); + } + + /** + * Maybe expand a macro invocation in lieu of an expression, type or pattern. + * + * @ptr Core guidelines R33, this function reseats the pointer. */ - void maybe_expand_type (std::unique_ptr<AST::Type> &type); + void maybe_expand_expr (std::unique_ptr<AST::Expr> &ptr); + void maybe_expand_type (std::unique_ptr<AST::Type> &ptr); + void maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type); + void maybe_expand_pattern (std::unique_ptr<AST::Pattern> &ptr); /** * Expand all macro invocations in lieu of types within a vector of struct @@ -107,7 +128,7 @@ public: */ template <typename T, typename U> void expand_macro_children (MacroExpander::ContextType ctx, T &values, - std::function<U (AST::SingleASTNode)> extractor) + U (AST::SingleASTNode::*extractor) (void)) { expander.push_context (ctx); @@ -123,14 +144,17 @@ public: */ template <typename T, typename U> void expand_macro_children (T &values, - std::function<U (AST::SingleASTNode)> extractor) + U (AST::SingleASTNode::*extractor) (void)) { for (auto it = values.begin (); it != values.end ();) { auto &value = *it; // Perform expansion + NodeId old_expect = value->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); value->accept_vis (*this); + std::swap (macro_invoc_expect_id, old_expect); auto final_fragment = expander.take_expanded_fragment (); @@ -140,7 +164,7 @@ public: it = values.erase (it); for (auto &node : final_fragment.get_nodes ()) { - U new_node = extractor (node); + U new_node = (node.*extractor) (); if (new_node != nullptr) { it = values.insert (it, std::move (new_node)); @@ -211,18 +235,17 @@ public: void visit (AST::AttrInputLiteral &) override; void visit (AST::AttrInputMacro &) override; void visit (AST::MetaItemLitExpr &) override; - void visit (AST::MetaItemPathLit &) override; - void visit (AST::ErrorPropagationExpr &expr) override; + void visit (AST::MetaItemPathExpr &) override; void visit (AST::ArithmeticOrLogicalExpr &expr) override; void visit (AST::ComparisonExpr &expr) override; void visit (AST::LazyBooleanExpr &expr) override; + void visit (AST::TypeCastExpr &expr) override; void visit (AST::AssignmentExpr &expr) override; void visit (AST::CompoundAssignmentExpr &expr) override; void visit (AST::GroupedExpr &expr) override; void visit (AST::StructExprStruct &expr) override; void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; void visit (AST::ClosureExprInner &expr) override; void visit (AST::BlockExpr &expr) override; @@ -233,7 +256,7 @@ public: void visit (AST::IfExprConseqElse &expr) override; void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::MatchExpr &expr) override; + void visit (AST::TupleExpr &expr) override; void visit (AST::TypeParam ¶m) override; void visit (AST::LifetimeWhereClauseItem &) override; void visit (AST::TypeBoundWhereClauseItem &item) override; @@ -253,7 +276,6 @@ public: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemConst &item) override; void visit (AST::Trait &trait) override; void visit (AST::InherentImpl &impl) override; void visit (AST::TraitImpl &impl) override; @@ -271,12 +293,20 @@ public: void visit (AST::MetaListNameValueStr &) override; void visit (AST::StructPatternFieldIdent &field) override; void visit (AST::GroupedPattern &pattern) override; + void visit (AST::SlicePatternItemsNoRest &items) override; + void visit (AST::SlicePatternItemsHasRest &items) override; + void visit (AST::AltPattern &pattern) override; + void visit (AST::TupleStructItemsNoRest &tuple_items) override; + void visit (AST::TupleStructItemsHasRest &tuple_items) override; + void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + void visit (AST::TuplePatternItemsHasRest &tuple_items) override; void visit (AST::LetStmt &stmt) override; void visit (AST::ExprStmt &stmt) override; void visit (AST::BareFunctionType &type) override; - void visit (AST::FunctionParam &type) override; + void visit (AST::FunctionParam ¶m) override; + void visit (AST::VariadicParam ¶m) override; void visit (AST::SelfParam &type) override; template <typename T> @@ -289,6 +319,7 @@ public: private: MacroExpander &expander; + NodeId macro_invoc_expect_id; }; } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index 4d02604..c991ca7 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -22,20 +22,9 @@ #include "rust-ast.h" #include "rust-fmt.h" #include "rust-stmt.h" +#include "rust-parse.h" namespace Rust { -std::map<AST::InlineAsmOption, std::string> InlineAsmOptionMap{ - {AST::InlineAsmOption::PURE, "pure"}, - {AST::InlineAsmOption::NOMEM, "nomem"}, - {AST::InlineAsmOption::READONLY, "readonly"}, - {AST::InlineAsmOption::PRESERVES_FLAGS, "preserves_flags"}, - {AST::InlineAsmOption::NORETURN, "noreturn"}, - {AST::InlineAsmOption::NOSTACK, "nostack"}, - {AST::InlineAsmOption::MAY_UNWIND, "may_unwind"}, - {AST::InlineAsmOption::ATT_SYNTAX, "att_syntax"}, - {AST::InlineAsmOption::RAW, "raw"}, -}; - std::set<std::string> potentially_nonpromoted_keywords = {"in", "out", "lateout", "inout", "inlateout", "const", "sym", "label"}; @@ -112,7 +101,7 @@ parse_clobber_abi (InlineAsmContext inline_asm_ctx) if (token->get_id () == STRING_LITERAL) { // TODO: Caring for span in here. - new_abis.push_back ({token->as_string (), token->get_locus ()}); + new_abis.emplace_back (token->as_string (), token->get_locus ()); } else { @@ -395,6 +384,7 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx) { auto &parser = inline_asm_ctx.parser; auto token = parser.peek_current_token (); + location_t locus = token->get_locus (); if (!inline_asm_ctx.is_global_asm () && check_identifier (parser, "inout")) { @@ -412,10 +402,8 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx) // TODO: Is error propogation our top priority, the ? in rust's asm.rs is // doing a lot of work. - // TODO: Not sure how to use parse_expr - if (!check_identifier (parser, "")) - rust_unreachable (); - // auto expr = parse_format_string (inline_asm_ctx); + std::unique_ptr<AST::Expr> in_expr = parser.parse_expr (); + rust_assert (in_expr != nullptr); std::unique_ptr<AST::Expr> out_expr; @@ -425,11 +413,19 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx) { // auto result = parse_format_string (inline_asm_ctx); - if (!check_identifier (parser, "")) - rust_unreachable (); - // out_expr = parser.parse_expr(); + out_expr = parser.parse_expr (); + + AST::InlineAsmOperand::SplitInOut splitinout ( + reg, false, std::move (in_expr), std::move (out_expr)); + + inline_asm_ctx.inline_asm.operands.emplace_back (splitinout, + locus); + + return inline_asm_ctx; } + rust_unreachable (); + // TODO: Rembmer to pass in clone_expr() instead of nullptr // https://github.com/rust-lang/rust/blob/a3167859f2fd8ff2241295469876a2b687280bdc/compiler/rustc_builtin_macros/src/asm.rs#L135 // RUST VERSION: ast::InlineAsmOperand::SplitInOut { reg, in_expr: @@ -443,6 +439,8 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx) } else { + AST::InlineAsmOperand::InOut inout (reg, false, std::move (in_expr)); + inline_asm_ctx.inline_asm.operands.emplace_back (inout, locus); // https://github.com/rust-lang/rust/blob/a3167859f2fd8ff2241295469876a2b687280bdc/compiler/rustc_builtin_macros/src/asm.rs#L137 // RUST VERSION: ast::InlineAsmOperand::InOut { reg, expr, late: false // } @@ -499,7 +497,7 @@ parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx) } void -check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option) +check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsm::Option option) { auto &parser = inline_asm_ctx.parser; auto &inline_asm = inline_asm_ctx.inline_asm; @@ -508,7 +506,7 @@ check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option) // TODO: report an error of duplication rust_error_at (parser.peek_current_token ()->get_locus (), "the %qs option was already provided", - InlineAsmOptionMap[option].c_str ()); + AST::InlineAsm::option_to_string (option).c_str ()); return; } else @@ -535,39 +533,40 @@ parse_options (InlineAsmContext &inline_asm_ctx) { if (!is_global_asm && check_identifier (parser, "pure")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::PURE); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::PURE); } else if (!is_global_asm && check_identifier (parser, "nomem")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOMEM); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOMEM); } else if (!is_global_asm && check_identifier (parser, "readonly")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::READONLY); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::READONLY); } else if (!is_global_asm && check_identifier (parser, "preserves_flags")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::PRESERVES_FLAGS); + check_and_set (inline_asm_ctx, + AST::InlineAsm::Option::PRESERVES_FLAGS); } else if (!is_global_asm && check_identifier (parser, "noreturn")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NORETURN); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NORETURN); } else if (!is_global_asm && check_identifier (parser, "nostack")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOSTACK); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOSTACK); } else if (!is_global_asm && check_identifier (parser, "may_unwind")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::MAY_UNWIND); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::MAY_UNWIND); } else if (check_identifier (parser, "att_syntax")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::ATT_SYNTAX); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::ATT_SYNTAX); } else if (check_identifier (parser, "raw")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::RAW); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::RAW); } else { @@ -660,6 +659,15 @@ MacroBuiltin::asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc, return parse_asm (invoc_locus, invoc, semicolon, is_global_asm); } +tl::optional<AST::Fragment> +MacroBuiltin::llvm_asm_handler (location_t invoc_locus, + AST::MacroInvocData &invoc, + AST::InvocKind semicolon, + AST::AsmKind is_global_asm) +{ + return parse_llvm_asm (invoc_locus, invoc, semicolon, is_global_asm); +} + tl::expected<InlineAsmContext, InlineAsmParseError> parse_asm_arg (InlineAsmContext inline_asm_ctx) { @@ -671,6 +679,14 @@ parse_asm_arg (InlineAsmContext inline_asm_ctx) { token = parser.peek_current_token (); + if (token->get_id () == COLON || token->get_id () == SCOPE_RESOLUTION) + { + rust_error_at ( + token->get_locus (), + "the legacy LLVM-style %<asm!%> syntax is no longer supported"); + return tl::unexpected<InlineAsmParseError> (COMMITTED); + } + // We accept a comma token here. if (token->get_id () != COMMA && inline_asm_ctx.consumed_comma_without_formatted_string) @@ -771,12 +787,12 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx) auto pieces = Fmt::Pieces::collect (template_str.symbol, false, Fmt::ffi::ParseMode::InlineAsm); - auto pieces_vec = pieces.get_pieces (); + auto &pieces_vec = pieces.get_pieces (); std::string transformed_template_str = ""; for (size_t i = 0; i < pieces_vec.size (); i++) { - auto piece = pieces_vec[i]; + auto &piece = pieces_vec[i]; if (piece.tag == Fmt::ffi::Piece::Tag::String) { transformed_template_str += piece.string._0.to_string (); @@ -789,7 +805,8 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx) auto next_argument = piece.next_argument._0; switch (piece.next_argument._0.position.tag) { - case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: { + case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: + { auto idx = next_argument.position.argument_implicitly_is._0; /*auto trait = next_argument.format;*/ /*auto arg = arguments.at (idx);*/ @@ -811,6 +828,11 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx) } break; case Fmt::ffi::Position::Tag::ArgumentIs: + { + auto idx = next_argument.position.argument_is._0; + transformed_template_str += "%" + std::to_string (idx); + break; + } case Fmt::ffi::Position::Tag::ArgumentNamed: rust_sorry_at (inline_asm.get_locus (), "unhandled argument position specifier"); @@ -858,7 +880,8 @@ parse_asm (location_t invoc_locus, AST::MacroInvocData &invoc, // context. if (resulting_context) { - auto node = (*resulting_context).inline_asm.clone_expr_without_block (); + auto resulting_ctx = resulting_context.value (); + auto node = resulting_ctx.inline_asm.clone_expr_without_block (); std::vector<AST::SingleASTNode> single_vec = {}; @@ -915,7 +938,9 @@ parse_format_strings (InlineAsmContext inline_asm_ctx) { if (!parser.skip_token (COMMA)) { - break; + rust_error_at (parser.peek_current_token ()->get_locus (), + "expected token %qs", ";"); + return tl::unexpected<InlineAsmParseError> (COMMITTED); } // Ok after the comma is good, we better be parsing correctly // everything in here, which is formatted string in ABNF @@ -962,4 +987,228 @@ validate (InlineAsmContext inline_asm_ctx) { return tl::expected<InlineAsmContext, InlineAsmParseError> (inline_asm_ctx); } + +tl::optional<LlvmAsmContext> +parse_llvm_templates (LlvmAsmContext ctx) +{ + auto &parser = ctx.parser; + + auto token = parser.peek_current_token (); + + if (token->get_id () == ctx.last_token_id + || token->get_id () != STRING_LITERAL) + { + return tl::nullopt; + } + + ctx.llvm_asm.get_templates ().emplace_back (token->get_locus (), + strip_double_quotes ( + token->as_string ())); + ctx.parser.skip_token (); + + token = parser.peek_current_token (); + if (token->get_id () != ctx.last_token_id && token->get_id () != COLON + && token->get_id () != SCOPE_RESOLUTION) + { + // We do not handle multiple template string, we provide minimal support + // for the black_box intrinsics. + rust_unreachable (); + } + + return ctx; +} + +tl::optional<LlvmAsmContext> +parse_llvm_arguments (LlvmAsmContext ctx) +{ + auto &parser = ctx.parser; + enum State + { + Templates = 0, + Output, + Input, + Clobbers, + Options + } current_state + = State::Templates; + + while (parser.peek_current_token ()->get_id () != ctx.last_token_id + && parser.peek_current_token ()->get_id () != END_OF_FILE) + { + if (parser.peek_current_token ()->get_id () == SCOPE_RESOLUTION) + { + parser.skip_token (SCOPE_RESOLUTION); + current_state = static_cast<State> (current_state + 2); + } + else + { + parser.skip_token (COLON); + current_state = static_cast<State> (current_state + 1); + } + + switch (current_state) + { + case State::Output: + parse_llvm_outputs (ctx); + break; + case State::Input: + parse_llvm_inputs (ctx); + break; + case State::Clobbers: + parse_llvm_clobbers (ctx); + break; + case State::Options: + parse_llvm_options (ctx); + break; + case State::Templates: + default: + rust_unreachable (); + } + } + + return ctx; +} + +void +parse_llvm_operands (LlvmAsmContext &ctx, std::vector<AST::LlvmOperand> &result) +{ + auto &parser = ctx.parser; + auto token = parser.peek_current_token (); + while (token->get_id () != COLON && token->get_id () != SCOPE_RESOLUTION + && token->get_id () != ctx.last_token_id) + { + std::string constraint; + if (token->get_id () == STRING_LITERAL) + { + constraint = strip_double_quotes (token->as_string ()); + } + parser.skip_token (STRING_LITERAL); + parser.skip_token (LEFT_PAREN); + + token = parser.peek_current_token (); + + ParseRestrictions restrictions; + restrictions.expr_can_be_null = true; + auto expr = parser.parse_expr (); + + parser.skip_token (RIGHT_PAREN); + + result.emplace_back (constraint, std::move (expr)); + + if (parser.peek_current_token ()->get_id () == COMMA) + parser.skip_token (COMMA); + + token = parser.peek_current_token (); + } +} + +void +parse_llvm_outputs (LlvmAsmContext &ctx) +{ + parse_llvm_operands (ctx, ctx.llvm_asm.get_outputs ()); +} + +void +parse_llvm_inputs (LlvmAsmContext &ctx) +{ + parse_llvm_operands (ctx, ctx.llvm_asm.get_inputs ()); +} + +void +parse_llvm_clobbers (LlvmAsmContext &ctx) +{ + auto &parser = ctx.parser; + auto token = parser.peek_current_token (); + while (token->get_id () != COLON && token->get_id () != ctx.last_token_id) + { + if (token->get_id () == STRING_LITERAL) + { + ctx.llvm_asm.get_clobbers ().push_back ( + {strip_double_quotes (token->as_string ()), token->get_locus ()}); + + parser.skip_token (STRING_LITERAL); + } + + parser.maybe_skip_token (COMMA); + token = parser.peek_current_token (); + } +} + +void +parse_llvm_options (LlvmAsmContext &ctx) +{ + auto &parser = ctx.parser; + auto token = parser.peek_current_token (); + + while (token->get_id () != ctx.last_token_id) + { + if (token->get_id () == STRING_LITERAL) + { + auto token_str = strip_double_quotes (token->as_string ()); + + if (token_str == "volatile") + ctx.llvm_asm.set_volatile (true); + else if (token_str == "alignstack") + ctx.llvm_asm.set_align_stack (true); + else if (token_str == "intel") + ctx.llvm_asm.set_dialect (AST::LlvmInlineAsm::Dialect::Intel); + else + rust_error_at (token->get_locus (), + "Unknown llvm assembly option %qs", + token_str.c_str ()); + } + parser.skip_token (STRING_LITERAL); + + token = parser.peek_current_token (); + + if (token->get_id () == ctx.last_token_id) + continue; + parser.skip_token (COMMA); + } + + parser.skip_token (); +} + +tl::optional<AST::Fragment> +parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc, + AST::InvocKind semicolon, AST::AsmKind is_global_asm) +{ + MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ()); + Parser<MacroInvocLexer> parser (lex); + auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser); + + AST::LlvmInlineAsm llvm_asm{invoc_locus}; + + auto asm_ctx = LlvmAsmContext (llvm_asm, parser, last_token_id); + + tl::optional<LlvmAsmContext> resulting_context + = parse_llvm_templates (asm_ctx).and_then (parse_llvm_arguments); + + if (resulting_context) + { + auto resulting_ctx = resulting_context.value (); + auto node = resulting_ctx.llvm_asm.clone_expr_without_block (); + + std::vector<AST::SingleASTNode> single_vec = {}; + + // If the macro invocation has a semicolon (`asm!("...");`), then we + // need to make it a statement. This way, it will be expanded + // properly. + if (semicolon == AST::InvocKind::Semicoloned) + { + single_vec.emplace_back ( + std::make_unique<AST::ExprStmt> (std::move (node), invoc_locus, + true /* has semicolon */)); + } + else + single_vec.emplace_back (std::move (node)); + + AST::Fragment fragment_ast + = AST::Fragment (single_vec, + std::vector<std::unique_ptr<AST::Token>> ()); + return fragment_ast; + } + return tl::nullopt; +} + } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h index 8081dae..3196a5a 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.h +++ b/gcc/rust/expand/rust-macro-builtins-asm.h @@ -142,16 +142,16 @@ tl::expected<InlineAsmContext, InlineAsmParseError> parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx); WARN_UNUSED_RESULT -tl::optional<AST::Fragment> -parse_asm (location_t invoc_locus, AST::MacroInvocData &invoc, - AST::InvocKind semicolon, AST::AsmKind is_global_asm); +tl::optional<AST::Fragment> parse_asm (location_t invoc_locus, + AST::MacroInvocData &invoc, + AST::InvocKind semicolon, + AST::AsmKind is_global_asm); WARN_UNUSED_RESULT -bool -check_identifier (Parser<MacroInvocLexer> &parser, std::string ident); +bool check_identifier (Parser<MacroInvocLexer> &parser, std::string ident); -void -check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option); +void check_and_set (InlineAsmContext &inline_asm_ctx, + AST::InlineAsm::Option option); // From rustc WARN_UNUSED_RESULT @@ -168,8 +168,36 @@ tl::optional<std::string> parse_format_string (InlineAsmContext &inline_asm_ctx); WARN_UNUSED_RESULT -tl::optional<std::string> -parse_label (Parser<MacroInvocLexer> &parser, TokenId last_token_id, - InlineAsmContext &inline_asm_ctx); +tl::optional<std::string> parse_label (Parser<MacroInvocLexer> &parser, + TokenId last_token_id, + InlineAsmContext &inline_asm_ctx); + +// LLVM ASM bits + +class LlvmAsmContext +{ +public: + AST::LlvmInlineAsm &llvm_asm; + Parser<MacroInvocLexer> &parser; + int last_token_id; + +public: + LlvmAsmContext (AST::LlvmInlineAsm &llvm_asm, Parser<MacroInvocLexer> &parser, + int last_token_id) + : llvm_asm (llvm_asm), parser (parser), last_token_id (last_token_id) + {} +}; + +void parse_llvm_outputs (LlvmAsmContext &ctx); + +void parse_llvm_inputs (LlvmAsmContext &ctx); + +void parse_llvm_clobbers (LlvmAsmContext &ctx); + +void parse_llvm_options (LlvmAsmContext &ctx); + +WARN_UNUSED_RESULT tl::optional<AST::Fragment> +parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc, + AST::InvocKind semicolon, AST::AsmKind is_global_asm); } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc index 8eb32d5..eb2a1cc 100644 --- a/gcc/rust/expand/rust-macro-builtins-format-args.cc +++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc @@ -37,30 +37,42 @@ struct FormatArgsParseError } kind; }; -static tl::expected<FormatArgsInput, FormatArgsParseError> -format_args_parse_arguments (AST::MacroInvocData &invoc) +static inline tl::expected<std::string, AST::Fragment> +format_args_parse_expr (location_t invoc_locus, AST::MacroInvocData &invoc, + Parser<MacroInvocLexer> &parser, + BuiltinMacro macro_kind) { - MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ()); - Parser<MacroInvocLexer> parser (lex); + std::unique_ptr<AST::Expr> format_expr = parser.parse_expr (); + rust_assert (format_expr); - // TODO: check if EOF - return that format_args!() requires at least one - // argument - - auto args = AST::FormatArguments (); - auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser); - std::unique_ptr<AST::Expr> format_expr = nullptr; - - // TODO: Handle the case where we're not parsing a string literal (macro - // invocation for e.g.) - if (parser.peek_current_token ()->get_id () == STRING_LITERAL) - format_expr = parser.parse_literal_expr (); + if (format_expr->get_expr_kind () == AST::Expr::Kind::MacroInvocation) + { + std::vector<std::unique_ptr<AST::MacroInvocation>> pending; + pending.emplace_back ( + static_cast<AST::MacroInvocation *> (format_expr.release ())); + return tl::unexpected<AST::Fragment> ( + make_eager_builtin_invocation (macro_kind, invoc_locus, + invoc.get_delim_tok_tree (), + std::move (pending))); + } // TODO(Arthur): Clean this up - if we haven't parsed a string literal but a // macro invocation, what do we do here? return a tl::unexpected? - auto format_str = static_cast<AST::LiteralExpr &> (*format_expr) - .get_literal () - .as_string (); + rust_assert (format_expr->is_literal ()); + return static_cast<AST::LiteralExpr &> (*format_expr) + .get_literal () + .as_string (); +} + +static inline tl::expected<AST::FormatArguments, FormatArgsParseError> +format_args_parse_arguments (AST::MacroInvocData &invoc, + Parser<MacroInvocLexer> &parser, + TokenId last_token_id) +{ + // TODO: check if EOF - return that format_args!() requires at least one + // argument + auto args = AST::FormatArguments (); // TODO: Allow implicit captures ONLY if the the first arg is a string literal // and not a macro invocation @@ -81,6 +93,11 @@ format_args_parse_arguments (AST::MacroInvocData &invoc) { parser.skip_token (COMMA); + // Check in case of an extraneous comma in the args list, which is + // allowed - format_args!("fmt", arg, arg2,) + if (parser.peek_current_token ()->get_id () == last_token_id) + break; + if (parser.peek_current_token ()->get_id () == IDENTIFIER && parser.peek (1)->get_id () == EQUAL) { @@ -112,7 +129,7 @@ format_args_parse_arguments (AST::MacroInvocData &invoc) // we need to skip commas, don't we? } - return FormatArgsInput{std::move (format_str), std::move (args)}; + return args; } tl::optional<AST::Fragment> @@ -121,9 +138,24 @@ MacroBuiltin::format_args_handler (location_t invoc_locus, AST::InvocKind semicolon, AST::FormatArgs::Newline nl) { - auto input = format_args_parse_arguments (invoc); + MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ()); + Parser<MacroInvocLexer> parser (lex); + + auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser); + + auto format_str = format_args_parse_expr (invoc_locus, invoc, parser, + nl == AST::FormatArgs::Newline::Yes + ? BuiltinMacro::FormatArgsNl + : BuiltinMacro::FormatArgs); + + if (!format_str) + { + return std::move (format_str.error ()); + } + + auto args = format_args_parse_arguments (invoc, parser, last_token_id); - if (!input) + if (!args) { rust_error_at (invoc_locus, "could not parse arguments to %<format_args!()%>"); @@ -159,7 +191,7 @@ MacroBuiltin::format_args_handler (location_t invoc_locus, bool append_newline = nl == AST::FormatArgs::Newline::Yes; - auto fmt_str = std::move (input->format_str); + auto fmt_str = std::move (format_str.value ()); if (append_newline) fmt_str += '\n'; @@ -175,7 +207,7 @@ MacroBuiltin::format_args_handler (location_t invoc_locus, // for creating the `template` auto fmt_args_node = AST::FormatArgs (invoc_locus, std::move (pieces), - std::move (input->args)); + std::move (args.value ())); auto expanded = Fmt::expand_format_args (fmt_args_node, diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.cc b/gcc/rust/expand/rust-macro-builtins-helpers.cc index 864379a..ee01f65 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.cc +++ b/gcc/rust/expand/rust-macro-builtins-helpers.cc @@ -68,6 +68,7 @@ make_eager_builtin_invocation ( { auto path_str = make_macro_path_str (kind); + auto token_stream = arguments.to_token_stream (); std::unique_ptr<AST::Expr> node = AST::MacroInvocation::Builtin ( kind, AST::MacroInvocData (AST::SimplePath ( @@ -76,7 +77,7 @@ make_eager_builtin_invocation ( {}, locus, std::move (pending_invocations)); return AST::Fragment ({AST::SingleASTNode (std::move (node))}, - arguments.to_token_stream ()); + std::move (token_stream)); } /* Match the end token of a macro given the start delimiter of the macro */ @@ -110,9 +111,9 @@ std::unique_ptr<AST::LiteralExpr> try_extract_string_literal_from_fragment (const location_t &parent_locus, std::unique_ptr<AST::Expr> &node) { - auto maybe_lit = static_cast<AST::LiteralExpr *> (node.get ()); if (!node || !node->is_literal () - || maybe_lit->get_lit_type () != AST::Literal::STRING) + || static_cast<AST::LiteralExpr &> (*node).get_lit_type () + != AST::Literal::STRING) { rust_error_at (parent_locus, "argument must be a string literal"); if (node) diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.h b/gcc/rust/expand/rust-macro-builtins-helpers.h index 429537e..ce63017 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.h +++ b/gcc/rust/expand/rust-macro-builtins-helpers.h @@ -22,7 +22,6 @@ #include "rust-ast.h" #include "rust-cfg-strip.h" #include "rust-diagnostics.h" -#include "rust-early-name-resolver.h" #include "rust-expr.h" #include "rust-lex.h" #include "rust-macro-builtins.h" @@ -33,29 +32,23 @@ #include "rust-token.h" namespace Rust { -std::string -make_macro_path_str (BuiltinMacro kind); +std::string make_macro_path_str (BuiltinMacro kind); -std::vector<std::unique_ptr<AST::MacroInvocation>> -check_for_eager_invocations ( +std::vector<std::unique_ptr<AST::MacroInvocation>> check_for_eager_invocations ( std::vector<std::unique_ptr<AST::Expr>> &expressions); // Shorthand function for creating unique_ptr tokens -std::unique_ptr<AST::Token> -make_token (const TokenPtr tok); +std::unique_ptr<AST::Token> make_token (const TokenPtr tok); -std::unique_ptr<AST::Expr> -make_string (location_t locus, std::string value); +std::unique_ptr<AST::Expr> make_string (location_t locus, std::string value); // TODO: Is this correct? -AST::Fragment -make_eager_builtin_invocation ( +AST::Fragment make_eager_builtin_invocation ( BuiltinMacro kind, location_t locus, AST::DelimTokenTree arguments, std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations); // Match the end token of a macro given the start delimiter of the macro -TokenId -macro_end_token (AST::DelimTokenTree &invoc_token_tree, - Parser<MacroInvocLexer> &parser); +TokenId macro_end_token (AST::DelimTokenTree &invoc_token_tree, + Parser<MacroInvocLexer> &parser); // Expand and then extract a string literal from the macro std::unique_ptr<AST::LiteralExpr> try_extract_string_literal_from_fragment (const location_t &parent_locus, @@ -70,21 +63,18 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser, // and return the LiteralExpr for it. Allow for an optional trailing comma, // but otherwise enforce that these are the only tokens. -std::unique_ptr<AST::Expr> -parse_single_string_literal (BuiltinMacro kind, - AST::DelimTokenTree &invoc_token_tree, - location_t invoc_locus, MacroExpander *expander, - bool is_semicoloned = false); +std::unique_ptr<AST::Expr> parse_single_string_literal ( + BuiltinMacro kind, AST::DelimTokenTree &invoc_token_tree, + location_t invoc_locus, MacroExpander *expander, bool is_semicoloned = false); // Treat PATH as a path relative to the source file currently being // compiled, and return the absolute path for it. -std::string -source_relative_path (std::string path, location_t locus); +std::string source_relative_path (std::string path, location_t locus); // Read the full contents of the file FILENAME and return them in a vector. // FIXME: platform specific. -tl::optional<std::vector<uint8_t>> -load_file_bytes (location_t invoc_locus, const char *filename); +tl::optional<std::vector<uint8_t>> load_file_bytes (location_t invoc_locus, + const char *filename); } // namespace Rust #endif // GCCRS_RUST_MACRO_BUILTINS_HELPERS_H diff --git a/gcc/rust/expand/rust-macro-builtins-offset-of.cc b/gcc/rust/expand/rust-macro-builtins-offset-of.cc new file mode 100644 index 0000000..02c637b --- /dev/null +++ b/gcc/rust/expand/rust-macro-builtins-offset-of.cc @@ -0,0 +1,78 @@ +// Copyright (C) 2020-2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "optional.h" +#include "rust-ast-fragment.h" +#include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" +#include "rust-diagnostics.h" +#include "rust-macro-builtins-helpers.h" +#include "rust-macro-builtins.h" +#include "rust-macro-invoc-lexer.h" +#include "rust-parse.h" + +namespace Rust { + +tl::optional<AST::Fragment> +MacroBuiltin::offset_of_handler (location_t invoc_locus, + AST::MacroInvocData &invoc, + AST::InvocKind semicolon) +{ + MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ()); + Parser<MacroInvocLexer> parser (lex); + + auto last_token = macro_end_token (invoc.get_delim_tok_tree (), parser); + + auto type = parser.parse_type (); + + // if we don't see a type, there might be an eager macro expansion missing + // FIXME: handle that + if (!type) + { + rust_error_at (invoc_locus, "could not parse type argument for %qs", + "offset_of"); + + // we skip so we can still parse the field arg and check if it is correct + while (parser.peek_current_token ()->get_id () != COMMA + && parser.peek_current_token ()->get_id () != last_token) + parser.skip_token (); + } + + parser.skip_token (COMMA); + + auto field_tok = parser.parse_identifier_or_keyword_token (); + auto invalid_field = !field_tok || !field_tok->should_have_str (); + + if (invalid_field) + rust_error_at (invoc_locus, "could not parse field argument for %qs", + "offset_of"); + + if (!type || invalid_field) + return tl::nullopt; + + auto field = Identifier (field_tok->get_str ()); + + // FIXME: Do we need to do anything to handle the optional comma at the end? + parser.maybe_skip_token (COMMA); + + return AST::Fragment ({AST::SingleASTNode (std::make_unique<AST::OffsetOf> ( + std::move (type), field, invoc_locus))}, + invoc.get_delim_tok_tree ().to_token_stream ()); +} + +} // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index 39c4c46..948f389 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -29,7 +29,6 @@ #include "rust-ast.h" #include "rust-cfg-strip.h" #include "rust-diagnostics.h" -#include "rust-early-name-resolver.h" #include "rust-expr.h" #include "rust-lex.h" #include "rust-macro-invoc-lexer.h" @@ -83,7 +82,6 @@ const BiMap<std::string, BuiltinMacro> MacroBuiltin::builtins = {{ {"Ord", BuiltinMacro::Ord}, {"PartialOrd", BuiltinMacro::PartialOrd}, {"Hash", BuiltinMacro::Hash}, - }}; AST::MacroTranscriberFunc @@ -104,6 +102,15 @@ inline_asm_maker (AST::AsmKind global_asm) }; } +AST::MacroTranscriberFunc +inline_llvm_asm_maker (AST::AsmKind global_asm) +{ + return [global_asm] (location_t loc, AST::MacroInvocData &invoc, + AST::InvocKind semicolon) { + return MacroBuiltin::llvm_asm_handler (loc, invoc, semicolon, global_asm); + }; +} + std::unordered_map<std::string, AST::MacroTranscriberFunc> MacroBuiltin::builtin_transcribers = { {"assert", MacroBuiltin::assert_handler}, @@ -122,7 +129,7 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc> {"format_args_nl", format_args_maker (AST::FormatArgs::Newline::Yes)}, {"asm", inline_asm_maker (AST::AsmKind::Inline)}, // FIXME: Is that okay? - {"llvm_asm", inline_asm_maker (AST::AsmKind::Inline)}, + {"llvm_asm", inline_llvm_asm_maker (AST::AsmKind::Inline)}, {"global_asm", inline_asm_maker (AST::AsmKind::Global)}, {"option_env", MacroBuiltin::option_env_handler}, /* Unimplemented macro builtins */ @@ -137,6 +144,7 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc> {"cfg_accessible", MacroBuiltin::sorry}, {"rustc_const_stable", MacroBuiltin::sorry}, {"rustc_const_unstable", MacroBuiltin::sorry}, + {"track_caller", MacroBuiltin::sorry}, /* Derive builtins do not need a real transcriber, but still need one. It should however never be called since builtin derive macros get expanded differently, and benefit from knowing on what kind of items they are @@ -153,6 +161,9 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc> {"Ord", MacroBuiltin::proc_macro_builtin}, {"PartialOrd", MacroBuiltin::proc_macro_builtin}, {"Hash", MacroBuiltin::proc_macro_builtin}, + /* offset_of is not declared in Rust 1.49 but still needed for + Rust-for-Linux, so we still create a transcriber and warn the user */ + {"offset_of", MacroBuiltin::offset_of_handler}, }; tl::optional<BuiltinMacro> diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h index ff06ebf..b6c2907 100644 --- a/gcc/rust/expand/rust-macro-builtins.h +++ b/gcc/rust/expand/rust-macro-builtins.h @@ -19,6 +19,7 @@ #ifndef RUST_MACRO_BUILTINS_H #define RUST_MACRO_BUILTINS_H +#include "optional.h" #include "rust-ast.h" #include "rust-builtin-ast-nodes.h" #include "rust-ast-fragment.h" @@ -181,9 +182,16 @@ public: AST::AsmKind is_global_asm); static tl::optional<AST::Fragment> + llvm_asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc, + AST::InvocKind semicolon, AST::AsmKind is_global_asm); + + static tl::optional<AST::Fragment> format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc, AST::InvocKind semicolon, AST::FormatArgs::Newline nl); + static tl::optional<AST::Fragment> + offset_of_handler (location_t, AST::MacroInvocData &, AST::InvocKind); + static tl::optional<AST::Fragment> sorry (location_t invoc_locus, AST::MacroInvocData &invoc, AST::InvocKind semicolon); diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index cd17a3f..b47e43a 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -19,6 +19,7 @@ #include "rust-macro-expand.h" #include "optional.h" #include "rust-ast-fragment.h" +#include "rust-macro-builtins.h" #include "rust-macro-substitute-ctx.h" #include "rust-ast-full.h" #include "rust-ast-visitor.h" @@ -26,8 +27,8 @@ #include "rust-macro.h" #include "rust-parse.h" #include "rust-cfg-strip.h" -#include "rust-early-name-resolver.h" #include "rust-proc-macro.h" +#include "rust-token-tree-desugar.h" namespace Rust { @@ -78,7 +79,10 @@ MacroExpander::expand_decl_macro (location_t invoc_locus, * trees. */ - AST::DelimTokenTree &invoc_token_tree = invoc.get_delim_tok_tree (); + AST::DelimTokenTree &invoc_token_tree_sugar = invoc.get_delim_tok_tree (); + + // We must first desugar doc comments into proper attributes + auto invoc_token_tree = AST::TokenTreeDesugar ().go (invoc_token_tree_sugar); // find matching arm AST::MacroRule *matched_rule = nullptr; @@ -283,6 +287,26 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, // lookup the rules auto rules_def = mappings.lookup_macro_invocation (invoc); + // We special case the `offset_of!()` macro if the flag is here and manually + // resolve to the builtin transcriber we have specified + auto assume_builtin_offset_of + = flag_assume_builtin_offset_of + && (invoc.get_invoc_data ().get_path ().as_string () == "offset_of") + && !rules_def; + + // TODO: This is *massive hack* which should be removed as we progress to + // Rust 1.71 when offset_of gets added to core + if (assume_builtin_offset_of) + { + fragment = MacroBuiltin::offset_of_handler (invoc.get_locus (), + invoc_data, semicolon) + .value_or (AST::Fragment::create_empty ()); + + set_expanded_fragment (std::move (fragment)); + + return; + } + // If there's no rule associated with the invocation, we can simply return // early. The early name resolver will have already emitted an error. if (!rules_def) @@ -426,7 +450,8 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> &parser, parser.parse_visibility (); break; - case AST::MacroFragSpec::STMT: { + case AST::MacroFragSpec::STMT: + { auto restrictions = ParseRestrictions (); restrictions.consume_semi = false; parser.parse_stmt (restrictions); @@ -476,19 +501,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, // this is used so we can check that we delimit the stream correctly. switch (delimiter->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { if (!check_delim (AST::DelimType::PARENS)) return false; } break; - case LEFT_SQUARE: { + case LEFT_SQUARE: + { if (!check_delim (AST::DelimType::SQUARE)) return false; } break; - case LEFT_CURLY: { + case LEFT_CURLY: + { if (!check_delim (AST::DelimType::CURLY)) return false; } @@ -506,7 +534,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, switch (match->get_macro_match_type ()) { - case AST::MacroMatch::MacroMatchType::Fragment: { + case AST::MacroMatch::MacroMatchType::Fragment: + { AST::MacroMatchFragment *fragment = static_cast<AST::MacroMatchFragment *> (match.get ()); if (!match_fragment (parser, *fragment)) @@ -520,14 +549,16 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, } break; - case AST::MacroMatch::MacroMatchType::Tok: { + case AST::MacroMatch::MacroMatchType::Tok: + { AST::Token *tok = static_cast<AST::Token *> (match.get ()); if (!match_token (parser, *tok)) return false; } break; - case AST::MacroMatch::MacroMatchType::Repetition: { + case AST::MacroMatch::MacroMatchType::Repetition: + { AST::MacroMatchRepetition *rep = static_cast<AST::MacroMatchRepetition *> (match.get ()); if (!match_repetition (parser, *rep)) @@ -535,7 +566,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, } break; - case AST::MacroMatch::MacroMatchType::Matcher: { + case AST::MacroMatch::MacroMatchType::Matcher: + { AST::MacroMatcher *m = static_cast<AST::MacroMatcher *> (match.get ()); expansion_depth++; @@ -552,19 +584,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, switch (delimiter->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { if (!parser.skip_token (RIGHT_PAREN)) return false; } break; - case LEFT_SQUARE: { + case LEFT_SQUARE: + { if (!parser.skip_token (RIGHT_SQUARE)) return false; } break; - case LEFT_CURLY: { + case LEFT_CURLY: + { if (!parser.skip_token (RIGHT_CURLY)) return false; } @@ -613,7 +648,8 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, size_t offs_begin = source.get_offs (); switch (match->get_macro_match_type ()) { - case AST::MacroMatch::MacroMatchType::Fragment: { + case AST::MacroMatch::MacroMatchType::Fragment: + { AST::MacroMatchFragment *fragment = static_cast<AST::MacroMatchFragment *> (match.get ()); valid_current_match = match_fragment (parser, *fragment); @@ -621,26 +657,30 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, // matched fragment get the offset in the token stream size_t offs_end = source.get_offs (); - sub_stack.insert_metavar ( - MatchedFragment (fragment->get_ident ().as_string (), - offs_begin, offs_end)); + if (valid_current_match) + sub_stack.insert_metavar ( + MatchedFragment (fragment->get_ident ().as_string (), + offs_begin, offs_end)); } break; - case AST::MacroMatch::MacroMatchType::Tok: { + case AST::MacroMatch::MacroMatchType::Tok: + { AST::Token *tok = static_cast<AST::Token *> (match.get ()); valid_current_match = match_token (parser, *tok); } break; - case AST::MacroMatch::MacroMatchType::Repetition: { + case AST::MacroMatch::MacroMatchType::Repetition: + { AST::MacroMatchRepetition *rep = static_cast<AST::MacroMatchRepetition *> (match.get ()); valid_current_match = match_repetition (parser, *rep); } break; - case AST::MacroMatch::MacroMatchType::Matcher: { + case AST::MacroMatch::MacroMatchType::Matcher: + { AST::MacroMatcher *m = static_cast<AST::MacroMatcher *> (match.get ()); valid_current_match = match_matcher (parser, *m, true); @@ -650,15 +690,15 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, } auto old_stack = sub_stack.pop (); - // nest metavars into repetitions - for (auto &ent : old_stack) - sub_stack.append_fragment (ent.first, std::move (ent.second)); - // If we've encountered an error once, stop trying to match more // repetitions if (!valid_current_match) break; + // nest metavars into repetitions + for (auto &ent : old_stack) + sub_stack.append_fragment (ent.first, std::move (ent.second)); + match_amount++; // Break early if we notice there's too many expressions already @@ -920,8 +960,11 @@ transcribe_expression (Parser<MacroInvocLexer> &parser) auto &lexer = parser.get_token_source (); auto start = lexer.get_offs (); - auto expr = parser.parse_expr (); - if (expr == nullptr) + auto attrs = parser.parse_outer_attributes (); + auto expr = parser.parse_expr (std::move (attrs)); + for (auto error : parser.get_errors ()) + error.emit (); + if (!expr) return AST::Fragment::create_error (); // FIXME: make this an error for some edititons @@ -952,12 +995,38 @@ 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 (); return AST::Fragment ({std::move (type)}, lexer.get_token_slice (start, end)); } +/** + * Transcribe one pattern from a macro invocation + * + * @param parser Parser to extract statements from + */ +static AST::Fragment +transcribe_pattern (Parser<MacroInvocLexer> &parser) +{ + auto &lexer = parser.get_token_source (); + auto start = lexer.get_offs (); + + auto pattern = parser.parse_pattern (); + 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)}, + lexer.get_token_slice (start, end)); +} + static AST::Fragment transcribe_context (MacroExpander::ContextType ctx, Parser<MacroInvocLexer> &parser, bool semicolon, @@ -970,6 +1039,7 @@ transcribe_context (MacroExpander::ContextType ctx, // -- Trait --> parser.parse_trait_item(); // -- Impl --> parser.parse_impl_item(); // -- Extern --> parser.parse_extern_item(); + // -- Pattern --> parser.parse_pattern(); // -- None --> [has semicolon?] // -- Yes --> parser.parse_stmt(); // -- No --> [switch invocation.delimiter()] @@ -998,6 +1068,8 @@ transcribe_context (MacroExpander::ContextType ctx, break; case MacroExpander::ContextType::TYPE: return transcribe_type (parser); + case MacroExpander::ContextType::PATTERN: + return transcribe_pattern (parser); break; case MacroExpander::ContextType::STMT: return transcribe_many_stmts (parser, last_token_id, semicolon); @@ -1039,8 +1111,9 @@ MacroExpander::transcribe_rule ( auto invoc_stream = invoc_token_tree.to_token_stream (); auto macro_rule_tokens = transcribe_tree.to_token_stream (); - auto substitute_context = SubstituteCtx (invoc_stream, macro_rule_tokens, - matched_fragments, definition); + auto substitute_context + = SubstituteCtx (invoc_stream, macro_rule_tokens, matched_fragments, + definition, invoc_token_tree.get_locus ()); std::vector<std::unique_ptr<AST::Token>> substituted_tokens = substitute_context.substitute_tokens (); @@ -1087,11 +1160,7 @@ MacroExpander::transcribe_rule ( // emit any errors if (parser.has_errors ()) - { - for (auto &err : parser.get_errors ()) - rust_error_at (err.locus, "%s", err.message.c_str ()); - return AST::Fragment::create_error (); - } + return AST::Fragment::create_error (); // are all the tokens used? bool did_delimit = parser.skip_token (last_token_id); @@ -1124,7 +1193,7 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts) auto result = parser.parse_item (false); if (result == nullptr) break; - nodes.push_back ({std::move (result)}); + nodes.emplace_back (std::move (result)); } break; case ContextType::STMT: @@ -1133,7 +1202,7 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts) auto result = parser.parse_stmt (); if (result == nullptr) break; - nodes.push_back ({std::move (result)}); + nodes.emplace_back (std::move (result)); } break; case ContextType::TRAIT: diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 360294c..0e79466 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -27,7 +27,6 @@ #include "rust-ast.h" #include "rust-macro.h" #include "rust-hir-map.h" -#include "rust-early-name-resolver.h" #include "rust-name-resolver.h" #include "rust-macro-invoc-lexer.h" #include "rust-proc-macro-invoc-lexer.h" @@ -291,6 +290,7 @@ struct MacroExpander TRAIT, IMPL, TRAIT_IMPL, + PATTERN, }; ExpansionCfg cfg; @@ -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/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index 02e4e3b..36bae5b 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -40,7 +40,7 @@ SubstituteCtx::substitute_dollar_crate ( if (*def_crate == current_crate) { expanded.push_back (std::make_unique<AST::Token> ( - Rust::Token::make_identifier (UNKNOWN_LOCATION, "crate"))); + Rust::Token::make_identifier (origin, "crate"))); } else { @@ -49,9 +49,9 @@ SubstituteCtx::substitute_dollar_crate ( rust_assert (name); expanded.push_back (std::make_unique<AST::Token> ( - Rust::Token::make (SCOPE_RESOLUTION, UNKNOWN_LOCATION))); + Rust::Token::make (SCOPE_RESOLUTION, origin))); expanded.push_back (std::make_unique<AST::Token> ( - Rust::Token::make_identifier (UNKNOWN_LOCATION, std::string (*name)))); + Rust::Token::make_identifier (origin, std::string (*name)))); } return true; @@ -108,6 +108,12 @@ SubstituteCtx::substitute_metavar ( return true; } +static bool +is_builtin_metavariable (AST::Token &token) +{ + return token.get_id () == CRATE; +} + bool SubstituteCtx::check_repetition_amount (size_t pattern_start, size_t pattern_end, @@ -125,6 +131,10 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start, || frag_token->get_id () == IDENTIFIER) { auto it = fragments.find (frag_token->get_str ()); + + if (is_builtin_metavariable (*frag_token)) + continue; + if (it == fragments.end ()) { // If the repetition is not anything we know (ie no declared @@ -136,6 +146,7 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start, frag_token->get_str ().c_str ()); is_valid = false; + continue; } auto &fragment = *it->second; @@ -226,7 +237,7 @@ SubstituteCtx::substitute_repetition ( } auto substitute_context - = SubstituteCtx (input, new_macro, sub_map, definition); + = SubstituteCtx (input, new_macro, sub_map, definition, origin); auto new_tokens = substitute_context.substitute_tokens (); // Skip the first repetition, but add the separator to the expanded @@ -273,7 +284,8 @@ SubstituteCtx::substitute_token (size_t token_idx) // don't substitute, dollar sign is alone/metavar is unknown return {std::vector<std::unique_ptr<AST::Token>> (), 0}; - case LEFT_PAREN: { + case LEFT_PAREN: + { // We need to parse up until the closing delimiter and expand this // fragment->n times. rust_debug ("expanding repetition"); diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.h b/gcc/rust/expand/rust-macro-substitute-ctx.h index c5c4956..3829a5a 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.h +++ b/gcc/rust/expand/rust-macro-substitute-ctx.h @@ -27,6 +27,8 @@ class SubstituteCtx std::vector<std::unique_ptr<AST::Token>> ¯o; std::map<std::string, MatchedFragmentContainer *> &fragments; AST::MacroRulesDefinition &definition; + // Macro invocation location + location_t origin; /** * Find the repetition amount to use when expanding a repetition, and @@ -43,9 +45,9 @@ public: SubstituteCtx (std::vector<std::unique_ptr<AST::Token>> &input, std::vector<std::unique_ptr<AST::Token>> ¯o, std::map<std::string, MatchedFragmentContainer *> &fragments, - AST::MacroRulesDefinition &definition) + AST::MacroRulesDefinition &definition, location_t origin) : input (input), macro (macro), fragments (fragments), - definition (definition) + definition (definition), origin (origin) {} /** diff --git a/gcc/rust/expand/rust-proc-macro.h b/gcc/rust/expand/rust-proc-macro.h index 6ffaaf6..058c93a 100644 --- a/gcc/rust/expand/rust-proc-macro.h +++ b/gcc/rust/expand/rust-proc-macro.h @@ -82,11 +82,9 @@ public: * * @param The path to the shared object file to load. */ -const std::vector<ProcMacro::Procmacro> -load_macros (std::string path); +const std::vector<ProcMacro::Procmacro> load_macros (std::string path); -std::string -generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id); +std::string generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id); } // namespace Rust diff --git a/gcc/rust/expand/rust-token-tree-desugar.cc b/gcc/rust/expand/rust-token-tree-desugar.cc new file mode 100644 index 0000000..aa20d50 --- /dev/null +++ b/gcc/rust/expand/rust-token-tree-desugar.cc @@ -0,0 +1,72 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-token-tree-desugar.h" +#include "rust-ast.h" +#include "rust-token.h" + +namespace Rust { +namespace AST { + +DelimTokenTree +TokenTreeDesugar::go (DelimTokenTree &tts) +{ + tts.accept_vis (*this); + + return DelimTokenTree (tts.get_delim_type (), std::move (desugared), + tts.get_locus ()); +} + +void +TokenTreeDesugar::append (TokenPtr &&new_token) +{ + desugared.emplace_back (std::make_unique<Token> (std::move (new_token))); +} + +void +TokenTreeDesugar::append (std::unique_ptr<TokenTree> &&new_token) +{ + desugared.emplace_back (std::move (new_token)); +} + +void +TokenTreeDesugar::visit (Token &tts) +{ + if (tts.get_id () == TokenId::OUTER_DOC_COMMENT + || tts.get_id () == TokenId::INNER_DOC_COMMENT) + { + append (Rust::Token::make (TokenId::HASH, tts.get_locus ())); + + if (tts.get_id () == TokenId::INNER_DOC_COMMENT) + append (Rust::Token::make (EXCLAM, tts.get_locus ())); + + append (Rust::Token::make (TokenId::LEFT_SQUARE, tts.get_locus ())); + append (Rust::Token::make_identifier (tts.get_locus (), "doc")); + append (Rust::Token::make (TokenId::EQUAL, tts.get_locus ())); + append (Rust::Token::make_string (tts.get_locus (), + std::string (tts.get_str ()))); + append (Rust::Token::make (TokenId::RIGHT_SQUARE, tts.get_locus ())); + } + else + { + append (tts.clone_token ()); + } +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/expand/rust-token-tree-desugar.h b/gcc/rust/expand/rust-token-tree-desugar.h new file mode 100644 index 0000000..da9d732 --- /dev/null +++ b/gcc/rust/expand/rust-token-tree-desugar.h @@ -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/>. + +#ifndef RUST_TOKEN_TREE_DESUGAR_H +#define RUST_TOKEN_TREE_DESUGAR_H + +#include "rust-ast-visitor.h" +#include "rust-system.h" +#include "rust-ast.h" + +namespace Rust { +namespace AST { + +/** + * Desugar a given token-tree before parsing it for a macro invocation. At the + * moment, the sole purpose of this desugar is to transform doc-comments into + * their attribute form (/// comment -> #[doc = "comment"]) + */ +class TokenTreeDesugar : public DefaultASTVisitor +{ +public: + TokenTreeDesugar () : desugared (std::vector<std::unique_ptr<TokenTree>> ()) + {} + + DelimTokenTree go (DelimTokenTree &tts); + +private: + std::vector<std::unique_ptr<TokenTree>> desugared; + void append (TokenPtr &&new_token); + void append (std::unique_ptr<TokenTree> &&new_token); + + using DefaultASTVisitor::visit; + + virtual void visit (Token &tts) override; +}; + +} // namespace AST +} // namespace Rust + +#endif //! RUST_TOKEN_TREE_DESUGAR_H diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index b0d347e..8984c98 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -47,6 +47,27 @@ ASTLoweringBase::visit (AST::ErrorPropagationExpr &expr) } void +ASTLoweringBase::visit (AST::TryExpr &expr) +{ + rust_fatal_error (expr.get_locus (), "missing desugar for try-blocks"); + rust_unreachable (); +} + +void +ASTLoweringBase::visit (AST::ForLoopExpr &expr) +{ + rust_fatal_error (expr.get_locus (), "missing desugar for for-loops"); + rust_unreachable (); +} + +void +ASTLoweringBase::visit (AST::WhileLetLoopExpr &expr) +{ + rust_fatal_error (expr.get_locus (), "missing desugar for while-let loops"); + rust_unreachable (); +} + +void ASTLoweringBase::visit (AST::Token &) {} void @@ -115,7 +136,7 @@ void ASTLoweringBase::visit (AST::MetaItemLitExpr &) {} void -ASTLoweringBase::visit (AST::MetaItemPathLit &) +ASTLoweringBase::visit (AST::MetaItemPathExpr &) {} void ASTLoweringBase::visit (AST::BorrowExpr &) @@ -201,6 +222,12 @@ void ASTLoweringBase::visit (AST::BlockExpr &) {} void +ASTLoweringBase::visit (AST::AnonConst &) +{} +void +ASTLoweringBase::visit (AST::ConstBlock &) +{} +void ASTLoweringBase::visit (AST::ClosureExprInnerTyped &) {} void @@ -245,12 +272,6 @@ void ASTLoweringBase::visit (AST::WhileLoopExpr &) {} void -ASTLoweringBase::visit (AST::WhileLetLoopExpr &) -{} -void -ASTLoweringBase::visit (AST::ForLoopExpr &) -{} -void ASTLoweringBase::visit (AST::IfExpr &) {} void @@ -267,6 +288,10 @@ void ASTLoweringBase::visit (AST::InlineAsm &) {} +void +ASTLoweringBase::visit (AST::LlvmInlineAsm &) +{} + // void ASTLoweringBase::visit(MatchCasematch_case) {} // void ASTLoweringBase:: (AST::MatchCaseBlockExpr &) {} // void ASTLoweringBase:: (AST::MatchCaseExpr &) {} @@ -347,9 +372,6 @@ void ASTLoweringBase::visit (AST::StaticItem &) {} void -ASTLoweringBase::visit (AST::TraitItemConst &) -{} -void ASTLoweringBase::visit (AST::TraitItemType &) {} void @@ -448,20 +470,20 @@ ASTLoweringBase::visit (AST::StructPattern &) {} // void ASTLoweringBase::visit(TupleStructItemstuple_items) {} void -ASTLoweringBase::visit (AST::TupleStructItemsNoRange &) +ASTLoweringBase::visit (AST::TupleStructItemsNoRest &) {} void -ASTLoweringBase::visit (AST::TupleStructItemsRange &) +ASTLoweringBase::visit (AST::TupleStructItemsHasRest &) {} void ASTLoweringBase::visit (AST::TupleStructPattern &) {} // void ASTLoweringBase::visit(TuplePatternItemstuple_items) {} void -ASTLoweringBase::visit (AST::TuplePatternItemsMultiple &) +ASTLoweringBase::visit (AST::TuplePatternItemsNoRest &) {} void -ASTLoweringBase::visit (AST::TuplePatternItemsRanged &) +ASTLoweringBase::visit (AST::TuplePatternItemsHasRest &) {} void ASTLoweringBase::visit (AST::TuplePattern &) @@ -470,6 +492,12 @@ void ASTLoweringBase::visit (AST::GroupedPattern &) {} void +ASTLoweringBase::visit (AST::SlicePatternItemsNoRest &) +{} +void +ASTLoweringBase::visit (AST::SlicePatternItemsHasRest &) +{} +void ASTLoweringBase::visit (AST::SlicePattern &) {} void @@ -547,6 +575,10 @@ void ASTLoweringBase::visit (AST::FormatArgs &fmt) {} +void +ASTLoweringBase::visit (AST::OffsetOf &offset_of) +{} + HIR::Lifetime ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime, bool default_to_static_lifetime) @@ -587,11 +619,10 @@ ASTLoweringBase::lower_generic_params ( std::vector<std::unique_ptr<AST::GenericParam>> ¶ms) { std::vector<std::unique_ptr<HIR::GenericParam>> lowered; + lowered.reserve (params.size ()); + for (auto &ast_param : params) - { - auto hir_param = ASTLowerGenericParam::translate (*ast_param); - lowered.push_back (std::unique_ptr<HIR::GenericParam> (hir_param)); - } + lowered.emplace_back (ASTLowerGenericParam::translate (*ast_param)); return lowered; } @@ -624,18 +655,16 @@ HIR::GenericArgs ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) { std::vector<HIR::GenericArgsBinding> binding_args; + binding_args.reserve (args.get_binding_args ().size ()); + for (auto &binding : args.get_binding_args ()) - { - HIR::GenericArgsBinding b = lower_binding (binding); - binding_args.push_back (std::move (b)); - } + binding_args.emplace_back (lower_binding (binding)); std::vector<HIR::Lifetime> lifetime_args; + lifetime_args.reserve (args.get_lifetime_args ().size ()); + for (auto &lifetime : args.get_lifetime_args ()) - { - HIR::Lifetime l = lower_lifetime (lifetime); - lifetime_args.push_back (std::move (l)); - } + lifetime_args.emplace_back (lower_lifetime (lifetime)); std::vector<std::unique_ptr<HIR::Type>> type_args; std::vector<HIR::ConstGenericArg> const_args; @@ -644,16 +673,17 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) { switch (arg.get_kind ()) { - case AST::GenericArg::Kind::Type: { - auto type = ASTLoweringType::translate (arg.get_type ()); - type_args.emplace_back (std::unique_ptr<HIR::Type> (type)); + case AST::GenericArg::Kind::Type: + { + type_args.emplace_back ( + ASTLoweringType::translate (arg.get_type ())); break; } - case AST::GenericArg::Kind::Const: { + case AST::GenericArg::Kind::Const: + { auto expr = ASTLoweringExpr::translate (arg.get_expression ()); - const_args.emplace_back ( - HIR::ConstGenericArg (std::unique_ptr<HIR::Expr> (expr), - expr->get_locus ())); + const_args.emplace_back (std::unique_ptr<HIR::Expr> (expr), + expr->get_locus ()); break; } default: @@ -690,8 +720,12 @@ ASTLoweringBase::lower_self (AST::Param ¶m) self.get_is_mut (), self.get_locus ()); } - AST::Lifetime l = self.get_lifetime (); - return HIR::SelfParam (mapping, lower_lifetime (l), self.get_is_mut (), + tl::optional<HIR::Lifetime> lifetime = tl::nullopt; + + if (self.has_lifetime ()) + lifetime = lower_lifetime (self.get_lifetime ()); + + return HIR::SelfParam (mapping, lifetime, self.get_is_mut (), self.get_locus ()); } @@ -786,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; @@ -809,9 +851,10 @@ void ASTLoweringBase::handle_lang_item_attribute (const ItemWrapper &item, const AST::Attribute &attr) { - auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &lang_item_type_str = literal.get_literal ().as_string (); - auto lang_item_type = LangItem::Parse (lang_item_type_str); + auto lang_item_type_str = Analysis::Attributes::extract_string_literal (attr); + rust_assert (lang_item_type_str.has_value ()); + + auto lang_item_type = LangItem::Parse (*lang_item_type_str); if (lang_item_type) mappings.insert_lang_item (*lang_item_type, @@ -836,41 +879,71 @@ ASTLoweringBase::attribute_handled_in_another_pass ( std::unique_ptr<HIR::TuplePatternItems> ASTLoweringBase::lower_tuple_pattern_multiple ( - AST::TuplePatternItemsMultiple &pattern) + AST::TuplePatternItemsNoRest &pattern) { std::vector<std::unique_ptr<HIR::Pattern>> patterns; + patterns.reserve (pattern.get_patterns ().size ()); + for (auto &p : pattern.get_patterns ()) - { - HIR::Pattern *translated = ASTLoweringPattern::translate (*p); - patterns.push_back (std::unique_ptr<HIR::Pattern> (translated)); - } + patterns.emplace_back (ASTLoweringPattern::translate (*p)); return std::unique_ptr<HIR::TuplePatternItems> ( - new HIR::TuplePatternItemsMultiple (std::move (patterns))); + new HIR::TuplePatternItemsNoRest (std::move (patterns))); } std::unique_ptr<TuplePatternItems> ASTLoweringBase::lower_tuple_pattern_ranged ( - AST::TuplePatternItemsRanged &pattern) + AST::TuplePatternItemsHasRest &pattern) { std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns; + lower_patterns.reserve (pattern.get_lower_patterns ().size ()); std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns; + upper_patterns.reserve (pattern.get_upper_patterns ().size ()); for (auto &p : pattern.get_lower_patterns ()) - { - HIR::Pattern *translated = ASTLoweringPattern::translate (*p); - lower_patterns.push_back (std::unique_ptr<HIR::Pattern> (translated)); - } + lower_patterns.emplace_back (ASTLoweringPattern::translate (*p)); for (auto &p : pattern.get_upper_patterns ()) - { - HIR::Pattern *translated = ASTLoweringPattern::translate (*p); - upper_patterns.push_back (std::unique_ptr<HIR::Pattern> (translated)); - } + upper_patterns.emplace_back (ASTLoweringPattern::translate (*p)); return std::unique_ptr<HIR::TuplePatternItems> ( - new HIR::TuplePatternItemsRanged (std::move (lower_patterns), - std::move (upper_patterns))); + new HIR::TuplePatternItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns))); +} + +std::unique_ptr<HIR::SlicePatternItems> +ASTLoweringBase::lower_slice_pattern_no_rest ( + AST::SlicePatternItemsNoRest &pattern) +{ + std::vector<std::unique_ptr<HIR::Pattern>> patterns; + patterns.reserve (pattern.get_patterns ().size ()); + for (auto &p : pattern.get_patterns ()) + patterns.emplace_back (ASTLoweringPattern::translate (*p)); + + return std::unique_ptr<HIR::SlicePatternItems> ( + new HIR::SlicePatternItemsNoRest (std::move (patterns))); +} + +std::unique_ptr<HIR::SlicePatternItems> +ASTLoweringBase::lower_slice_pattern_has_rest ( + AST::SlicePatternItemsHasRest &pattern) +{ + std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns; + lower_patterns.reserve (pattern.get_lower_patterns ().size ()); + std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns; + upper_patterns.reserve (pattern.get_upper_patterns ().size ()); + + for (auto &p : pattern.get_lower_patterns ()) + lower_patterns.emplace_back ( + std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*p))); + + for (auto &p : pattern.get_upper_patterns ()) + upper_patterns.emplace_back ( + std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*p))); + + return std::unique_ptr<HIR::SlicePatternItems> ( + new HIR::SlicePatternItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns))); } std::unique_ptr<HIR::RangePatternBound> @@ -879,7 +952,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) std::unique_ptr<HIR::RangePatternBound> hir_bound = nullptr; switch (bound.get_bound_type ()) { - case AST::RangePatternBound::RangePatternBoundType::LITERAL: { + case AST::RangePatternBound::RangePatternBoundType::LITERAL: + { AST::RangePatternBoundLiteral &ref = static_cast<AST::RangePatternBoundLiteral &> (bound); @@ -890,7 +964,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) ref.get_has_minus ())); } break; - case AST::RangePatternBound::RangePatternBoundType::PATH: { + case AST::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast<AST::RangePatternBoundPath &> (bound); HIR::PathInExpression *path @@ -900,7 +975,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) new HIR::RangePatternBoundPath (*path)); } break; - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: { + case AST::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound); HIR::QualifiedPathInExpression *qualpath @@ -964,14 +1040,15 @@ ASTLoweringBase::lower_extern_block (AST::ExternBlock &extern_block) mappings.get_next_localdef_id (crate_num)); std::vector<std::unique_ptr<HIR::ExternalItem>> extern_items; + extern_items.reserve (extern_block.get_extern_items ().size ()); + for (auto &item : extern_block.get_extern_items ()) { if (item->is_marked_for_strip ()) continue; - HIR::ExternalItem *lowered - = ASTLoweringExternItem::translate (item.get (), mapping.get_hirid ()); - extern_items.push_back (std::unique_ptr<HIR::ExternalItem> (lowered)); + extern_items.emplace_back ( + ASTLoweringExternItem::translate (item.get (), mapping.get_hirid ())); } ABI abi = ABI::C; diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index b3bb174..933f77b 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -20,6 +20,8 @@ #define RUST_AST_LOWER_BASE #include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" +#include "rust-expr.h" #include "rust-system.h" #include "rust-ast-full.h" #include "rust-ast-visitor.h" @@ -63,6 +65,9 @@ public: // Special casing nodes that should never reach the HIR lowering stage virtual void visit (AST::MacroInvocation &) override final; virtual void visit (AST::ErrorPropagationExpr &) override final; + virtual void visit (AST::ForLoopExpr &) override final; + virtual void visit (AST::TryExpr &) override final; + virtual void visit (AST::WhileLetLoopExpr &) override final; // visitor impl // rust-ast.h @@ -101,7 +106,7 @@ public: virtual void visit (AST::AttrInputLiteral &attr_input) override; virtual void visit (AST::AttrInputMacro &attr_input) override; virtual void visit (AST::MetaItemLitExpr &meta_item) override; - virtual void visit (AST::MetaItemPathLit &meta_item) override; + virtual void visit (AST::MetaItemPathExpr &meta_item) override; virtual void visit (AST::BorrowExpr &expr) override; virtual void visit (AST::DereferenceExpr &expr) override; virtual void visit (AST::NegationExpr &expr) override; @@ -131,6 +136,8 @@ public: virtual void visit (AST::FieldAccessExpr &expr) override; virtual void visit (AST::ClosureExprInner &expr) override; virtual void visit (AST::BlockExpr &expr) override; + virtual void visit (AST::AnonConst &expr) override; + virtual void visit (AST::ConstBlock &expr) override; virtual void visit (AST::ClosureExprInnerTyped &expr) override; virtual void visit (AST::ContinueExpr &expr) override; virtual void visit (AST::BreakExpr &expr) override; @@ -145,13 +152,12 @@ public: virtual void visit (AST::UnsafeBlockExpr &expr) override; virtual void visit (AST::LoopExpr &expr) override; virtual void visit (AST::WhileLoopExpr &expr) override; - virtual void visit (AST::WhileLetLoopExpr &expr) override; - virtual void visit (AST::ForLoopExpr &expr) override; virtual void visit (AST::IfExpr &expr) override; virtual void visit (AST::IfExprConseqElse &expr) override; virtual void visit (AST::IfLetExpr &expr) override; virtual void visit (AST::IfLetExprConseqElse &expr) override; virtual void visit (AST::InlineAsm &expr) override; + virtual void visit (AST::LlvmInlineAsm &expr) override; // virtual void visit(MatchCase& match_case) override; // virtual void visit (AST::MatchCaseBlockExpr &match_case) override; // virtual void visit (AST::MatchCaseExpr &match_case) override; @@ -183,7 +189,6 @@ public: virtual void visit (AST::Union &union_item) override; virtual void visit (AST::ConstantItem &const_item) override; virtual void visit (AST::StaticItem &static_item) override; - virtual void visit (AST::TraitItemConst &item) override; virtual void visit (AST::TraitItemType &item) override; virtual void visit (AST::Trait &trait) override; virtual void visit (AST::InherentImpl &impl) override; @@ -222,14 +227,16 @@ public: virtual void visit (AST::StructPatternFieldIdent &field) override; virtual void visit (AST::StructPattern &pattern) override; // virtual void visit(TupleStructItems& tuple_items) override; - virtual void visit (AST::TupleStructItemsNoRange &tuple_items) override; - virtual void visit (AST::TupleStructItemsRange &tuple_items) override; + virtual void visit (AST::TupleStructItemsNoRest &tuple_items) override; + virtual void visit (AST::TupleStructItemsHasRest &tuple_items) override; virtual void visit (AST::TupleStructPattern &pattern) override; // virtual void visit(TuplePatternItems& tuple_items) override; - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override; + virtual void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (AST::TuplePatternItemsHasRest &tuple_items) override; virtual void visit (AST::TuplePattern &pattern) override; virtual void visit (AST::GroupedPattern &pattern) override; + virtual void visit (AST::SlicePatternItemsNoRest &items) override; + virtual void visit (AST::SlicePatternItemsHasRest &items) override; virtual void visit (AST::SlicePattern &pattern) override; virtual void visit (AST::AltPattern &pattern) override; @@ -258,6 +265,7 @@ public: virtual void visit (AST::SelfParam ¶m) override; virtual void visit (AST::FormatArgs &fmt) override; + virtual void visit (AST::OffsetOf &offset_of) override; protected: ASTLoweringBase () @@ -308,10 +316,16 @@ protected: attribute_handled_in_another_pass (const std::string &attribute_path) const; std::unique_ptr<TuplePatternItems> - lower_tuple_pattern_multiple (AST::TuplePatternItemsMultiple &pattern); + lower_tuple_pattern_multiple (AST::TuplePatternItemsNoRest &pattern); std::unique_ptr<TuplePatternItems> - lower_tuple_pattern_ranged (AST::TuplePatternItemsRanged &pattern); + lower_tuple_pattern_ranged (AST::TuplePatternItemsHasRest &pattern); + + std::unique_ptr<SlicePatternItems> + lower_slice_pattern_no_rest (AST::SlicePatternItemsNoRest &pattern); + + std::unique_ptr<SlicePatternItems> + lower_slice_pattern_has_rest (AST::SlicePatternItemsHasRest &pattern); std::unique_ptr<HIR::RangePatternBound> lower_range_pattern_bound (AST::RangePatternBound &bound); diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h index a39c010..f10039b 100644 --- a/gcc/rust/hir/rust-ast-lower-block.h +++ b/gcc/rust/hir/rust-ast-lower-block.h @@ -195,7 +195,9 @@ public: HIR::BlockExpr *loop_block = ASTLoweringBlock::translate (expr.get_loop_block (), &terminated); - HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ()); + tl::optional<HIR::LoopLabel> loop_label = tl::nullopt; + if (expr.has_loop_label ()) + loop_label = lower_loop_label (expr.get_loop_label ()); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -211,8 +213,6 @@ public: void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::MatchExpr &expr) override; private: diff --git a/gcc/rust/hir/rust-ast-lower-enumitem.h b/gcc/rust/hir/rust-ast-lower-enumitem.h index 1b95345..8e28c08 100644 --- a/gcc/rust/hir/rust-ast-lower-enumitem.h +++ b/gcc/rust/hir/rust-ast-lower-enumitem.h @@ -80,6 +80,8 @@ public: item.get_visibility ().as_string ().c_str ()); std::vector<HIR::TupleField> fields; + fields.reserve (item.get_tuple_fields ().size ()); + for (auto &field : item.get_tuple_fields ()) { HIR::Visibility vis = translate_visibility (field.get_visibility ()); @@ -90,11 +92,8 @@ public: crate_num, field.get_node_id (), mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); - HIR::TupleField translated_field (field_mapping, - std::unique_ptr<HIR::Type> (type), - vis, field.get_locus (), - field.get_outer_attrs ()); - fields.push_back (std::move (translated_field)); + fields.emplace_back (field_mapping, std::unique_ptr<HIR::Type> (type), + vis, field.get_locus (), field.get_outer_attrs ()); } translated diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index 9f363c0..a1e24ee 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -24,7 +24,9 @@ #include "rust-ast-lower-pattern.h" #include "rust-ast-lower-type.h" #include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" #include "rust-diagnostics.h" +#include "rust-hir-map.h" #include "rust-system.h" #include "tree/rust-hir-expr.h" @@ -79,11 +81,10 @@ void ASTLoweringExpr::visit (AST::TupleExpr &expr) { std::vector<std::unique_ptr<HIR::Expr>> tuple_elements; + tuple_elements.reserve (expr.get_tuple_elems ().size ()); + for (auto &e : expr.get_tuple_elems ()) - { - HIR::Expr *t = ASTLoweringExpr::translate (*e); - tuple_elements.push_back (std::unique_ptr<HIR::Expr> (t)); - } + tuple_elements.emplace_back (ASTLoweringExpr::translate (*e)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -127,6 +128,50 @@ ASTLoweringExpr::visit (AST::BlockExpr &expr) } void +ASTLoweringExpr::visit (AST::AnonConst &expr) +{ + auto &mappings = Analysis::Mappings::get (); + auto crate_num = mappings.get_current_crate (); + auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (), + mappings.get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + if (expr.is_deferred ()) + { + translated = new HIR::AnonConst (std::move (mapping), expr.get_locus ()); + } + else + { + auto inner_expr = ASTLoweringExpr::translate (expr.get_inner_expr ()); + + translated = new HIR::AnonConst (std::move (mapping), + std::unique_ptr<Expr> (inner_expr), + expr.get_locus ()); + } +} + +void +ASTLoweringExpr::visit (AST::ConstBlock &expr) +{ + auto inner_expr = ASTLoweringExpr::translate (expr.get_const_expr ()); + + // we know this will always be an `AnonConst`, or we have an issue. Let's + // assert just to be sure. + rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst); + auto anon_const = static_cast<AnonConst *> (inner_expr); + + auto &mappings = Analysis::Mappings::get (); + auto crate_num = mappings.get_current_crate (); + auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (), + mappings.get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::ConstBlock (std::move (mapping), std::move (*anon_const), + expr.get_locus (), expr.get_outer_attrs ()); +} + +void ASTLoweringExpr::visit (AST::UnsafeBlockExpr &expr) { translated = ASTLoweringBlock::translate (expr, &terminated); @@ -175,12 +220,12 @@ ASTLoweringExpr::visit (AST::CallExpr &expr) HIR::Expr *func = ASTLoweringExpr::translate (expr.get_function_expr ()); auto const &in_params = expr.get_params (); + std::vector<std::unique_ptr<HIR::Expr>> params; + params.reserve (in_params.size ()); + for (auto ¶m : in_params) - { - auto trans = ASTLoweringExpr::translate (*param); - params.push_back (std::unique_ptr<HIR::Expr> (trans)); - } + params.emplace_back (ASTLoweringExpr::translate (*param)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping ( @@ -202,11 +247,10 @@ ASTLoweringExpr::visit (AST::MethodCallExpr &expr) auto const &in_params = expr.get_params (); std::vector<std::unique_ptr<HIR::Expr>> params; + params.reserve (in_params.size ()); + for (auto ¶m : in_params) - { - auto trans = ASTLoweringExpr::translate (*param); - params.push_back (std::unique_ptr<HIR::Expr> (trans)); - } + params.emplace_back (ASTLoweringExpr::translate (*param)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -292,11 +336,10 @@ void ASTLoweringExpr::visit (AST::ArrayElemsValues &elems) { std::vector<std::unique_ptr<HIR::Expr>> elements; + elements.reserve (elems.get_values ().size ()); + for (auto &elem : elems.get_values ()) - { - HIR::Expr *translated_elem = ASTLoweringExpr::translate (*elem); - elements.push_back (std::unique_ptr<HIR::Expr> (translated_elem)); - } + elements.emplace_back (ASTLoweringExpr::translate (*elem)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (mappings.get_current_crate (), @@ -523,13 +566,12 @@ ASTLoweringExpr::visit (AST::StructExprStructFields &struct_expr) } auto const &in_fields = struct_expr.get_fields (); + std::vector<std::unique_ptr<HIR::StructExprField>> fields; + fields.reserve (in_fields.size ()); + for (auto &field : in_fields) - { - HIR::StructExprField *translated - = ASTLowerStructExprField::translate (*field); - fields.push_back (std::unique_ptr<HIR::StructExprField> (translated)); - } + fields.emplace_back (ASTLowerStructExprField::translate (*field)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (), @@ -589,16 +631,12 @@ ASTLoweringExpr::visit (AST::WhileLoopExpr &expr) } void -ASTLoweringExpr::visit (AST::ForLoopExpr &expr) -{ - rust_unreachable (); -} - -void ASTLoweringExpr::visit (AST::BreakExpr &expr) { - HIR::Lifetime break_label - = lower_lifetime (expr.get_label ().get_lifetime ()); + tl::optional<HIR::Lifetime> break_label = tl::nullopt; + if (expr.has_label ()) + break_label = lower_lifetime (expr.get_label_unchecked ().get_lifetime ()); + HIR::Expr *break_expr = expr.has_break_expr () ? ASTLoweringExpr::translate (expr.get_break_expr ()) @@ -618,7 +656,9 @@ ASTLoweringExpr::visit (AST::BreakExpr &expr) void ASTLoweringExpr::visit (AST::ContinueExpr &expr) { - HIR::Lifetime break_label = lower_lifetime (expr.get_label ()); + tl::optional<HIR::Lifetime> break_label; + if (expr.has_label ()) + break_label = lower_lifetime (expr.get_label_unchecked ()); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -633,9 +673,6 @@ ASTLoweringExpr::visit (AST::ContinueExpr &expr) void ASTLoweringExpr::visit (AST::BorrowExpr &expr) { - if (expr.is_raw_borrow ()) - rust_unreachable (); - HIR::Expr *borrow_lvalue = ASTLoweringExpr::translate (expr.get_borrowed_expr ()); @@ -646,8 +683,8 @@ ASTLoweringExpr::visit (AST::BorrowExpr &expr) auto *borrow_expr = new HIR::BorrowExpr (mapping, std::unique_ptr<HIR::Expr> (borrow_lvalue), - expr.get_mutability (), expr.get_outer_attrs (), - expr.get_locus ()); + expr.get_mutability (), expr.is_raw_borrow (), + expr.get_outer_attrs (), expr.get_locus ()); if (expr.get_is_double_borrow ()) { @@ -659,8 +696,8 @@ ASTLoweringExpr::visit (AST::BorrowExpr &expr) borrow_expr = new HIR::BorrowExpr (mapping, std::unique_ptr<HIR::Expr> (borrow_expr), - expr.get_mutability (), expr.get_outer_attrs (), - expr.get_locus ()); + expr.get_mutability (), expr.is_raw_borrow (), + expr.get_outer_attrs (), expr.get_locus ()); } translated = borrow_expr; @@ -773,11 +810,10 @@ ASTLoweringExpr::visit (AST::ClosureExprInner &expr) = ASTLoweringExpr::translate (expr.get_definition_expr ()); std::vector<HIR::ClosureParam> closure_params; + closure_params.reserve (expr.get_params ().size ()); + for (auto ¶m : expr.get_params ()) - { - HIR::ClosureParam p = lower_closure_param (param); - closure_params.push_back (std::move (p)); - } + closure_params.emplace_back (lower_closure_param (param)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -797,14 +833,13 @@ ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr) { HIR::Type *closure_return_type = nullptr; HIR::Expr *closure_expr - = ASTLoweringExpr::translate (expr.get_definition_block ()); + = ASTLoweringExpr::translate (expr.get_definition_expr ()); std::vector<HIR::ClosureParam> closure_params; + closure_params.reserve (expr.get_params ().size ()); + for (auto ¶m : expr.get_params ()) - { - HIR::ClosureParam p = lower_closure_param (param); - closure_params.push_back (std::move (p)); - } + closure_params.emplace_back (lower_closure_param (param)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -840,6 +875,7 @@ translate_operand_out (const AST::InlineAsmOperand &operand) *out_value.expr.get ()))); return out; } + HIR::InlineAsmOperand translate_operand_inout (const AST::InlineAsmOperand &operand) { @@ -850,6 +886,7 @@ translate_operand_inout (const AST::InlineAsmOperand &operand) *inout_value.expr.get ()))); return inout; } + HIR::InlineAsmOperand translate_operand_split_in_out (const AST::InlineAsmOperand &operand) { @@ -862,19 +899,21 @@ translate_operand_split_in_out (const AST::InlineAsmOperand &operand) ASTLoweringExpr::translate (*split_in_out_value.out_expr.get ()))); return split_in_out; } + HIR::InlineAsmOperand translate_operand_const (const AST::InlineAsmOperand &operand) { auto const_value = operand.get_const (); - struct HIR::AnonConst anon_const (const_value.anon_const.id, - std::unique_ptr<Expr> ( - ASTLoweringExpr::translate ( - *const_value.anon_const.expr.get ()))); - struct HIR::InlineAsmOperand::Const cnst - { - anon_const - }; - return cnst; + + auto inner_expr = ASTLoweringExpr::translate (const_value.anon_const); + + // Like `ConstBlock`, we know this should only be an `AnonConst` - let's + // assert to make sure and static cast + rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst); + + auto anon_const = static_cast<AnonConst *> (inner_expr); + + return HIR::InlineAsmOperand::Const{*anon_const}; } HIR::InlineAsmOperand @@ -954,6 +993,72 @@ ASTLoweringExpr::visit (AST::InlineAsm &expr) hir_operands, expr.get_clobber_abi (), expr.get_options (), mapping); } + +namespace { +// We're not really supporting llvm_asm, only the bare minimum for libcore's +// blackbox +// llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile"); +bool +check_llvm_asm_support (const std::vector<LlvmOperand> &inputs, + const std::vector<LlvmOperand> &outputs, + const AST::LlvmInlineAsm &expr) +{ + return outputs.size () == 0 && inputs.size () <= 1 + && expr.get_clobbers ().size () <= 1 + && expr.get_templates ().size () == 1 + && expr.get_templates ()[0].symbol == ""; +} + +} // namespace + +void +ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr) +{ + auto crate_num = mappings.get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings.get_next_hir_id (crate_num), + mappings.get_next_localdef_id (crate_num)); + + std::vector<LlvmOperand> inputs; + inputs.reserve (expr.get_inputs ().size ()); + + std::vector<LlvmOperand> outputs; + outputs.reserve (expr.get_outputs ().size ()); + + for (auto i : expr.get_inputs ()) + { + std::unique_ptr<Expr> inner_expr + = std::unique_ptr<Expr> (translate (*i.expr.get ())); + inputs.emplace_back (i.constraint, std::move (inner_expr)); + } + + for (auto o : expr.get_outputs ()) + { + std::unique_ptr<Expr> inner_expr + = std::unique_ptr<Expr> (translate (*o.expr.get ())); + outputs.emplace_back (o.constraint, std::move (inner_expr)); + } + + HIR::LlvmInlineAsm::Options options{expr.is_volatile (), + expr.is_stack_aligned (), + expr.get_dialect ()}; + + if (!check_llvm_asm_support (inputs, outputs, expr)) + { + rust_error_at (expr.get_locus (), "unsupported %qs construct", + "llvm_asm"); + rust_inform ( + expr.get_locus (), + "%<llvm_asm%> has been replaced with %<asm%>, gccrs only supports a " + "subset of %<llvm_asm%> to compile libcore"); + } + + translated + = new HIR::LlvmInlineAsm (expr.get_locus (), inputs, outputs, + expr.get_templates (), expr.get_clobbers (), + options, expr.get_outer_attrs (), mapping); +} + void ASTLoweringExpr::visit (AST::FormatArgs &fmt) { @@ -961,5 +1066,20 @@ ASTLoweringExpr::visit (AST::FormatArgs &fmt) "FormatArgs lowering is not implemented yet"); } +void +ASTLoweringExpr::visit (AST::OffsetOf &offset_of) +{ + auto type = std::unique_ptr<Type> ( + ASTLoweringType::translate (offset_of.get_type ())); + + auto crate_num = mappings.get_current_crate (); + Analysis::NodeMapping mapping (crate_num, offset_of.get_node_id (), + mappings.get_next_hir_id (crate_num), + mappings.get_next_localdef_id (crate_num)); + + translated = new HIR::OffsetOf (std::move (type), offset_of.get_field (), + mapping, offset_of.get_locus ()); +} + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index af60e01..4eed4ec 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -21,6 +21,7 @@ #include "rust-ast-lower-base.h" #include "rust-ast.h" +#include "rust-expr.h" namespace Rust { namespace HIR { @@ -82,6 +83,8 @@ public: void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::BlockExpr &expr) override; + void visit (AST::AnonConst &expr) override; + void visit (AST::ConstBlock &expr) override; void visit (AST::UnsafeBlockExpr &expr) override; void visit (AST::PathInExpression &expr) override; void visit (AST::QualifiedPathInExpression &expr) override; @@ -108,7 +111,6 @@ public: void visit (AST::FieldAccessExpr &expr) override; void visit (AST::LoopExpr &expr) override; void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; void visit (AST::BreakExpr &expr) override; void visit (AST::ContinueExpr &expr) override; void visit (AST::BorrowExpr &expr) override; @@ -122,9 +124,11 @@ public: void visit (AST::ClosureExprInner &expr) override; void visit (AST::ClosureExprInnerTyped &expr) override; void visit (AST::InlineAsm &expr) override; + void visit (AST::LlvmInlineAsm &expr) override; - // Extra visitor for FormatArgs nodes + // Extra visitor for builtin macro nodes void visit (AST::FormatArgs &fmt) override; + void visit (AST::OffsetOf &offset_of) override; private: ASTLoweringExpr (); diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h index 0105e38..1f3ceda 100644 --- a/gcc/rust/hir/rust-ast-lower-extern.h +++ b/gcc/rust/hir/rust-ast-lower-extern.h @@ -99,7 +99,7 @@ public: = static_cast<AST::IdentifierPattern &> (param.get_pattern ()); Identifier param_name = param_kind == AST::Pattern::Kind::Identifier ? param_ident.get_ident () - : std::string ("_"); + : Identifier ("_", param.get_locus ()); HIR::Type *param_type = ASTLoweringType::translate (param.get_type ()); @@ -109,9 +109,8 @@ public: mappings.get_next_localdef_id ( crate_num)); - function_params.push_back ( - HIR::NamedFunctionParam (mapping, param_name, - std::unique_ptr<HIR::Type> (param_type))); + function_params.emplace_back (mapping, param_name, + std::unique_ptr<HIR::Type> (param_type)); } auto crate_num = mappings.get_current_crate (); diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc index 5380d25..87f1e01 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.cc +++ b/gcc/rust/hir/rust-ast-lower-implitem.cc @@ -22,6 +22,7 @@ #include "rust-ast-lower-expr.h" #include "rust-ast-lower-pattern.h" #include "rust-ast-lower-block.h" +#include "rust-hir-item.h" #include "rust-item.h" namespace Rust { @@ -54,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 ()); @@ -109,12 +110,12 @@ 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 = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); + where_clause_items.emplace_back (i); } HIR::WhereClause where_clause (std::move (where_clause_items)); @@ -123,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 ()); @@ -131,15 +132,19 @@ ASTLowerImplItem::visit (AST::Function &function) Identifier function_name = function.get_function_name (); location_t locus = function.get_locus (); - HIR::SelfParam self_param = HIR::SelfParam::error (); + tl::optional<HIR::SelfParam> self_param = tl::nullopt; if (function.has_self_param ()) self_param = lower_self (function.get_self_param ()); std::unique_ptr<HIR::Type> return_type = function.has_return_type () ? std::unique_ptr<HIR::Type> ( - ASTLoweringType::translate (function.get_return_type ())) + ASTLoweringType::translate (function.get_return_type (), false, + true /* impl trait is allowed here*/)) : nullptr; + Defaultness defaultness + = function.is_default () ? Defaultness::Default : Defaultness::Final; + std::vector<HIR::FunctionParam> function_params; for (auto &p : function.get_function_params ()) { @@ -157,10 +162,9 @@ ASTLowerImplItem::visit (AST::Function &function) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - auto hir_param - = HIR::FunctionParam (mapping, std::move (translated_pattern), - std::move (translated_type), param.get_locus ()); - function_params.push_back (std::move (hir_param)); + function_params.emplace_back (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); } bool terminated = false; @@ -183,15 +187,15 @@ ASTLowerImplItem::visit (AST::Function &function) std::move (function_params), std::move (return_type), std::move (where_clause), std::move (function_body), std::move (vis), function.get_outer_attrs (), - std::move (self_param), locus); + std::move (self_param), defaultness, locus); - if (!fn->get_self_param ().is_error ()) + if (fn->is_method ()) { // insert mappings for self - mappings.insert_hir_self_param (&fn->get_self_param ()); + mappings.insert_hir_self_param (&fn->get_self_param_unchecked ()); mappings.insert_location ( - fn->get_self_param ().get_mappings ().get_hirid (), - fn->get_self_param ().get_locus ()); + fn->get_self_param_unchecked ().get_mappings ().get_hirid (), + fn->get_self_param_unchecked ().get_locus ()); } // add the mappings for the function params at the end @@ -229,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 ()); @@ -245,9 +249,9 @@ ASTLowerTraitItem::visit (AST::Function &func) // set self parameter to error if this is a method // else lower to hir - HIR::SelfParam self_param = func.has_self_param () - ? lower_self (func.get_self_param ()) - : HIR::SelfParam::error (); + tl::optional<HIR::SelfParam> self_param = tl::nullopt; + if (func.has_self_param ()) + self_param = lower_self (func.get_self_param ()); std::vector<HIR::FunctionParam> function_params; for (auto &p : func.get_function_params ()) @@ -267,10 +271,18 @@ ASTLowerTraitItem::visit (AST::Function &func) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - auto hir_param - = HIR::FunctionParam (mapping, std::move (translated_pattern), - std::move (translated_type), param.get_locus ()); - function_params.push_back (hir_param); + function_params.emplace_back (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); + } + + if (func.has_self_param ()) + { + // insert mappings for self + // TODO: Is this correct ? Looks fishy + mappings.insert_hir_self_param (&*self_param); + mappings.insert_location (self_param->get_mappings ().get_hirid (), + self_param->get_locus ()); } HIR::TraitFunctionDecl decl (func.get_function_name (), @@ -296,13 +308,6 @@ ASTLowerTraitItem::visit (AST::Function &func) = new HIR::TraitItemFunc (mapping, std::move (decl), std::move (block_expr), func.get_outer_attrs (), func.get_locus ()); translated = trait_item; - if (func.has_self_param ()) - { - // insert mappings for self - mappings.insert_hir_self_param (&self_param); - mappings.insert_location (self_param.get_mappings ().get_hirid (), - self_param.get_locus ()); - } // add the mappings for the function params at the end for (auto ¶m : trait_item->get_decl ().get_function_params ()) @@ -313,10 +318,10 @@ ASTLowerTraitItem::visit (AST::Function &func) } void -ASTLowerTraitItem::visit (AST::TraitItemConst &constant) +ASTLowerTraitItem::visit (AST::ConstantItem &constant) { HIR::Type *type = ASTLoweringType::translate (constant.get_type ()); - HIR::Expr *expr = constant.has_expression () + HIR::Expr *expr = constant.has_expr () ? ASTLoweringExpr::translate (constant.get_expr ()) : nullptr; @@ -337,7 +342,24 @@ ASTLowerTraitItem::visit (AST::TraitItemConst &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), @@ -345,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-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h index 8331bba..dfcf567 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.h +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -49,7 +49,7 @@ class ASTLowerTraitItem : public ASTLoweringBase public: static HIR::TraitItem *translate (AST::AssociatedItem &item); void visit (AST::Function &func) override; - void visit (AST::TraitItemConst &constant) override; + void visit (AST::ConstantItem &constant) override; void visit (AST::TraitItemType &type) override; private: diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index 5dbcad5..81815ff 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -72,7 +72,7 @@ ASTLoweringItem::visit (AST::Module &module) // The item may be null if it doesn't need to live in the HIR - for // example, macro rules definitions if (transitem) - items.push_back (std::unique_ptr<Item> (transitem)); + items.emplace_back (transitem); } // should be lowered/copied from module.get_in/outer_attrs() @@ -90,12 +90,11 @@ void ASTLoweringItem::visit (AST::TypeAlias &alias) { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve (alias.get_where_clause ().get_items ().size ()); + for (auto &item : alias.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (alias.get_visibility ()); @@ -130,17 +129,19 @@ ASTLoweringItem::visit (AST::TupleStruct &struct_decl) } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + struct_decl.get_where_clause ().get_items ().size ()); + for (auto &item : struct_decl.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ()); std::vector<HIR::TupleField> fields; + fields.reserve (struct_decl.get_fields ().size ()); + for (AST::TupleField &field : struct_decl.get_fields ()) { if (field.get_field_type ().is_marked_for_strip ()) @@ -155,11 +156,8 @@ ASTLoweringItem::visit (AST::TupleStruct &struct_decl) mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); - HIR::TupleField translated_field (mapping, - std::unique_ptr<HIR::Type> (type), vis, - field.get_locus (), - field.get_outer_attrs ()); - fields.push_back (std::move (translated_field)); + fields.emplace_back (mapping, std::unique_ptr<HIR::Type> (type), vis, + field.get_locus (), field.get_outer_attrs ()); } auto crate_num = mappings.get_current_crate (); @@ -185,12 +183,12 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl) } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + struct_decl.get_where_clause ().get_items ().size ()); + for (auto &item : struct_decl.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); @@ -217,7 +215,7 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl) field.get_outer_attrs ()); if (struct_field_name_exists (fields, translated_field)) - break; + continue; fields.push_back (std::move (translated_field)); } @@ -245,25 +243,26 @@ ASTLoweringItem::visit (AST::Enum &enum_decl) } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + enum_decl.get_where_clause ().get_items ().size ()); + for (auto &item : enum_decl.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (enum_decl.get_visibility ()); // bool is_unit = enum_decl.is_zero_variant (); std::vector<std::unique_ptr<HIR::EnumItem>> items; + items.reserve (enum_decl.get_variants ().size ()); + for (auto &variant : enum_decl.get_variants ()) { if (variant->is_marked_for_strip ()) continue; - HIR::EnumItem *hir_item = ASTLoweringEnumItem::translate (variant.get ()); - items.push_back (std::unique_ptr<HIR::EnumItem> (hir_item)); + items.emplace_back (ASTLoweringEnumItem::translate (variant.get ())); } auto crate_num = mappings.get_current_crate (); @@ -288,17 +287,16 @@ ASTLoweringItem::visit (AST::Union &union_decl) { std::vector<std::unique_ptr<HIR::GenericParam>> generic_params; if (union_decl.has_generics ()) - { - generic_params = lower_generic_params (union_decl.get_generic_params ()); - } + generic_params = lower_generic_params (union_decl.get_generic_params ()); std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + union_decl.get_where_clause ().get_items ().size ()); + for (auto &item : union_decl.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (union_decl.get_visibility ()); @@ -367,7 +365,9 @@ ASTLoweringItem::visit (AST::ConstantItem &constant) HIR::Visibility vis = translate_visibility (constant.get_visibility ()); HIR::Type *type = ASTLoweringType::translate (constant.get_type (), true); - HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ()); + HIR::Expr *expr = nullptr; + if (constant.has_expr ()) + expr = ASTLoweringExpr::translate (constant.get_expr ()); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, constant.get_node_id (), @@ -388,12 +388,12 @@ ASTLoweringItem::visit (AST::Function &function) return; std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + function.get_where_clause ().get_items ().size ()); + for (auto &item : function.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::FunctionQualifiers qualifiers @@ -411,14 +411,46 @@ ASTLoweringItem::visit (AST::Function &function) std::unique_ptr<HIR::Type> return_type = function.has_return_type () ? std::unique_ptr<HIR::Type> ( - ASTLoweringType::translate (function.get_return_type ())) + ASTLoweringType::translate (function.get_return_type (), false, + true /* impl trait is allowed here*/)) : nullptr; std::vector<HIR::FunctionParam> function_params; + function_params.reserve (function.get_function_params ().size ()); + + auto crate_num = mappings.get_current_crate (); for (auto &p : function.get_function_params ()) { - if (p->is_variadic () || p->is_self ()) + if (p->is_variadic ()) continue; + if (p->is_self ()) + { + rich_location r (line_table, p->get_locus ()); + r.add_range (function.get_locus ()); + rust_error_at ( + r, "%<self%> parameter is only allowed in associated functions"); + + // rustc creates a synthetic regular fn-param here pointing to a + // generic Self as far as i can see but that seems over the top for + // now. + // + // see this example (invalid code): + // + // pub trait X { + // fn x() { + // fn f(&mut self) {} + // f(); + // } + // } + // + // without a synthetic param we wont get the number of args error as + // well but i think this is fine for now. + // + // problem is what we make the param type to become... + + continue; + } + auto param = static_cast<AST::FunctionParam &> (*p); auto translated_pattern = std::unique_ptr<HIR::Pattern> ( @@ -431,10 +463,9 @@ ASTLoweringItem::visit (AST::Function &function) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - auto hir_param - = HIR::FunctionParam (mapping, std::move (translated_pattern), - std::move (translated_type), param.get_locus ()); - function_params.push_back (std::move (hir_param)); + function_params.emplace_back (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); } bool terminated = false; @@ -443,7 +474,6 @@ ASTLoweringItem::visit (AST::Function &function) ASTLoweringBlock::translate (*function.get_definition ().value (), &terminated)); - auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, function.get_node_id (), mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); @@ -451,13 +481,16 @@ ASTLoweringItem::visit (AST::Function &function) mappings.insert_location (function_body->get_mappings ().get_hirid (), function.get_locus ()); + Defaultness defaultness + = function.is_default () ? Defaultness::Default : Defaultness::Final; + auto fn = new HIR::Function (mapping, std::move (function_name), std::move (qualifiers), std::move (generic_params), std::move (function_params), std::move (return_type), std::move (where_clause), std::move (function_body), std::move (vis), function.get_outer_attrs (), - HIR::SelfParam::error (), locus); + tl::nullopt, defaultness, locus); // add the mappings for the function params at the end for (auto ¶m : fn->get_function_params ()) @@ -473,11 +506,12 @@ void ASTLoweringItem::visit (AST::InherentImpl &impl_block) { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + impl_block.get_where_clause ().get_items ().size ()); + for (auto &item : impl_block.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item)); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (impl_block.get_visibility ()); @@ -491,7 +525,8 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block) { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { const HIR::TypeParam &t = static_cast<const HIR::TypeParam &> (*generic_param); @@ -533,7 +568,7 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block) HIR::ImplItem *lowered = ASTLowerImplItem::translate (*impl_item, mapping.get_hirid ()); rust_assert (lowered != nullptr); - impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered)); + impl_items.emplace_back (lowered); impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ()); } @@ -556,12 +591,12 @@ void ASTLoweringItem::visit (AST::Trait &trait) { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve (trait.get_where_clause ().get_items ().size ()); + for (auto &item : trait.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (trait.get_visibility ()); @@ -582,23 +617,24 @@ ASTLoweringItem::visit (AST::Trait &trait) if (trait.has_type_param_bounds ()) { for (auto &bound : trait.get_type_param_bounds ()) - { - HIR::TypeParamBound *b = lower_bound (*bound); - type_param_bounds.push_back ( - std::unique_ptr<HIR::TypeParamBound> (b)); - } + type_param_bounds.emplace_back (lower_bound (*bound)); } + auto trait_item_size = trait.get_trait_items ().size (); + std::vector<std::unique_ptr<HIR::TraitItem>> trait_items; + trait_items.reserve (trait_item_size); std::vector<HirId> trait_item_ids; + trait_item_ids.reserve (trait_item_size); + for (auto &item : trait.get_trait_items ()) { if (item->is_marked_for_strip ()) continue; HIR::TraitItem *lowered = ASTLowerTraitItem::translate (*item); - trait_items.push_back (std::unique_ptr<HIR::TraitItem> (lowered)); trait_item_ids.push_back (lowered->get_mappings ().get_hirid ()); + trait_items.emplace_back (lowered); } auto crate_num = mappings.get_current_crate (); @@ -629,13 +665,16 @@ ASTLoweringItem::visit (AST::Trait &trait) void ASTLoweringItem::visit (AST::TraitImpl &impl_block) { - std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; bool unsafe = impl_block.is_unsafe (); + + std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + impl_block.get_where_clause ().get_items ().size ()); + for (auto &item : impl_block.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item)); + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (impl_block.get_visibility ()); @@ -648,7 +687,8 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block) { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { const HIR::TypeParam &t = static_cast<const HIR::TypeParam &> (*generic_param); @@ -682,8 +722,13 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block) mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); + auto impl_items_size = impl_block.get_impl_items ().size (); + std::vector<std::unique_ptr<HIR::ImplItem>> impl_items; + impl_items.reserve (impl_items_size); std::vector<HirId> impl_item_ids; + impl_item_ids.reserve (impl_items_size); + for (auto &impl_item : impl_block.get_impl_items ()) { if (impl_item->is_marked_for_strip ()) @@ -692,8 +737,8 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block) HIR::ImplItem *lowered = ASTLowerImplItem::translate (*impl_item, mapping.get_hirid ()); rust_assert (lowered != nullptr); - impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered)); impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ()); + impl_items.emplace_back (lowered); } BoundPolarity polarity = impl_block.is_exclam () @@ -726,6 +771,25 @@ ASTLoweringItem::visit (AST::MacroRulesDefinition &def) lower_macro_definition (def); } +void +ASTLoweringItem::visit (AST::ExternCrate &extern_crate) +{ + if (extern_crate.references_self ()) + return; + + auto &mappings = Analysis::Mappings::get (); + CrateNum num + = mappings.lookup_crate_name (extern_crate.get_referenced_crate ()) + .value (); + AST::Crate &crate = mappings.get_ast_crate (num); + + auto saved_crate_num = mappings.get_current_crate (); + mappings.set_current_crate (num); + auto lowered = ASTLowering::Resolve (crate); + mappings.insert_hir_crate (std::move (lowered)); + mappings.set_current_crate (saved_crate_num); +} + HIR::SimplePath ASTLoweringSimplePath::translate (const AST::SimplePath &path) { diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 4e142ed..dc75057 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -45,6 +45,7 @@ public: void visit (AST::TraitImpl &impl_block) override; void visit (AST::ExternBlock &extern_block) override; void visit (AST::MacroRulesDefinition &rules_def) override; + void visit (AST::ExternCrate &extern_crate) override; private: ASTLoweringItem () : translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index b7a4c56..c941a5c 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -23,7 +23,9 @@ namespace Rust { namespace HIR { -ASTLoweringPattern::ASTLoweringPattern () : translated (nullptr) {} +ASTLoweringPattern::ASTLoweringPattern () + : translated (nullptr), is_let_top_level (false) +{} HIR::Pattern * ASTLoweringPattern::translate (AST::Pattern &pattern, bool is_let_top_level) @@ -49,13 +51,18 @@ ASTLoweringPattern::visit (AST::IdentifierPattern &pattern) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - std::unique_ptr<Pattern> to_bind; + std::unique_ptr<Pattern> subpattern; + if (pattern.has_subpattern ()) + { + subpattern = std::unique_ptr<Pattern> ( + ASTLoweringPattern::translate (pattern.get_subpattern ())); + } translated = new HIR::IdentifierPattern (mapping, pattern.get_ident (), pattern.get_locus (), pattern.get_is_ref (), pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm, - std::move (to_bind)); + std::move (subpattern)); } void @@ -74,24 +81,45 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case AST::TupleStructItems::RANGE: { - // TODO - rust_unreachable (); + case AST::TupleStructItems::HAS_REST: + { + AST::TupleStructItemsHasRest &items_has_rest + = static_cast<AST::TupleStructItemsHasRest &> (items); + + std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns; + lower_patterns.reserve (items_has_rest.get_lower_patterns ().size ()); + for (auto &pattern_member : items_has_rest.get_lower_patterns ()) + { + lower_patterns.emplace_back ( + ASTLoweringPattern::translate (*pattern_member)); + } + + std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns; + upper_patterns.reserve (items_has_rest.get_upper_patterns ().size ()); + for (auto &pattern_member : items_has_rest.get_upper_patterns ()) + { + upper_patterns.emplace_back ( + ASTLoweringPattern::translate (*pattern_member)); + } + + lowered = new HIR::TupleStructItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns)); } break; - case AST::TupleStructItems::NO_RANGE: { - AST::TupleStructItemsNoRange &items_no_range - = static_cast<AST::TupleStructItemsNoRange &> (items); + case AST::TupleStructItems::NO_REST: + { + AST::TupleStructItemsNoRest &items_no_rest + = static_cast<AST::TupleStructItemsNoRest &> (items); std::vector<std::unique_ptr<HIR::Pattern>> patterns; - for (auto &inner_pattern : items_no_range.get_patterns ()) - { - HIR::Pattern *p = ASTLoweringPattern::translate (*inner_pattern); - patterns.push_back (std::unique_ptr<HIR::Pattern> (p)); - } + patterns.reserve (items_no_rest.get_patterns ().size ()); + + for (auto &inner_pattern : items_no_rest.get_patterns ()) + patterns.emplace_back ( + ASTLoweringPattern::translate (*inner_pattern)); - lowered = new HIR::TupleStructItemsNoRange (std::move (patterns)); + lowered = new HIR::TupleStructItemsNoRest (std::move (patterns)); } break; } @@ -112,7 +140,6 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) = ASTLowerPathInExpression::translate (pattern.get_path ()); auto &raw_elems = pattern.get_struct_pattern_elems (); - rust_assert (!raw_elems.has_etc ()); std::vector<std::unique_ptr<HIR::StructPatternField>> fields; for (auto &field : raw_elems.get_struct_pattern_fields ()) @@ -120,7 +147,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) HIR::StructPatternField *f = nullptr; switch (field->get_item_type ()) { - case AST::StructPatternField::ItemType::TUPLE_PAT: { + case AST::StructPatternField::ItemType::TUPLE_PAT: + { auto &tuple = static_cast<AST::StructPatternFieldTuplePat &> (*field); @@ -140,7 +168,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT_PAT: { + case AST::StructPatternField::ItemType::IDENT_PAT: + { AST::StructPatternFieldIdentPat &ident = static_cast<AST::StructPatternFieldIdentPat &> (*field); @@ -160,7 +189,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT: { + case AST::StructPatternField::ItemType::IDENT: + { AST::StructPatternFieldIdent &ident = static_cast<AST::StructPatternFieldIdent &> (*field.get ()); @@ -184,7 +214,7 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) mappings.insert_node_to_hir (field_node_id, field_id); // add it to the lowered fields list - fields.push_back (std::unique_ptr<HIR::StructPatternField> (f)); + fields.emplace_back (f); } auto crate_num = mappings.get_current_crate (); @@ -192,7 +222,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - HIR::StructPatternElements elems (std::move (fields)); + HIR::StructPatternElements elems ( + std::move (fields), pattern.get_struct_pattern_elems ().has_rest ()); translated = new HIR::StructPattern (mapping, *path, std::move (elems)); } @@ -211,19 +242,20 @@ void ASTLoweringPattern::visit (AST::TuplePattern &pattern) { std::unique_ptr<HIR::TuplePatternItems> items; - switch (pattern.get_items ().get_pattern_type ()) + switch (pattern.get_items ().get_item_type ()) { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: { - AST::TuplePatternItemsMultiple &ref - = static_cast<AST::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + case AST::TuplePatternItems::ItemType::NO_REST: + { + AST::TuplePatternItemsNoRest &ref + = static_cast<AST::TuplePatternItemsNoRest &> (pattern.get_items ()); items = lower_tuple_pattern_multiple (ref); } break; - case AST::TuplePatternItems::TuplePatternItemType::RANGED: { - AST::TuplePatternItemsRanged &ref - = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ()); + case AST::TuplePatternItems::ItemType::HAS_REST: + { + AST::TuplePatternItemsHasRest &ref + = static_cast<AST::TuplePatternItemsHasRest &> (pattern.get_items ()); items = lower_tuple_pattern_ranged (ref); } break; @@ -248,14 +280,13 @@ 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 ASTLoweringPattern::visit (AST::RangePattern &pattern) { - if (pattern.get_range_kind () == AST::RangeKind::EXCLUDED) - rust_unreachable (); // Not supported yet auto upper_bound = lower_range_pattern_bound (pattern.get_upper_bound ()); auto lower_bound = lower_range_pattern_bound (pattern.get_lower_bound ()); @@ -264,9 +295,11 @@ ASTLoweringPattern::visit (AST::RangePattern &pattern) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - translated - = new HIR::RangePattern (mapping, std::move (lower_bound), - std::move (upper_bound), pattern.get_locus ()); + bool is_inclusive = (pattern.get_range_kind () == AST::RangeKind::INCLUDED); + + translated = new HIR::RangePattern (mapping, std::move (lower_bound), + std::move (upper_bound), + pattern.get_locus (), is_inclusive); } void @@ -308,11 +341,24 @@ ASTLoweringPattern::visit (AST::ReferencePattern &pattern) void ASTLoweringPattern::visit (AST::SlicePattern &pattern) { - std::vector<std::unique_ptr<HIR::Pattern>> items; - for (auto &p : pattern.get_items ()) + std::unique_ptr<HIR::SlicePatternItems> items; + + switch (pattern.get_items ().get_item_type ()) { - HIR::Pattern *item = ASTLoweringPattern::translate (*p); - items.push_back (std::unique_ptr<HIR::Pattern> (item)); + case AST::SlicePatternItems::ItemType::NO_REST: + { + auto &ref + = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ()); + items = ASTLoweringBase::lower_slice_pattern_no_rest (ref); + } + break; + case AST::SlicePatternItems::ItemType::HAS_REST: + { + auto &ref + = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ()); + items = ASTLoweringBase::lower_slice_pattern_has_rest (ref); + } + break; } auto crate_num = mappings.get_current_crate (); @@ -333,12 +379,10 @@ ASTLoweringPattern::visit (AST::AltPattern &pattern) UNKNOWN_LOCAL_DEFID); std::vector<std::unique_ptr<HIR::Pattern>> alts; + alts.reserve (pattern.get_alts ().size ()); for (auto &alt : pattern.get_alts ()) - { - alts.push_back ( - std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*alt))); - } + alts.emplace_back (ASTLoweringPattern::translate (*alt)); translated = new HIR::AltPattern (mapping, std::move (alts), pattern.get_locus ()); diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index d3e528d..1841576 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -209,10 +209,17 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path) path.get_locus ()); } +ASTLoweringType::ASTLoweringType (bool default_to_static_lifetime, + bool impl_trait_allowed) + : ASTLoweringBase (), default_to_static_lifetime (default_to_static_lifetime), + impl_trait_allowed (impl_trait_allowed), translated (nullptr) +{} + HIR::Type * -ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime) +ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime, + bool impl_trait_allowed) { - ASTLoweringType resolver (default_to_static_lifetime); + ASTLoweringType resolver (default_to_static_lifetime, impl_trait_allowed); type.accept_vis (resolver); rust_assert (resolver.translated != nullptr); @@ -260,7 +267,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) HIR::Type *param_type = ASTLoweringType::translate (param.get_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); HIR::MaybeNamedParam p (param.get_name (), kind, std::unique_ptr<HIR::Type> (param_type), @@ -272,7 +280,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) if (fntype.has_return_type ()) { return_type = ASTLoweringType::translate (fntype.get_return_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); } auto crate_num = mappings.get_current_crate (); @@ -292,8 +301,8 @@ ASTLoweringType::visit (AST::TupleType &tuple) std::vector<std::unique_ptr<HIR::Type>> elems; for (auto &e : tuple.get_elems ()) { - HIR::Type *t - = ASTLoweringType::translate (*e, default_to_static_lifetime); + HIR::Type *t = ASTLoweringType::translate (*e, default_to_static_lifetime, + impl_trait_allowed); elems.push_back (std::unique_ptr<HIR::Type> (t)); } @@ -323,7 +332,8 @@ ASTLoweringType::visit (AST::ArrayType &type) { HIR::Type *translated_type = ASTLoweringType::translate (type.get_elem_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); HIR::Expr *array_size = ASTLoweringExpr::translate (type.get_size_expr ()); auto crate_num = mappings.get_current_crate (); @@ -343,9 +353,9 @@ ASTLoweringType::visit (AST::ReferenceType &type) HIR::Lifetime lifetime = lower_lifetime (type.get_lifetime (), default_to_static_lifetime); - HIR::Type *base_type - = ASTLoweringType::translate (type.get_base_type (), - default_to_static_lifetime); + HIR::Type *base_type = ASTLoweringType::translate (type.get_base_type (), + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -364,7 +374,8 @@ ASTLoweringType::visit (AST::RawPointerType &type) { HIR::Type *base_type = ASTLoweringType::translate (type.get_type_pointed_to (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -384,9 +395,9 @@ ASTLoweringType::visit (AST::RawPointerType &type) void ASTLoweringType::visit (AST::SliceType &type) { - HIR::Type *base_type - = ASTLoweringType::translate (type.get_elem_type (), - default_to_static_lifetime); + HIR::Type *base_type = ASTLoweringType::translate (type.get_elem_type (), + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -463,7 +474,8 @@ void ASTLoweringType::visit (AST::ParenthesisedType &type) { auto *inner = ASTLoweringType::translate (*type.get_type_in_parens (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -480,6 +492,9 @@ ASTLoweringType::visit (AST::ParenthesisedType &type) void ASTLoweringType::visit (AST::ImplTraitType &type) { + if (!impl_trait_allowed) + emit_impl_trait_error (type.get_locus ()); + std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds; for (auto &bound : type.get_type_param_bounds ()) { @@ -499,9 +514,12 @@ ASTLoweringType::visit (AST::ImplTraitType &type) void ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type) { + if (!impl_trait_allowed) + emit_impl_trait_error (type.get_locus ()); + std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds; - auto b = ASTLoweringTypeBounds::translate (type.get_trait_bound ()); + auto b = ASTLoweringTypeBounds::translate (*type.get_trait_bound ().get ()); bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (b)); auto crate_num = mappings.get_current_crate (); @@ -513,6 +531,15 @@ ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type) = new HIR::ImplTraitType (mapping, std::move (bounds), type.get_locus ()); } +void +ASTLoweringType::emit_impl_trait_error (location_t locus) +{ + rich_location r (line_table, locus); + rust_error_at (r, ErrorCode::E0562, + "%<impl Trait%> not allowed outside of function and inherent " + "method return types"); +} + HIR::GenericParam * ASTLowerGenericParam::translate (AST::GenericParam ¶m) { @@ -557,7 +584,7 @@ ASTLowerGenericParam::visit (AST::ConstGenericParam ¶m) HIR::Expr *default_expr = nullptr; if (param.has_default_value ()) default_expr = ASTLoweringExpr::translate ( - param.get_default_value ().get_expression ()); + param.get_default_value_unchecked ().get_expression ()); translated = new HIR::ConstGenericParam (param.get_name ().as_string (), std::unique_ptr<Type> (type), @@ -593,7 +620,8 @@ ASTLowerGenericParam::visit (AST::TypeParam ¶m) translated = new HIR::TypeParam (mapping, param.get_type_representation (), param.get_locus (), std::move (type_param_bounds), - std::move (type), param.get_outer_attrs ()); + std::move (type), param.get_outer_attrs (), + param.from_impl_trait ()); } HIR::TypeParamBound * diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 4efaeee..50f543a 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -66,7 +66,8 @@ class ASTLoweringType : public ASTLoweringBase public: static HIR::Type *translate (AST::Type &type, - bool default_to_static_lifetime = false); + bool default_to_static_lifetime = false, + bool impl_trait_allowed = false); void visit (AST::BareFunctionType &fntype) override; void visit (AST::TupleType &tuple) override; @@ -81,19 +82,17 @@ public: void visit (AST::TraitObjectTypeOneBound &type) override; void visit (AST::TraitObjectType &type) override; void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitType &type) override; void visit (AST::ImplTraitTypeOneBound &type) override; + void emit_impl_trait_error (location_t locus); + private: - ASTLoweringType (bool default_to_static_lifetime) - : ASTLoweringBase (), - default_to_static_lifetime (default_to_static_lifetime), - translated (nullptr) - {} + ASTLoweringType (bool default_to_static_lifetime, bool impl_trait_allowed); /** Used when compiling const and static items. */ bool default_to_static_lifetime; + bool impl_trait_allowed; HIR::Type *translated; }; diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index ebdf981..5b8e7c5 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -80,7 +80,7 @@ ASTLowering::go () { auto translated = ASTLoweringItem::translate (*item); if (translated != nullptr) - items.push_back (std::unique_ptr<HIR::Item> (translated)); + items.emplace_back (translated); } auto &mappings = Analysis::Mappings::get (); @@ -97,7 +97,11 @@ ASTLowering::go () void ASTLoweringBlock::visit (AST::BlockExpr &expr) { - auto label = lower_loop_label (expr.get_label ()); + tl::optional<HIR::LoopLabel> label; + if (expr.has_label ()) + label = lower_loop_label (expr.get_label ()); + else + label = tl::nullopt; std::vector<std::unique_ptr<HIR::Stmt>> block_stmts; bool block_did_terminate = false; @@ -123,7 +127,7 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr) block_did_terminate |= terminated; if (translated_stmt) - block_stmts.push_back (std::unique_ptr<HIR::Stmt> (translated_stmt)); + block_stmts.emplace_back (translated_stmt); } if (expr.has_tail_expr () && block_did_terminate) @@ -227,6 +231,7 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr, { HIR::Expr *kase_expr; std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns; + match_arm_patterns.reserve (expr.get_patterns ().size ()); *branch_value = ASTLoweringExpr::translate (expr.get_value_expr ()); kase_expr = ASTLoweringExpr::translate (expr.get_if_block ()); @@ -237,10 +242,7 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr, rust_assert (expr.get_patterns ().size () == 1); for (auto &pattern : expr.get_patterns ()) - { - HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern); - match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn)); - } + match_arm_patterns.emplace_back (ASTLoweringPattern::translate (*pattern)); // The match arm corresponding to the if let pattern when it matches. HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), nullptr, @@ -251,9 +253,8 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr, mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - HIR::MatchCase kase (std::move (mapping), std::move (arm), - std::unique_ptr<HIR::Expr> (kase_expr)); - match_arms.push_back (std::move (kase)); + match_arms.emplace_back (std::move (mapping), std::move (arm), + std::unique_ptr<HIR::Expr> (kase_expr)); // The default match arm when the if let pattern does not match std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns_wildcard; @@ -261,19 +262,14 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr, mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - std::unique_ptr<HIR::WildcardPattern> wc - = std::unique_ptr<HIR::WildcardPattern> ( - new HIR::WildcardPattern (mapping_default, expr.get_locus ())); - - match_arm_patterns_wildcard.push_back (std::move (wc)); + match_arm_patterns_wildcard.emplace_back ( + new HIR::WildcardPattern (mapping_default, expr.get_locus ())); HIR::MatchArm arm_default (std::move (match_arm_patterns_wildcard), expr.get_locus (), nullptr, {}); - HIR::MatchCase kase_else (std::move (mapping_default), - std::move (arm_default), - std::unique_ptr<HIR::Expr> (kase_else_expr)); - match_arms.push_back (std::move (kase_else)); + match_arms.emplace_back (std::move (mapping_default), std::move (arm_default), + std::unique_ptr<HIR::Expr> (kase_else_expr)); } void @@ -398,7 +394,10 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr) HIR::BlockExpr *loop_block = ASTLoweringBlock::translate (expr.get_loop_block (), &terminated); - HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ()); + tl::optional<HIR::LoopLabel> loop_label; + if (expr.has_loop_label ()) + loop_label = lower_loop_label (expr.get_loop_label ()); + HIR::Expr *loop_condition = ASTLoweringExpr::translate (expr.get_predicate_expr (), &terminated); @@ -416,12 +415,6 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr) } void -ASTLoweringExprWithBlock::visit (AST::ForLoopExpr &expr) -{ - rust_unreachable (); -} - -void ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr) { HIR::Expr *branch_value @@ -441,11 +434,12 @@ ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr) } std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns; + match_arm_patterns.reserve ( + match_case.get_arm ().get_patterns ().size ()); + for (auto &pattern : match_case.get_arm ().get_patterns ()) - { - HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern); - match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn)); - } + match_arm_patterns.emplace_back ( + ASTLoweringPattern::translate (*pattern)); HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), std::unique_ptr<HIR::Expr> (kase_guard_expr), @@ -456,9 +450,8 @@ ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - HIR::MatchCase kase (std::move (mapping), std::move (arm), - std::unique_ptr<HIR::Expr> (kase_expr)); - match_arms.push_back (std::move (kase)); + match_arms.emplace_back (std::move (mapping), std::move (arm), + std::unique_ptr<HIR::Expr> (kase_expr)); } auto crate_num = mappings.get_current_crate (); @@ -489,8 +482,11 @@ ASTLowerPathInExpression::visit (AST::PathInExpression &expr) return; } - std::vector<HIR::PathExprSegment> path_segments; auto &segments = expr.get_segments (); + + std::vector<HIR::PathExprSegment> path_segments; + path_segments.reserve (segments.size ()); + for (auto &s : segments) { path_segments.push_back (lower_path_expr_seg ((s))); @@ -530,8 +526,11 @@ ASTLowerQualPathInExpression::visit (AST::QualifiedPathInExpression &expr) HIR::QualifiedPathType qual_path_type = lower_qual_path_type (expr.get_qualified_path_type ()); - std::vector<HIR::PathExprSegment> path_segments; auto &segments = expr.get_segments (); + + std::vector<HIR::PathExprSegment> path_segments; + path_segments.reserve (segments.size ()); + for (auto &s : segments) { path_segments.push_back (lower_path_expr_seg ((s))); diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h index cc74082..0787ddf 100644 --- a/gcc/rust/hir/rust-ast-lower.h +++ b/gcc/rust/hir/rust-ast-lower.h @@ -28,16 +28,14 @@ namespace HIR { /* Checks whether the name of a field already exists. Returns true and produces an error if so. */ -bool -struct_field_name_exists (std::vector<HIR::StructField> &fields, - HIR::StructField &new_field); +bool struct_field_name_exists (std::vector<HIR::StructField> &fields, + HIR::StructField &new_field); /** * Lowers a Visibility from the AST into an HIR Visibility, desugaring it in * the process */ -Visibility -translate_visibility (const AST::Visibility &vis); +Visibility translate_visibility (const AST::Visibility &vis); /** * Main base class used for lowering AST to HIR. diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index 89fcc3d..49ce143 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -92,7 +92,7 @@ Dump::go (HIR::Crate &e) end ("Crate"); } -Dump::Dump (std::ostream &stream) : stream (stream) {} +Dump::Dump (std::ostream &stream) : beg_of_line (false), stream (stream) {} /** * Writes TEXT with a final newline if ENDLINE is true. @@ -546,7 +546,8 @@ Dump::do_traitfunctiondecl (TraitFunctionDecl &e) else put_field ("where_clause", "none"); - put_field ("self", e.get_self ().as_string ()); + if (e.is_method ()) + put_field ("self", e.get_self_unchecked ().as_string ()); end ("TraitFunctionDecl"); } @@ -1283,7 +1284,9 @@ Dump::visit (BlockExpr &e) do_expr (e); do_inner_attrs (e); put_field ("tail_reachable", std::to_string (e.is_tail_reachable ())); - put_field ("label", e.get_label ().as_string ()); + + if (e.has_label ()) + put_field ("label", e.get_label ().as_string ()); visit_collection ("statements", e.get_statements ()); @@ -1294,6 +1297,31 @@ Dump::visit (BlockExpr &e) } void +Dump::visit (AnonConst &e) +{ + begin ("AnonConst"); + do_expr (e); + + if (e.is_deferred ()) + put_field ("inner", "_"); + else + visit_field ("inner", e.get_inner_expr ()); + + end ("AnonConst"); +} + +void +Dump::visit (ConstBlock &e) +{ + begin ("ConstBlock"); + do_expr (e); + + visit_field ("inner", e.get_const_expr ()); + + end ("ConstBlock"); +} + +void Dump::visit (ContinueExpr &e) { begin ("ContinueExpr"); @@ -1504,9 +1532,91 @@ Dump::visit (AsyncBlockExpr &e) void Dump::visit (InlineAsm &e) +{ + begin ("InlineAsm"); + do_expr (e); + for (auto &temp : e.get_template_ ()) + { + put_field ("template", temp.string); + } + + for (auto &temp_str : e.get_template_strs ()) + { + put_field ("template_str", temp_str.symbol); + } + + for (auto &operand : e.get_operands ()) + { + switch (operand.get_register_type ()) + { + case HIR::InlineAsmOperand::RegisterType::In: + { + const auto &in = operand.get_in (); + visit_field ("in expr", *in.expr); + break; + } + case HIR::InlineAsmOperand::RegisterType::Out: + { + const auto &out = operand.get_out (); + visit_field ("out expr", *out.expr); + break; + } + case HIR::InlineAsmOperand::RegisterType::InOut: + { + const auto &inout = operand.get_in_out (); + visit_field ("inout expr", *inout.expr); + break; + } + case HIR::InlineAsmOperand::RegisterType::SplitInOut: + { + const auto &inout = operand.get_split_in_out (); + begin ("Split in out"); + visit_field ("in expr", *inout.in_expr); + visit_field ("out expr", *inout.out_expr); + end ("Split in out"); + + break; + } + case HIR::InlineAsmOperand::RegisterType::Const: + { + auto &cnst = operand.get_const (); + visit_field ("const expr", cnst.anon_const.get_inner_expr ()); + break; + } + case HIR::InlineAsmOperand::RegisterType::Sym: + { + auto &sym = operand.get_sym (); + visit_field ("sym expr", *sym.expr); + break; + } + case HIR::InlineAsmOperand::RegisterType::Label: + { + auto &label = operand.get_label (); + put_field ("label name", label.label_name); + do_expr (*label.expr); + break; + } + } + } + end ("InlineAsm"); +} + +void +Dump::visit (LlvmInlineAsm &e) {} void +Dump::visit (OffsetOf &e) +{ + begin ("OffsetOf"); + + put_field ("type", e.get_type ().as_string ()); + put_field ("field", e.get_field ()); + + end ("OffsetOf"); +} + +void Dump::visit (TypeParam &e) { begin ("TypeParam"); @@ -1595,7 +1705,8 @@ Dump::visit (UseTreeGlob &e) case UseTreeGlob::PathType::GLOBAL: glob = "::*"; break; - case UseTreeGlob::PathType::PATH_PREFIXED: { + case UseTreeGlob::PathType::PATH_PREFIXED: + { path = e.get_path ().as_string (); glob = "::*"; break; @@ -1623,7 +1734,8 @@ Dump::visit (UseTreeList &e) case UseTreeList::PathType::GLOBAL: path_type = "::*"; break; - case UseTreeList::PathType::PATH_PREFIXED: { + case UseTreeList::PathType::PATH_PREFIXED: + { path = e.get_path ().as_string (); path_type = "::*"; break; @@ -1693,7 +1805,8 @@ Dump::visit (Function &e) put_field ("where clause", e.get_where_clause ().as_string ()); visit_field ("function_body", e.get_definition ()); - put_field ("self", e.get_self_param ().as_string ()); + if (e.is_method ()) + put_field ("self", e.get_self_param_unchecked ().as_string ()); end ("Function"); } @@ -1894,7 +2007,8 @@ Dump::visit (ConstantItem &e) do_vis_item (e); put_field ("identifier", e.get_identifier ().as_string ()); visit_field ("type", e.get_type ()); - visit_field ("const_expr", e.get_expr ()); + if (e.has_expr ()) + visit_field ("const_expr", e.get_expr ()); end ("ConstantItem"); } @@ -2083,10 +2197,10 @@ Dump::visit (IdentifierPattern &e) put_field ("is_ref", std::to_string (e.get_is_ref ())); put_field ("mut", std::to_string (e.is_mut ())); - if (e.has_pattern_to_bind ()) - put_field ("to_bind", e.get_to_bind ().as_string ()); + if (e.has_subpattern ()) + visit_field ("subpattern", e.get_subpattern ()); else - put_field ("to_bind", "none"); + put_field ("subpattern", "none"); end ("IdentifierPattern"); } @@ -2164,7 +2278,7 @@ Dump::visit (StructPatternFieldIdentPat &e) auto oa = e.get_outer_attrs (); do_outer_attrs (oa); put_field ("ident", e.get_identifier ().as_string ()); - put_field ("ident_pattern", e.get_pattern ().as_string ()); + visit_field ("ident_pattern", e.get_pattern ()); end ("StructPatternFieldIdentPat"); } @@ -2193,20 +2307,20 @@ Dump::visit (StructPattern &e) } void -Dump::visit (TupleStructItemsNoRange &e) +Dump::visit (TupleStructItemsNoRest &e) { - begin ("TupleStructItemsNoRange"); + begin ("TupleStructItemsNoRest"); visit_collection ("patterns", e.get_patterns ()); - end ("TupleStructItemsNoRange"); + end ("TupleStructItemsNoRest"); } void -Dump::visit (TupleStructItemsRange &e) +Dump::visit (TupleStructItemsHasRest &e) { - begin ("TupleStructItemsRange"); + begin ("TupleStructItemsHasRest"); visit_collection ("lower_patterns", e.get_lower_patterns ()); visit_collection ("upper_patterns", e.get_upper_patterns ()); - end ("TupleStructItemsRange"); + end ("TupleStructItemsHasRest"); } void @@ -2223,20 +2337,20 @@ Dump::visit (TupleStructPattern &e) } void -Dump::visit (TuplePatternItemsMultiple &e) +Dump::visit (TuplePatternItemsNoRest &e) { - begin ("TuplePatternItemsMultiple"); + begin ("TuplePatternItemsNoRest"); visit_collection ("patterns", e.get_patterns ()); - end ("TuplePatternItemsMultiple"); + end ("TuplePatternItemsNoRest"); } void -Dump::visit (TuplePatternItemsRanged &e) +Dump::visit (TuplePatternItemsHasRest &e) { - begin ("TuplePatternItemsRanged"); + begin ("TuplePatternItemsHasRest"); visit_collection ("lower_patterns", e.get_lower_patterns ()); visit_collection ("upper_patterns", e.get_upper_patterns ()); - end ("TuplePatternItemsRanged"); + end ("TuplePatternItemsHasRest"); } void @@ -2249,11 +2363,28 @@ Dump::visit (TuplePattern &e) } void +Dump::visit (SlicePatternItemsNoRest &e) +{ + begin ("SlicePatternItemsNoRest"); + visit_collection ("patterns", e.get_patterns ()); + end ("SlicePatternItemsNoRest"); +} + +void +Dump::visit (SlicePatternItemsHasRest &e) +{ + begin ("SlicePatternItemsHasRest"); + visit_collection ("lower_patterns", e.get_lower_patterns ()); + visit_collection ("upper_patterns", e.get_upper_patterns ()); + end ("SlicePatternItemsHasRest"); +} + +void Dump::visit (SlicePattern &e) { begin ("SlicePattern"); do_mappings (e.get_mappings ()); - visit_collection ("items", e.get_items ()); + visit_field ("items", e.get_items ()); end ("SlicePattern"); } @@ -2282,7 +2413,7 @@ Dump::visit (LetStmt &e) auto oa = e.get_outer_attrs (); do_outer_attrs (oa); - put_field ("variable_pattern", e.get_pattern ().as_string ()); + visit_field ("variable_pattern", e.get_pattern ()); if (e.has_type ()) visit_field ("type", e.get_type ()); diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h index afcd668..4dfc885 100644 --- a/gcc/rust/hir/rust-hir-dump.h +++ b/gcc/rust/hir/rust-hir-dump.h @@ -146,6 +146,8 @@ private: virtual void visit (FieldAccessExpr &) override; virtual void visit (ClosureExpr &) override; virtual void visit (BlockExpr &) override; + virtual void visit (AnonConst &) override; + virtual void visit (ConstBlock &) override; virtual void visit (ContinueExpr &) override; virtual void visit (BreakExpr &) override; virtual void visit (RangeFromToExpr &) override; @@ -166,6 +168,8 @@ private: virtual void visit (AwaitExpr &) override; virtual void visit (AsyncBlockExpr &) override; virtual void visit (InlineAsm &) override; + virtual void visit (LlvmInlineAsm &) override; + virtual void visit (OffsetOf &) override; virtual void visit (TypeParam &) override; virtual void visit (ConstGenericParam &) override; @@ -219,14 +223,18 @@ private: virtual void visit (StructPatternFieldIdent &) override; virtual void visit (StructPattern &) override; - virtual void visit (TupleStructItemsNoRange &) override; - virtual void visit (TupleStructItemsRange &) override; + virtual void visit (TupleStructItemsNoRest &) override; + virtual void visit (TupleStructItemsHasRest &) override; virtual void visit (TupleStructPattern &) override; - virtual void visit (TuplePatternItemsMultiple &) override; - virtual void visit (TuplePatternItemsRanged &) override; + virtual void visit (TuplePatternItemsNoRest &) override; + virtual void visit (TuplePatternItemsHasRest &) override; virtual void visit (TuplePattern &) override; + + virtual void visit (SlicePatternItemsNoRest &) override; + virtual void visit (SlicePatternItemsHasRest &) override; virtual void visit (SlicePattern &) override; + virtual void visit (AltPattern &) override; virtual void visit (EmptyStmt &) override; @@ -251,7 +259,6 @@ private: } // namespace Rust // In the global namespace to make it easier to call from debugger -void -debug (Rust::HIR::FullVisitable &v); +void debug (Rust::HIR::FullVisitable &v); #endif // !RUST_HIR_DUMP_H diff --git a/gcc/rust/hir/tree/rust-hir-bound.h b/gcc/rust/hir/tree/rust-hir-bound.h index 78bb133..8fa6a22 100644 --- a/gcc/rust/hir/tree/rust-hir-bound.h +++ b/gcc/rust/hir/tree/rust-hir-bound.h @@ -44,18 +44,6 @@ public: {} // Returns true if the lifetime is in an error state. - bool is_error () const - { - return lifetime_type == AST::Lifetime::LifetimeType::NAMED - && lifetime_name.empty (); - } - - static Lifetime error () - { - return Lifetime (Analysis::NodeMapping::get_error (), - AST::Lifetime::LifetimeType::NAMED, "", UNDEF_LOCATION); - } - std::string as_string () const override; void accept_vis (HIRFullVisitor &vis) override; diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h b/gcc/rust/hir/tree/rust-hir-expr-abstract.h index ecf9bd1..371daa8 100644 --- a/gcc/rust/hir/tree/rust-hir-expr-abstract.h +++ b/gcc/rust/hir/tree/rust-hir-expr-abstract.h @@ -43,7 +43,7 @@ public: WITHOUT_BLOCK, }; - enum ExprType + enum class ExprType { Lit, Operator, @@ -58,6 +58,8 @@ public: FieldAccess, Closure, Block, + AnonConst, + ConstBlock, Continue, Break, Range, @@ -71,6 +73,8 @@ public: AsyncBlock, Path, InlineAsm, + LlvmInlineAsm, + OffsetOf, }; BaseKind get_hir_kind () override final { return Node::BaseKind::EXPR; } diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc index 2ded789..14786ad 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.cc +++ b/gcc/rust/hir/tree/rust-hir-expr.cc @@ -17,6 +17,8 @@ // <http://www.gnu.org/licenses/>. #include "rust-hir-expr.h" +#include "rust-hir-map.h" +#include "optional.h" #include "rust-operators.h" #include "rust-hir-stmt.h" @@ -81,10 +83,10 @@ OperatorExpr::operator= (OperatorExpr const &other) BorrowExpr::BorrowExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> borrow_lvalue, Mutability mut, - AST::AttrVec outer_attribs, location_t locus) + bool raw, AST::AttrVec outer_attribs, location_t locus) : OperatorExpr (std::move (mappings), std::move (borrow_lvalue), std::move (outer_attribs), locus), - mut (mut) + mut (mut), raw (raw) {} DereferenceExpr::DereferenceExpr (Analysis::NodeMapping mappings, @@ -749,7 +751,7 @@ BlockExpr::BlockExpr (Analysis::NodeMapping mappings, std::vector<std::unique_ptr<Stmt>> block_statements, std::unique_ptr<Expr> block_expr, bool tail_reachable, AST::AttrVec inner_attribs, AST::AttrVec outer_attribs, - LoopLabel label, location_t start_locus, + tl::optional<LoopLabel> label, location_t start_locus, location_t end_locus) : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), WithInnerAttrs (std::move (inner_attribs)), @@ -790,14 +792,71 @@ BlockExpr::operator= (BlockExpr const &other) return *this; } +AnonConst::AnonConst (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> &&expr, location_t locus) + : ExprWithBlock (std::move (mappings), {}), locus (locus), + kind (Kind::Explicit), expr (std::move (expr)) +{ + rust_assert (this->expr.value ()); +} + +AnonConst::AnonConst (Analysis::NodeMapping mappings, location_t locus) + : ExprWithBlock (std::move (mappings), {}), locus (locus), + kind (Kind::DeferredInference), expr (tl::nullopt) +{} + +AnonConst::AnonConst (const AnonConst &other) + : ExprWithBlock (other), locus (other.locus), kind (other.kind) +{ + if (other.expr) + expr = other.expr.value ()->clone_expr (); +} + +AnonConst +AnonConst::operator= (const AnonConst &other) +{ + ExprWithBlock::operator= (other); + + locus = other.locus; + kind = other.kind; + + if (other.expr) + expr = other.expr.value ()->clone_expr (); + + return *this; +} + +ConstBlock::ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr, + location_t locus, AST::AttrVec outer_attrs) + : ExprWithBlock (std::move (mappings), std::move (outer_attrs)), + expr (std::move (expr)), locus (locus) +{} + +ConstBlock::ConstBlock (const ConstBlock &other) + : ExprWithBlock (other), expr (other.expr), locus (other.locus) +{} + +ConstBlock +ConstBlock::operator= (const ConstBlock &other) +{ + ExprWithBlock::operator= (other); + + expr = other.expr; + locus = other.locus; + + return *this; +} + ContinueExpr::ContinueExpr (Analysis::NodeMapping mappings, location_t locus, - Lifetime label, AST::AttrVec outer_attribs) + tl::optional<Lifetime> label, + AST::AttrVec outer_attribs) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), label (std::move (label)), locus (locus) {} BreakExpr::BreakExpr (Analysis::NodeMapping mappings, location_t locus, - Lifetime break_label, std::unique_ptr<Expr> expr_in_break, + tl::optional<Lifetime> break_label, + std::unique_ptr<Expr> expr_in_break, AST::AttrVec outer_attribs) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), label (std::move (break_label)), break_expr (std::move (expr_in_break)), @@ -985,7 +1044,8 @@ UnsafeBlockExpr::operator= (UnsafeBlockExpr const &other) BaseLoopExpr::BaseLoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<BlockExpr> loop_block, - location_t locus, LoopLabel loop_label, + location_t locus, + tl::optional<LoopLabel> loop_label, AST::AttrVec outer_attribs) : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), loop_label (std::move (loop_label)), loop_block (std::move (loop_block)), @@ -1011,7 +1071,8 @@ BaseLoopExpr::operator= (BaseLoopExpr const &other) LoopExpr::LoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label, AST::AttrVec outer_attribs) + tl::optional<LoopLabel> loop_label, + AST::AttrVec outer_attribs) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, std::move (loop_label), std::move (outer_attribs)) {} @@ -1019,7 +1080,8 @@ LoopExpr::LoopExpr (Analysis::NodeMapping mappings, WhileLoopExpr::WhileLoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> loop_condition, std::unique_ptr<BlockExpr> loop_block, - location_t locus, LoopLabel loop_label, + location_t locus, + tl::optional<LoopLabel> loop_label, AST::AttrVec outer_attribs) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, std::move (loop_label), std::move (outer_attribs)), @@ -1046,7 +1108,8 @@ WhileLetLoopExpr::WhileLetLoopExpr ( Analysis::NodeMapping mappings, std::vector<std::unique_ptr<Pattern>> match_arm_patterns, std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> loop_block, - location_t locus, LoopLabel loop_label, AST::AttrVec outer_attribs) + location_t locus, tl::optional<LoopLabel> loop_label, + AST::AttrVec outer_attribs) : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, std::move (loop_label), std::move (outer_attribs)), match_arm_patterns (std::move (match_arm_patterns)), @@ -1271,59 +1334,42 @@ AsyncBlockExpr::operator= (AsyncBlockExpr const &other) OperatorExprMeta::OperatorExprMeta (HIR::CompoundAssignmentExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), - locus (expr.get_locus ()) + rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), - locus (expr.get_locus ()) + rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::NegationExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), + rvalue_mappings (Analysis::NodeMapping::get_error ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::DereferenceExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), + rvalue_mappings (Analysis::NodeMapping::get_error ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::ArrayIndexExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_array_expr ().get_mappings ()), + rvalue_mappings (expr.get_index_expr ().get_mappings ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::ComparisonExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), - locus (expr.get_locus ()) + rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ()) {} -AnonConst::AnonConst (NodeId id, std::unique_ptr<Expr> expr) - : id (id), expr (std::move (expr)) -{ - rust_assert (this->expr != nullptr); -} - -AnonConst::AnonConst (const AnonConst &other) -{ - id = other.id; - expr = other.expr->clone_expr (); -} - -AnonConst -AnonConst::operator= (const AnonConst &other) -{ - id = other.id; - expr = other.expr->clone_expr (); - return *this; -} - InlineAsmOperand::In::In ( const tl::optional<struct AST::InlineAsmRegOrRegClass> ®, std::unique_ptr<Expr> expr) @@ -1470,7 +1516,7 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm, std::vector<AST::TupleTemplateStr> template_strs, std::vector<HIR::InlineAsmOperand> operands, std::vector<AST::TupleClobber> clobber_abi, - std::set<AST::InlineAsmOption> options, + std::set<AST::InlineAsm::Option> options, Analysis::NodeMapping mappings, AST::AttrVec outer_attribs) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), @@ -1480,5 +1526,41 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm, clobber_abi (std::move (clobber_abi)), options (std::move (options)) {} +OffsetOf & +OffsetOf::operator= (const OffsetOf &other) +{ + ExprWithoutBlock::operator= (other); + + type = other.type->clone_type (); + field = other.field; + loc = other.loc; + + return *this; +} + +ExprWithoutBlock * +OffsetOf::clone_expr_without_block_impl () const +{ + return new OffsetOf (*this); +} + +std::string +OffsetOf::as_string () const +{ + return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")"; +} + +void +OffsetOf::accept_vis (HIRExpressionVisitor &vis) +{ + vis.visit (*this); +} + +void +OffsetOf::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index f8f2128..61e3590 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -19,12 +19,15 @@ #ifndef RUST_HIR_EXPR_H #define RUST_HIR_EXPR_H +#include "rust-ast.h" #include "rust-hir-expr-abstract.h" #include "rust-hir-literal.h" #include "rust-common.h" #include "rust-hir-bound.h" #include "rust-hir-attrs.h" #include "rust-expr.h" +#include "rust-hir-map.h" +#include "rust-mapping-common.h" namespace Rust { namespace HIR { @@ -45,9 +48,6 @@ public: LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label, location_t locus); - // Returns whether the LoopLabel is in an error state. - bool is_error () const { return label.is_error (); } - location_t get_locus () const { return locus; } Analysis::NodeMapping &get_mappings () { return mappings; } @@ -199,12 +199,13 @@ public: class BorrowExpr : public OperatorExpr { Mutability mut; + bool raw; public: std::string as_string () const override; BorrowExpr (Analysis::NodeMapping mappings, - std::unique_ptr<Expr> borrow_lvalue, Mutability mut, + std::unique_ptr<Expr> borrow_lvalue, Mutability mut, bool raw, AST::AttrVec outer_attribs, location_t locus); void accept_vis (HIRFullVisitor &vis) override; @@ -212,6 +213,7 @@ public: Mutability get_mut () const { return mut; } bool is_mut () const { return mut == Mutability::Mut; } + bool is_raw_borrow () const { return raw; } protected: /* Use covariance to implement clone function as returning this object rather @@ -1715,7 +1717,7 @@ public: std::vector<std::unique_ptr<Stmt>> statements; std::unique_ptr<Expr> expr; bool tail_reachable; - LoopLabel label; + tl::optional<LoopLabel> label; location_t start_locus; location_t end_locus; @@ -1735,7 +1737,8 @@ public: std::vector<std::unique_ptr<Stmt>> block_statements, std::unique_ptr<Expr> block_expr, bool tail_reachable, AST::AttrVec inner_attribs, AST::AttrVec outer_attribs, - LoopLabel label, location_t start_locus, location_t end_locus); + tl::optional<LoopLabel> label, location_t start_locus, + location_t end_locus); // Copy constructor with clone BlockExpr (BlockExpr const &other); @@ -1774,8 +1777,8 @@ public: return ExprType::Block; } - bool has_label () const { return !label.is_error (); } - LoopLabel &get_label () { return label; } + bool has_label () const { return label.has_value (); } + LoopLabel &get_label () { return label.value (); } protected: /* Use covariance to implement clone function as returning this object rather @@ -1800,28 +1803,116 @@ protected: } }; +class AnonConst : public ExprWithBlock +{ +public: + enum class Kind + { + Explicit, + DeferredInference + }; + + AnonConst (Analysis::NodeMapping mappings, std::unique_ptr<Expr> &&expr, + location_t locus = UNKNOWN_LOCATION); + AnonConst (Analysis::NodeMapping mappings, + location_t locus = UNKNOWN_LOCATION); + AnonConst (const AnonConst &other); + AnonConst operator= (const AnonConst &other); + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + ExprType get_expression_type () const final override + { + return ExprType::AnonConst; + } + + location_t get_locus () const override { return locus; } + + Expr &get_inner_expr () + { + rust_assert (kind == Kind::Explicit); + return *expr.value (); + } + + const Expr &get_inner_expr () const + { + rust_assert (kind == Kind::Explicit); + return *expr.value (); + } + + bool is_deferred () const { return kind == Kind::DeferredInference; } + +private: + location_t locus; + Kind kind; + tl::optional<std::unique_ptr<Expr>> expr; + + AnonConst *clone_expr_with_block_impl () const override + { + return new AnonConst (*this); + } +}; + +class ConstBlock : public ExprWithBlock +{ +public: + ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr, + location_t locus = UNKNOWN_LOCATION, + AST::AttrVec outer_attrs = {}); + ConstBlock (const ConstBlock &other); + ConstBlock operator= (const ConstBlock &other); + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::string as_string () const override; + + ExprType get_expression_type () const final override + { + return ExprType::ConstBlock; + } + + location_t get_locus () const override { return locus; } + AnonConst &get_const_expr () { return expr; } + const AnonConst &get_const_expr () const { return expr; } + +private: + AnonConst expr; + location_t locus; + + ConstBlock *clone_expr_with_block_impl () const override + { + return new ConstBlock (*this); + } +}; + // HIR node representing continue expression within loops class ContinueExpr : public ExprWithoutBlock { - Lifetime label; + tl::optional<Lifetime> label; location_t locus; public: std::string as_string () const override; // Returns true if the continue expr has a label. - bool has_label () const { return !label.is_error (); } + bool has_label () const { return label.has_value (); } // Constructor for a ContinueExpr with a label. ContinueExpr (Analysis::NodeMapping mappings, location_t locus, - Lifetime label, AST::AttrVec outer_attribs = AST::AttrVec ()); + tl::optional<Lifetime> label, + AST::AttrVec outer_attribs = AST::AttrVec ()); location_t get_locus () const override final { return locus; } void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRExpressionVisitor &vis) override; - Lifetime &get_label () { return label; } + Lifetime &get_label () { return label.value (); } + const Lifetime &get_label () const { return label.value (); } ExprType get_expression_type () const final override { @@ -1848,7 +1939,7 @@ protected: class BreakExpr : public ExprWithoutBlock { // bool has_label; - Lifetime label; + tl::optional<Lifetime> label; // bool has_break_expr; std::unique_ptr<Expr> break_expr; @@ -1859,7 +1950,7 @@ public: std::string as_string () const override; // Returns whether the break expression has a label or not. - bool has_label () const { return !label.is_error (); } + bool has_label () const { return label.has_value (); } /* Returns whether the break expression has an expression used in the break or * not. */ @@ -1867,7 +1958,7 @@ public: // Constructor for a break expression BreakExpr (Analysis::NodeMapping mappings, location_t locus, - Lifetime break_label, + tl::optional<Lifetime> break_label, std::unique_ptr<Expr> expr_in_break = nullptr, AST::AttrVec outer_attribs = AST::AttrVec ()); @@ -1886,7 +1977,8 @@ public: void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRExpressionVisitor &vis) override; - Lifetime &get_label () { return label; } + Lifetime &get_label () { return label.value (); } + const Lifetime &get_label () const { return label.value (); } Expr &get_expr () { return *break_expr; } @@ -2293,7 +2385,7 @@ protected: class BaseLoopExpr : public ExprWithBlock { protected: - LoopLabel loop_label; + tl::optional<LoopLabel> loop_label; std::unique_ptr<BlockExpr> loop_block; private: @@ -2303,7 +2395,7 @@ protected: // Constructor for BaseLoopExpr BaseLoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label, + tl::optional<LoopLabel> loop_label, AST::AttrVec outer_attribs = AST::AttrVec ()); // Copy constructor for BaseLoopExpr with clone @@ -2322,13 +2414,14 @@ protected: } public: - bool has_loop_label () const { return !loop_label.is_error (); } + bool has_loop_label () const { return loop_label.has_value (); } location_t get_locus () const override final { return locus; } HIR::BlockExpr &get_loop_block () { return *loop_block; }; - LoopLabel &get_loop_label () { return loop_label; } + LoopLabel &get_loop_label () { return loop_label.value (); } + const LoopLabel &get_loop_label () const { return loop_label.value (); } }; // 'Loop' expression (i.e. the infinite loop) HIR node @@ -2340,7 +2433,8 @@ public: // Constructor for LoopExpr LoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label, AST::AttrVec outer_attribs = AST::AttrVec ()); + tl::optional<LoopLabel> loop_label, + AST::AttrVec outer_attribs = AST::AttrVec ()); void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRExpressionVisitor &vis) override; @@ -2370,7 +2464,7 @@ public: WhileLoopExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> loop_condition, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label, + tl::optional<LoopLabel> loop_label, AST::AttrVec outer_attribs = AST::AttrVec ()); // Copy constructor with clone @@ -2419,7 +2513,7 @@ public: std::vector<std::unique_ptr<Pattern>> match_arm_patterns, std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label, + tl::optional<LoopLabel> loop_label, AST::AttrVec outer_attribs = AST::AttrVec ()); // Copy constructor with clone @@ -2626,6 +2720,8 @@ public: Expr &get_guard_expr () { return *guard_expr; } location_t get_locus () const { return locus; } + + AST::AttrVec &get_outer_attrs () { return outer_attrs; } }; /* A "match case" - a correlated match arm and resulting expression. Not @@ -2818,6 +2914,22 @@ public: OperatorExprMeta (HIR::ComparisonExpr &expr); + OperatorExprMeta (const OperatorExprMeta &other) + : node_mappings (other.node_mappings), + lvalue_mappings (other.lvalue_mappings), + rvalue_mappings (other.rvalue_mappings), locus (other.locus) + {} + + OperatorExprMeta &operator= (const OperatorExprMeta &other) + { + node_mappings = other.node_mappings; + lvalue_mappings = other.lvalue_mappings; + rvalue_mappings = other.rvalue_mappings; + locus = other.locus; + + return *this; + } + const Analysis::NodeMapping &get_mappings () const { return node_mappings; } const Analysis::NodeMapping &get_lvalue_mappings () const @@ -2825,11 +2937,22 @@ public: return lvalue_mappings; } + const Analysis::NodeMapping &get_rvalue_mappings () const + { + return rvalue_mappings; + } + + bool has_rvalue_mappings () const + { + return rvalue_mappings.get_hirid () != UNKNOWN_HIRID; + } + location_t get_locus () const { return locus; } private: - const Analysis::NodeMapping node_mappings; - const Analysis::NodeMapping lvalue_mappings; + Analysis::NodeMapping node_mappings; + Analysis::NodeMapping lvalue_mappings; + Analysis::NodeMapping rvalue_mappings; location_t locus; }; @@ -2887,18 +3010,6 @@ class InlineAsmRegClass std::string placeholder; }; -struct AnonConst -{ - NodeId id; - std::unique_ptr<Expr> expr; - - AnonConst (NodeId id, std::unique_ptr<Expr> expr); - - AnonConst (const AnonConst &other); - - AnonConst operator= (const AnonConst &other); -}; - class InlineAsmOperand { public: @@ -2987,8 +3098,9 @@ public: Label operator= (const struct Label &other); }; -private: using RegisterType = AST::InlineAsmOperand::RegisterType; + +private: AST::InlineAsmOperand::RegisterType register_type; tl::optional<struct In> in; @@ -3032,13 +3144,24 @@ public: RegisterType get_register_type () const { return register_type; } // Potentially unsafe without get_register_type() check - struct In get_in () const { return in.value (); } - struct Out get_out () const { return out.value (); } - struct InOut get_in_out () const { return in_out.value (); } - struct SplitInOut get_split_in_out () const { return split_in_out.value (); } - struct Const get_const () const { return cnst.value (); } - struct Sym get_sym () const { return sym.value (); } - struct Label get_label () const { return label.value (); } + const struct In &get_in () const { return in.value (); } + const struct Out &get_out () const { return out.value (); } + const struct InOut &get_in_out () const { return in_out.value (); } + const struct SplitInOut &get_split_in_out () const + { + return split_in_out.value (); + } + const struct Const &get_const () const { return cnst.value (); } + const struct Sym &get_sym () const { return sym.value (); } + const struct Label &get_label () const { return label.value (); } + + struct In &get_in () { return in.value (); } + struct Out &get_out () { return out.value (); } + struct InOut &get_in_out () { return in_out.value (); } + struct SplitInOut &get_split_in_out () { return split_in_out.value (); } + struct Const &get_const () { return cnst.value (); } + struct Sym &get_sym () { return sym.value (); } + struct Label &get_label () { return label.value (); } }; // Inline Assembly Node @@ -3054,7 +3177,7 @@ public: std::vector<AST::TupleTemplateStr> template_strs; std::vector<HIR::InlineAsmOperand> operands; std::vector<AST::TupleClobber> clobber_abi; - std::set<AST::InlineAsmOption> options; + std::set<AST::InlineAsm::Option> options; std::vector<location_t> line_spans; @@ -3085,11 +3208,11 @@ public: return template_strs; } - std::vector<HIR::InlineAsmOperand> get_operands () { return operands; } + std::vector<HIR::InlineAsmOperand> &get_operands () { return operands; } std::vector<AST::TupleClobber> get_clobber_abi () { return clobber_abi; } - std::set<AST::InlineAsmOption> get_options () { return options; } + std::set<AST::InlineAsm::Option> get_options () { return options; } bool is_simple_asm () { @@ -3108,11 +3231,121 @@ public: std::vector<AST::TupleTemplateStr> template_strs, std::vector<HIR::InlineAsmOperand> operands, std::vector<AST::TupleClobber> clobber_abi, - std::set<AST::InlineAsmOption> options, + std::set<AST::InlineAsm::Option> options, Analysis::NodeMapping mappings, AST::AttrVec outer_attribs = AST::AttrVec ()); }; +class OffsetOf : public ExprWithoutBlock +{ +public: + OffsetOf (std::unique_ptr<Type> &&type, Identifier field, + Analysis::NodeMapping mappings, location_t loc) + : ExprWithoutBlock (mappings), type (std::move (type)), field (field), + loc (loc) + {} + + OffsetOf (const OffsetOf &other) + : ExprWithoutBlock (other), type (other.type->clone_type ()), + field (other.field), loc (other.loc) + {} + + OffsetOf &operator= (const OffsetOf &other); + + ExprWithoutBlock *clone_expr_without_block_impl () const override; + std::string as_string () const override; + + void accept_vis (HIRExpressionVisitor &vis) override; + void accept_vis (HIRFullVisitor &vis) override; + + ExprType get_expression_type () const override { return ExprType::OffsetOf; } + + location_t get_locus () const override { return loc; } + + Type &get_type () { return *type; } + const Type &get_type () const { return *type; } + const Identifier &get_field () const { return field; } + +private: + std::unique_ptr<Type> type; + Identifier field; + location_t loc; +}; + +struct LlvmOperand +{ + std::string constraint; + std::unique_ptr<Expr> expr; + + LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr) + : constraint (constraint), expr (std::move (expr)) + {} + + LlvmOperand (const LlvmOperand &other) + : constraint (other.constraint), expr (other.expr->clone_expr ()) + {} + LlvmOperand &operator= (const LlvmOperand &other) + { + constraint = other.constraint; + expr = other.expr->clone_expr (); + + return *this; + } +}; + +class LlvmInlineAsm : public ExprWithoutBlock +{ +public: + struct Options + { + bool is_volatile; + bool align_stack; + AST::LlvmInlineAsm::Dialect dialect; + }; + + location_t locus; + AST::AttrVec outer_attrs; + std::vector<LlvmOperand> inputs; + std::vector<LlvmOperand> outputs; + std::vector<AST::TupleTemplateStr> templates; + std::vector<AST::TupleClobber> clobbers; + Options options; + + LlvmInlineAsm (location_t locus, std::vector<LlvmOperand> inputs, + std::vector<LlvmOperand> outputs, + std::vector<AST::TupleTemplateStr> templates, + std::vector<AST::TupleClobber> clobbers, Options options, + AST::AttrVec outer_attrs, Analysis::NodeMapping mappings) + : ExprWithoutBlock (mappings, std::move (outer_attrs)), locus (locus), + inputs (std::move (inputs)), outputs (std::move (outputs)), + templates (std::move (templates)), clobbers (std::move (clobbers)), + options (options) + {} + + AST::LlvmInlineAsm::Dialect get_dialect () { return options.dialect; } + + location_t get_locus () const override { return locus; } + + std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; } + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + LlvmInlineAsm *clone_expr_without_block_impl () const override + { + return new LlvmInlineAsm (*this); + } + + std::vector<AST::TupleTemplateStr> &get_templates () { return templates; } + + Expr::ExprType get_expression_type () const override + { + return Expr::ExprType::LlvmInlineAsm; + } + + std::vector<AST::TupleClobber> get_clobbers () { return clobbers; } +}; + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h index 6c19f24..aec2f36 100644 --- a/gcc/rust/hir/tree/rust-hir-full-decls.h +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -95,6 +95,8 @@ class FieldAccessExpr; struct ClosureParam; class ClosureExpr; class BlockExpr; +class AnonConst; +class ConstBlock; class ContinueExpr; class BreakExpr; class RangeExpr; @@ -123,9 +125,10 @@ class AwaitExpr; class AsyncBlockExpr; class InlineAsmReg; class InlineAsmRegClass; -struct AnonConst; class InlineAsmOperand; class InlineAsm; +class LlvmInlineAsm; +class OffsetOf; // rust-stmt.h class EmptyStmt; @@ -196,13 +199,15 @@ class StructPatternFieldIdentPat; class StructPatternFieldIdent; class StructPattern; class TupleStructItems; -class TupleStructItemsNoRange; -class TupleStructItemsRange; +class TupleStructItemsNoRest; +class TupleStructItemsHasRest; class TupleStructPattern; class TuplePatternItems; -class TuplePatternItemsMultiple; -class TuplePatternItemsRanged; +class TuplePatternItemsNoRest; +class TuplePatternItemsHasRest; class TuplePattern; +class SlicePatternItemsNoRest; +class SlicePatternItemsHasRest; class SlicePattern; class AltPattern; diff --git a/gcc/rust/hir/tree/rust-hir-generic-param.h b/gcc/rust/hir/tree/rust-hir-generic-param.h index a1c59bf..340b5c6 100644 --- a/gcc/rust/hir/tree/rust-hir-generic-param.h +++ b/gcc/rust/hir/tree/rust-hir-generic-param.h @@ -97,9 +97,6 @@ public: AST::AttrVec &get_outer_attrs () override { return outer_attrs; } - // Returns whether the lifetime param is in an error state. - bool is_error () const { return lifetime.is_error (); } - // Constructor LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime, location_t locus = UNDEF_LOCATION, @@ -153,7 +150,7 @@ public: location_t get_locus () const override final { return locus; }; - bool has_default_expression () { return default_expression != nullptr; } + bool has_default_expression () const { return default_expression != nullptr; } std::string get_name () { return name; } Type &get_type () @@ -163,6 +160,8 @@ public: } Expr &get_default_expression () { return *default_expression; } + const Expr &get_default_expression () const { return *default_expression; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc index cff06d3..268b09b 100644 --- a/gcc/rust/hir/tree/rust-hir-item.cc +++ b/gcc/rust/hir/tree/rust-hir-item.cc @@ -26,16 +26,18 @@ TypeParam::TypeParam ( Analysis::NodeMapping mappings, Identifier type_representation, location_t locus, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds, - tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs) + tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs, + bool was_impl_trait) : GenericParam (mappings), outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), type (std::move (type)), - locus (locus) + locus (locus), was_impl_trait (was_impl_trait) {} TypeParam::TypeParam (TypeParam const &other) : GenericParam (other.mappings), outer_attrs (other.outer_attrs), - type_representation (other.type_representation), locus (other.locus) + type_representation (other.type_representation), locus (other.locus), + was_impl_trait (other.was_impl_trait) { // guard to prevent null pointer dereference if (other.has_type ()) @@ -55,6 +57,7 @@ TypeParam::operator= (TypeParam const &other) outer_attrs = other.outer_attrs; locus = other.locus; mappings = other.mappings; + was_impl_trait = other.was_impl_trait; // guard to prevent null pointer dereference if (other.has_type ()) @@ -123,7 +126,8 @@ TypeBoundWhereClauseItem::get_type_param_bounds () } SelfParam::SelfParam (Analysis::NodeMapping mappings, - ImplicitSelfKind self_kind, Lifetime lifetime, Type *type) + ImplicitSelfKind self_kind, + tl::optional<Lifetime> lifetime, Type *type) : self_kind (self_kind), lifetime (std::move (lifetime)), type (type), mappings (mappings) {} @@ -131,13 +135,13 @@ SelfParam::SelfParam (Analysis::NodeMapping mappings, SelfParam::SelfParam (Analysis::NodeMapping mappings, std::unique_ptr<Type> type, bool is_mut, location_t locus) : self_kind (is_mut ? ImplicitSelfKind::MUT : ImplicitSelfKind::IMM), - lifetime ( - Lifetime (mappings, AST::Lifetime::LifetimeType::NAMED, "", locus)), - type (std::move (type)), locus (locus), mappings (mappings) + lifetime (tl::nullopt), type (std::move (type)), locus (locus), + mappings (mappings) {} -SelfParam::SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, - bool is_mut, location_t locus) +SelfParam::SelfParam (Analysis::NodeMapping mappings, + tl::optional<Lifetime> lifetime, bool is_mut, + location_t locus) : self_kind (is_mut ? ImplicitSelfKind::MUT_REF : ImplicitSelfKind::IMM_REF), lifetime (std::move (lifetime)), locus (locus), mappings (mappings) {} @@ -263,7 +267,8 @@ Function::Function (Analysis::NodeMapping mappings, Identifier function_name, std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type, WhereClause where_clause, std::unique_ptr<BlockExpr> function_body, Visibility vis, - AST::AttrVec outer_attrs, SelfParam self, location_t locus) + AST::AttrVec outer_attrs, tl::optional<SelfParam> self, + Defaultness defaultness, location_t locus) : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), qualifiers (std::move (qualifiers)), function_name (std::move (function_name)), @@ -272,7 +277,7 @@ Function::Function (Analysis::NodeMapping mappings, Identifier function_name, return_type (std::move (return_type)), where_clause (std::move (where_clause)), function_body (std::move (function_body)), self (std::move (self)), - locus (locus) + locus (locus), defaultness (defaultness) {} Function::Function (Function const &other) @@ -280,7 +285,7 @@ Function::Function (Function const &other) function_name (other.function_name), function_params (other.function_params), where_clause (other.where_clause), function_body (other.function_body->clone_block_expr ()), self (other.self), - locus (other.locus) + locus (other.locus), defaultness (other.defaultness) { // guard to prevent null dereference (always required) if (other.return_type != nullptr) @@ -312,6 +317,8 @@ Function::operator= (Function const &other) locus = other.locus; self = other.self; + defaultness = other.defaultness; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -609,9 +616,9 @@ StaticItem::operator= (StaticItem const &other) TraitFunctionDecl::TraitFunctionDecl ( Identifier function_name, FunctionQualifiers qualifiers, - std::vector<std::unique_ptr<GenericParam>> generic_params, SelfParam self, - std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type, - WhereClause where_clause) + std::vector<std::unique_ptr<GenericParam>> generic_params, + tl::optional<SelfParam> self, std::vector<FunctionParam> function_params, + std::unique_ptr<Type> return_type, WhereClause where_clause) : qualifiers (std::move (qualifiers)), function_name (std::move (function_name)), generic_params (std::move (generic_params)), @@ -709,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 ()); @@ -734,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 4744717..7629406 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -95,17 +95,11 @@ protected: class TypeParam : public GenericParam { AST::AttrVec outer_attrs; - Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound>> - type_param_bounds; // inlined form - + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; tl::optional<std::unique_ptr<Type>> type; - location_t locus; + bool was_impl_trait; public: // Returns whether the type of the type param has been specified. @@ -121,9 +115,9 @@ public: TypeParam (Analysis::NodeMapping mappings, Identifier type_representation, location_t locus = UNDEF_LOCATION, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds - = std::vector<std::unique_ptr<TypeParamBound>> (), + = {}, tl::optional<std::unique_ptr<Type>> type = tl::nullopt, - AST::AttrVec outer_attrs = std::vector<AST::Attribute> ()); + AST::AttrVec outer_attrs = {}, bool was_impl_trait = false); // Copy constructor uses clone TypeParam (TypeParam const &other); @@ -154,6 +148,8 @@ public: std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds (); + bool from_impl_trait () const { return was_impl_trait; } + protected: // Clone function implementation as (not pure) virtual method TypeParam *clone_generic_param_impl () const override @@ -213,6 +209,8 @@ public: std::string as_string () const override; + location_t get_locus () const { return locus; } + void accept_vis (HIRFullVisitor &vis) override; Lifetime &get_lifetime () { return lifetime; } @@ -371,13 +369,13 @@ public: private: ImplicitSelfKind self_kind; - Lifetime lifetime; + tl::optional<Lifetime> lifetime; std::unique_ptr<Type> type; location_t locus; Analysis::NodeMapping mappings; SelfParam (Analysis::NodeMapping mappings, ImplicitSelfKind self_kind, - Lifetime lifetime, Type *type); + tl::optional<Lifetime> lifetime, Type *type); public: // Type-based self parameter (not ref, no lifetime) @@ -385,8 +383,8 @@ public: bool is_mut, location_t locus); // Lifetime-based self parameter (is ref, no type) - SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool is_mut, - location_t locus); + SelfParam (Analysis::NodeMapping mappings, tl::optional<Lifetime> lifetime, + bool is_mut, location_t locus); // Copy constructor requires clone SelfParam (SelfParam const &other); @@ -398,22 +396,15 @@ public: SelfParam (SelfParam &&other) = default; SelfParam &operator= (SelfParam &&other) = default; - static SelfParam error () - { - return SelfParam (Analysis::NodeMapping::get_error (), - ImplicitSelfKind::NONE, Lifetime::error (), nullptr); - } - // Returns whether the self-param has a type field. bool has_type () const { return type != nullptr; } // Returns whether the self-param has a valid lifetime. - bool has_lifetime () const { return !lifetime.is_error (); } + bool has_lifetime () const { return lifetime.has_value (); } - const Lifetime &get_lifetime () const { return lifetime; } + const Lifetime &get_lifetime () const { return lifetime.value (); } - // Returns whether the self-param is in an error state. - bool is_error () const { return self_kind == ImplicitSelfKind::NONE; } + Lifetime &get_lifetime () { return lifetime.value (); } std::string as_string () const; @@ -461,6 +452,7 @@ public: bool is_unsafe () const { return unsafety == Unsafety::Unsafe; } bool is_async () const { return async_status == Async::Yes; } + Unsafety get_unsafety () const { return unsafety; } ABI get_abi () const { return abi; } }; @@ -945,6 +937,12 @@ protected: class LetStmt; +enum class Defaultness +{ + Default, + Final, +}; + // Rust function declaration HIR node class Function : public VisItem, public ImplItem { @@ -955,9 +953,14 @@ class Function : public VisItem, public ImplItem std::unique_ptr<Type> return_type; WhereClause where_clause; std::unique_ptr<BlockExpr> function_body; - SelfParam self; + tl::optional<SelfParam> self; location_t locus; + // NOTE: This should be moved to the trait item base class once we start + // implementing specialization for real, instead of just stubbing out the + // feature + Defaultness defaultness; + public: std::string as_string () const override; @@ -973,6 +976,9 @@ public: // Returns whether function has a where clause. bool has_where_clause () const { return !where_clause.is_empty (); } + // Returns whether function has a default qualifier + bool is_default () const { return defaultness == Defaultness::Default; } + ImplItemType get_impl_item_type () const override final { return ImplItem::ImplItemType::FUNCTION; @@ -987,7 +993,8 @@ public: std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type, WhereClause where_clause, std::unique_ptr<BlockExpr> function_body, Visibility vis, - AST::AttrVec outer_attrs, SelfParam self, location_t locus); + AST::AttrVec outer_attrs, tl::optional<SelfParam> self, + Defaultness defaultness, location_t locus); // Copy constructor with clone Function (Function const &other); @@ -1041,9 +1048,13 @@ public: // TODO: is this better? Or is a "vis_block" better? Type &get_return_type () { return *return_type; } - bool is_method () const { return !self.is_error (); } + bool is_method () const { return self.has_value (); } + + tl::optional<SelfParam> &get_self_param () { return self; } + const tl::optional<SelfParam> &get_self_param () const { return self; } - SelfParam &get_self_param () { return self; } + SelfParam &get_self_param_unchecked () { return self.value (); } + const SelfParam &get_self_param_unchecked () const { return self.value (); } std::string get_impl_item_name () const override final { @@ -1791,6 +1802,8 @@ public: return *type; } + bool has_expr () const { return const_expr != nullptr; } + Expr &get_expr () { return *const_expr; } Identifier get_identifier () const { return identifier; } @@ -1898,13 +1911,14 @@ private: std::vector<FunctionParam> function_params; std::unique_ptr<Type> return_type; WhereClause where_clause; - SelfParam self; + tl::optional<SelfParam> self; public: // Mega-constructor TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers, std::vector<std::unique_ptr<GenericParam>> generic_params, - SelfParam self, std::vector<FunctionParam> function_params, + tl::optional<SelfParam> self, + std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type, WhereClause where_clause); @@ -1936,9 +1950,13 @@ public: WhereClause &get_where_clause () { return where_clause; } - bool is_method () const { return !self.is_error (); } + bool is_method () const { return self.has_value (); } + + SelfParam &get_self_unchecked () { return self.value (); } + const SelfParam &get_self_unchecked () const { return self.value (); } - SelfParam &get_self () { return self; } + tl::optional<SelfParam> &get_self () { return self; } + const tl::optional<SelfParam> &get_self () const { return self; } Identifier get_function_name () const { return function_name; } @@ -2055,6 +2073,8 @@ public: Identifier get_name () const { return name; } + bool has_type () const { return expr != nullptr; } + bool has_expr () const { return expr != nullptr; } Type &get_type () @@ -2101,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); @@ -2132,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-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 3ce2662..4f296d8 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -41,11 +41,15 @@ public: : segment_name (std::move (segment_name)) {} - /* TODO: insert check in constructor for this? Or is this a semantic error - * best handled then? */ + PathIdentSegment (const PathIdentSegment &other) + : segment_name (other.segment_name) + {} - /* TODO: does this require visitor? pretty sure this isn't polymorphic, but - * not entirely sure */ + PathIdentSegment &operator= (PathIdentSegment const &other) + { + segment_name = other.segment_name; + return *this; + } // Creates an error PathIdentSegment. static PathIdentSegment create_error () { return PathIdentSegment (""); } @@ -128,6 +132,8 @@ public: std::unique_ptr<Expr> &get_expression () { return expression; } + location_t get_locus () const { return locus; } + private: std::unique_ptr<Expr> expression; location_t locus; @@ -146,7 +152,7 @@ public: bool has_generic_args () const { return !(lifetime_args.empty () && type_args.empty () - && binding_args.empty ()); + && binding_args.empty () && const_args.empty ()); } GenericArgs (std::vector<Lifetime> lifetime_args, diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 5cc5c95..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 */ @@ -80,7 +90,7 @@ class IdentifierPattern : public Pattern Identifier variable_ident; bool is_ref; Mutability mut; - std::unique_ptr<Pattern> to_bind; + std::unique_ptr<Pattern> subpattern; location_t locus; Analysis::NodeMapping mappings; @@ -88,15 +98,15 @@ public: std::string as_string () const override; // Returns whether the IdentifierPattern has a pattern to bind. - bool has_pattern_to_bind () const { return to_bind != nullptr; } + bool has_subpattern () const { return subpattern != nullptr; } // Constructor IdentifierPattern (Analysis::NodeMapping mappings, Identifier ident, location_t locus, bool is_ref = false, Mutability mut = Mutability::Imm, - std::unique_ptr<Pattern> to_bind = nullptr) + std::unique_ptr<Pattern> subpattern = nullptr) : variable_ident (std::move (ident)), is_ref (is_ref), mut (mut), - to_bind (std::move (to_bind)), locus (locus), mappings (mappings) + subpattern (std::move (subpattern)), locus (locus), mappings (mappings) {} // Copy constructor with clone @@ -105,8 +115,8 @@ public: mut (other.mut), locus (other.locus), mappings (other.mappings) { // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); } // Overload assignment operator to use clone @@ -119,8 +129,8 @@ public: mappings = other.mappings; // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); return *this; } @@ -133,7 +143,7 @@ public: bool is_mut () const { return mut == Mutability::Mut; } bool get_is_ref () const { return is_ref; } - Pattern &get_to_bind () { return *to_bind; } + Pattern &get_subpattern () { return *subpattern; } void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRPatternVisitor &vis) override; @@ -350,6 +360,7 @@ class RangePattern : public Pattern /* location only stored to avoid a dereference - lower pattern should give * correct location so maybe change in future */ location_t locus; + bool is_inclusive; Analysis::NodeMapping mappings; public: @@ -359,10 +370,10 @@ public: RangePattern (Analysis::NodeMapping mappings, std::unique_ptr<RangePatternBound> lower, std::unique_ptr<RangePatternBound> upper, location_t locus, - bool has_ellipsis_syntax = false) + bool is_inclusive, bool has_ellipsis_syntax = false) : lower (std::move (lower)), upper (std::move (upper)), has_ellipsis_syntax (has_ellipsis_syntax), locus (locus), - mappings (mappings) + is_inclusive (is_inclusive), mappings (mappings) {} // Copy constructor with clone @@ -370,7 +381,7 @@ public: : lower (other.lower->clone_range_pattern_bound ()), upper (other.upper->clone_range_pattern_bound ()), has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus), - mappings (other.mappings) + is_inclusive (other.is_inclusive), mappings (other.mappings) {} // Overloaded assignment operator to clone @@ -380,6 +391,7 @@ public: upper = other.upper->clone_range_pattern_bound (); has_ellipsis_syntax = other.has_ellipsis_syntax; locus = other.locus; + is_inclusive = other.is_inclusive; mappings = other.mappings; return *this; @@ -395,6 +407,7 @@ public: void accept_vis (HIRPatternVisitor &vis) override; bool get_has_ellipsis_syntax () { return has_ellipsis_syntax; }; + bool is_inclusive_range () const { return is_inclusive; } const Analysis::NodeMapping &get_mappings () const override final { @@ -680,6 +693,7 @@ protected: class StructPatternElements { std::vector<std::unique_ptr<StructPatternField>> fields; + bool has_rest_pattern; public: // Returns whether there are any struct pattern fields @@ -689,10 +703,18 @@ public: * no etc). */ bool is_empty () const { return !has_struct_pattern_fields (); } + bool has_rest () const { return has_rest_pattern; } + // Constructor for StructPatternElements with both (potentially) StructPatternElements ( std::vector<std::unique_ptr<StructPatternField>> fields) - : fields (std::move (fields)) + : fields (std::move (fields)), has_rest_pattern (false) + {} + + StructPatternElements ( + std::vector<std::unique_ptr<StructPatternField>> fields, + bool has_rest_pattern) + : fields (std::move (fields)), has_rest_pattern (has_rest_pattern) {} // Copy constructor with vector clone @@ -700,7 +722,8 @@ public: { fields.reserve (other.fields.size ()); for (const auto &e : other.fields) - fields.push_back (e->clone_struct_pattern_field ()); + fields.emplace_back (e->clone_struct_pattern_field ()); + has_rest_pattern = other.has_rest_pattern; } // Overloaded assignment operator with vector clone @@ -709,8 +732,8 @@ public: fields.clear (); fields.reserve (other.fields.size ()); for (const auto &e : other.fields) - fields.push_back (e->clone_struct_pattern_field ()); - + fields.emplace_back (e->clone_struct_pattern_field ()); + has_rest_pattern = other.has_rest_pattern; return *this; } @@ -778,24 +801,25 @@ protected: } }; -// Base abstract class for TupleStructItems and TuplePatternItems -class TupleItems : public FullVisitable +// Base abstract class for TupleStructItems, TuplePatternItems & +// SlicePatternItems +class PatternItems : public FullVisitable { public: enum ItemType { - MULTIPLE, - RANGED, + NO_REST, + HAS_REST, }; - virtual ~TupleItems () {} + virtual ~PatternItems () {} // TODO: should this store location data? // Unique pointer custom clone function - std::unique_ptr<TupleItems> clone_tuple_items () const + std::unique_ptr<PatternItems> clone_pattern_items () const { - return std::unique_ptr<TupleItems> (clone_tuple_items_impl ()); + return std::unique_ptr<PatternItems> (clone_pattern_items_impl ()); } virtual ItemType get_item_type () const = 0; @@ -804,36 +828,36 @@ public: protected: // pure virtual clone implementation - virtual TupleItems *clone_tuple_items_impl () const = 0; + virtual PatternItems *clone_pattern_items_impl () const = 0; }; // Base abstract class for patterns used in TupleStructPattern -class TupleStructItems : public TupleItems +class TupleStructItems : public PatternItems { public: // Unique pointer custom clone function std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const { - return std::unique_ptr<TupleStructItems> (clone_tuple_items_impl ()); + return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ()); } protected: // pure virtual clone implementation - virtual TupleStructItems *clone_tuple_items_impl () const override = 0; + virtual TupleStructItems *clone_pattern_items_impl () const override = 0; }; -// Class for non-ranged tuple struct pattern patterns -class TupleStructItemsNoRange : public TupleStructItems +// Class for patterns within a tuple struct pattern, without a rest pattern +class TupleStructItemsNoRest : public TupleStructItems { std::vector<std::unique_ptr<Pattern>> patterns; public: - TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns) + TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) : patterns (std::move (patterns)) {} // Copy constructor with vector clone - TupleStructItemsNoRange (TupleStructItemsNoRange const &other) + TupleStructItemsNoRest (TupleStructItemsNoRest const &other) { patterns.reserve (other.patterns.size ()); for (const auto &e : other.patterns) @@ -841,7 +865,7 @@ public: } // Overloaded assignment operator with vector clone - TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other) + TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other) { patterns.clear (); patterns.reserve (other.patterns.size ()); @@ -852,9 +876,8 @@ public: } // move constructors - TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default; - TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other) - = default; + TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default; + TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default; std::string as_string () const override; @@ -866,32 +889,33 @@ public: return patterns; } - ItemType get_item_type () const override final { return ItemType::MULTIPLE; } + ItemType get_item_type () const override final { return ItemType::NO_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleStructItemsNoRange *clone_tuple_items_impl () const override + TupleStructItemsNoRest *clone_pattern_items_impl () const override { - return new TupleStructItemsNoRange (*this); + return new TupleStructItemsNoRest (*this); } }; -// Class for ranged tuple struct pattern patterns -class TupleStructItemsRange : public TupleStructItems +// Class for patterns within a tuple struct pattern, with a rest pattern +// included +class TupleStructItemsHasRest : public TupleStructItems { std::vector<std::unique_ptr<Pattern>> lower_patterns; std::vector<std::unique_ptr<Pattern>> upper_patterns; public: - TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) + TupleStructItemsHasRest (std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} // Copy constructor with vector clone - TupleStructItemsRange (TupleStructItemsRange const &other) + TupleStructItemsHasRest (TupleStructItemsHasRest const &other) { lower_patterns.reserve (other.lower_patterns.size ()); for (const auto &e : other.lower_patterns) @@ -903,7 +927,7 @@ public: } // Overloaded assignment operator to clone - TupleStructItemsRange &operator= (TupleStructItemsRange const &other) + TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other) { lower_patterns.clear (); lower_patterns.reserve (other.lower_patterns.size ()); @@ -919,8 +943,9 @@ public: } // move constructors - TupleStructItemsRange (TupleStructItemsRange &&other) = default; - TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default; + TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default; + TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other) + = default; std::string as_string () const override; @@ -945,14 +970,14 @@ public: return upper_patterns; } - ItemType get_item_type () const override final { return ItemType::RANGED; } + ItemType get_item_type () const override final { return ItemType::HAS_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleStructItemsRange *clone_tuple_items_impl () const override + TupleStructItemsHasRest *clone_pattern_items_impl () const override { - return new TupleStructItemsRange (*this); + return new TupleStructItemsHasRest (*this); } }; @@ -1025,32 +1050,32 @@ protected: }; // Base abstract class representing TuplePattern patterns -class TuplePatternItems : public TupleItems +class TuplePatternItems : public PatternItems { public: // Unique pointer custom clone function std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const { - return std::unique_ptr<TuplePatternItems> (clone_tuple_items_impl ()); + return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ()); } protected: // pure virtual clone implementation - virtual TuplePatternItems *clone_tuple_items_impl () const override = 0; + virtual TuplePatternItems *clone_pattern_items_impl () const override = 0; }; -// Class representing TuplePattern patterns where there are multiple patterns -class TuplePatternItemsMultiple : public TuplePatternItems +// Class representing patterns within a TuplePattern, without a rest pattern +class TuplePatternItemsNoRest : public TuplePatternItems { std::vector<std::unique_ptr<Pattern>> patterns; public: - TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns) + TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) : patterns (std::move (patterns)) {} // Copy constructor with vector clone - TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other) + TuplePatternItemsNoRest (TuplePatternItemsNoRest const &other) { patterns.reserve (other.patterns.size ()); for (const auto &e : other.patterns) @@ -1058,7 +1083,7 @@ public: } // Overloaded assignment operator to vector clone - TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other) + TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other) { patterns.clear (); patterns.reserve (other.patterns.size ()); @@ -1069,15 +1094,15 @@ public: } // move constructors - TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default; - TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other) + TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default; + TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other) = default; std::string as_string () const override; void accept_vis (HIRFullVisitor &vis) override; - ItemType get_item_type () const override { return ItemType::MULTIPLE; } + ItemType get_item_type () const override { return ItemType::NO_REST; } std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; } const std::vector<std::unique_ptr<Pattern>> &get_patterns () const @@ -1088,27 +1113,29 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TuplePatternItemsMultiple *clone_tuple_items_impl () const override + TuplePatternItemsNoRest *clone_pattern_items_impl () const override { - return new TuplePatternItemsMultiple (*this); + return new TuplePatternItemsNoRest (*this); } }; -// Class representing TuplePattern patterns where there are a range of patterns -class TuplePatternItemsRanged : public TuplePatternItems +// Class representing patterns within a TuplePattern, with a rest pattern +// included +class TuplePatternItemsHasRest : public TuplePatternItems { std::vector<std::unique_ptr<Pattern>> lower_patterns; std::vector<std::unique_ptr<Pattern>> upper_patterns; public: - TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) + TuplePatternItemsHasRest ( + std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} // Copy constructor with vector clone - TuplePatternItemsRanged (TuplePatternItemsRanged const &other) + TuplePatternItemsHasRest (TuplePatternItemsHasRest const &other) { lower_patterns.reserve (other.lower_patterns.size ()); for (const auto &e : other.lower_patterns) @@ -1120,7 +1147,7 @@ public: } // Overloaded assignment operator to clone - TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other) + TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other) { lower_patterns.clear (); lower_patterns.reserve (other.lower_patterns.size ()); @@ -1136,15 +1163,15 @@ public: } // move constructors - TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default; - TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other) + TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default; + TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other) = default; std::string as_string () const override; void accept_vis (HIRFullVisitor &vis) override; - ItemType get_item_type () const override { return ItemType::RANGED; } + ItemType get_item_type () const override { return ItemType::HAS_REST; } std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () { @@ -1167,9 +1194,9 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TuplePatternItemsRanged *clone_tuple_items_impl () const override + TuplePatternItemsHasRest *clone_pattern_items_impl () const override { - return new TuplePatternItemsRanged (*this); + return new TuplePatternItemsHasRest (*this); } }; @@ -1234,10 +1261,161 @@ protected: } }; +// Base abstract class representing SlicePattern patterns +class SlicePatternItems : public PatternItems +{ +public: + // Unique pointer custom clone function + std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const + { + return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ()); + } + +protected: + // pure virtual clone implementation + virtual SlicePatternItems *clone_pattern_items_impl () const override = 0; +}; + +// Class representing patterns within a SlicePattern, without a rest pattern +class SlicePatternItemsNoRest : public SlicePatternItems +{ + std::vector<std::unique_ptr<Pattern>> patterns; + +public: + SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other) + { + patterns.clear (); + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default; + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + ItemType get_item_type () const override { return ItemType::NO_REST; } + + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; } + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const + { + return patterns; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsNoRest *clone_pattern_items_impl () const override + { + return new SlicePatternItemsNoRest (*this); + } +}; + +// Class representing patterns within a SlicePattern, with a rest pattern +// included +class SlicePatternItemsHasRest : public SlicePatternItems +{ + std::vector<std::unique_ptr<Pattern>> lower_patterns; + std::vector<std::unique_ptr<Pattern>> upper_patterns; + +public: + SlicePatternItemsHasRest ( + std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other) + { + lower_patterns.clear (); + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + lower_patterns.clear (); + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default; + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + ItemType get_item_type () const override { return ItemType::HAS_REST; } + + std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () + { + return lower_patterns; + } + const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const + { + return lower_patterns; + } + + std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () + { + return upper_patterns; + } + const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const + { + return upper_patterns; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsHasRest *clone_pattern_items_impl () const override + { + return new SlicePatternItemsHasRest (*this); + } +}; + // HIR node representing patterns that can match slices and arrays class SlicePattern : public Pattern { - std::vector<std::unique_ptr<Pattern>> items; + std::unique_ptr<SlicePatternItems> items; location_t locus; Analysis::NodeMapping mappings; @@ -1245,30 +1423,23 @@ public: std::string as_string () const override; SlicePattern (Analysis::NodeMapping mappings, - std::vector<std::unique_ptr<Pattern>> items, location_t locus) + std::unique_ptr<SlicePatternItems> items, location_t locus) : items (std::move (items)), locus (locus), mappings (mappings) {} - // Copy constructor with vector clone + // Copy constructor requires clone SlicePattern (SlicePattern const &other) - : locus (other.locus), mappings (other.mappings) - { - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); - } + : items (other.items->clone_slice_pattern_items ()), locus (other.locus), + mappings (other.mappings) + {} // Overloaded assignment operator to vector clone SlicePattern &operator= (SlicePattern const &other) { + items = other.items->clone_slice_pattern_items (); locus = other.locus; mappings = other.mappings; - items.clear (); - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); - return *this; } @@ -1276,11 +1447,8 @@ public: SlicePattern (SlicePattern &&other) = default; SlicePattern &operator= (SlicePattern &&other) = default; - std::vector<std::unique_ptr<Pattern>> &get_items () { return items; } - const std::vector<std::unique_ptr<Pattern>> &get_items () const - { - return items; - } + SlicePatternItems &get_items () { return *items; } + const SlicePatternItems &get_items () const { return *items; } location_t get_locus () const override { return locus; } diff --git a/gcc/rust/hir/tree/rust-hir-type.cc b/gcc/rust/hir/tree/rust-hir-type.cc index 6a6c319..ec48425 100644 --- a/gcc/rust/hir/tree/rust-hir-type.cc +++ b/gcc/rust/hir/tree/rust-hir-type.cc @@ -162,7 +162,7 @@ RawPointerType::operator= (RawPointerType const &other) ReferenceType::ReferenceType (Analysis::NodeMapping mappings, Mutability mut, std::unique_ptr<Type> type_no_bounds, - location_t locus, Lifetime lifetime) + location_t locus, tl::optional<Lifetime> lifetime) : TypeNoBounds (mappings, locus), lifetime (std::move (lifetime)), mut (mut), type (std::move (type_no_bounds)) {} diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index bd0f2b6..cbc20ff 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -291,7 +291,7 @@ protected: class ReferenceType : public TypeNoBounds { // bool has_lifetime; // TODO: handle in lifetime or something? - Lifetime lifetime; + tl::optional<Lifetime> lifetime; Mutability mut; std::unique_ptr<Type> type; @@ -301,12 +301,12 @@ public: bool is_mut () const { return mut == Mutability::Mut; } // Returns whether the reference has a lifetime. - bool has_lifetime () const { return !lifetime.is_error (); } + bool has_lifetime () const { return lifetime.has_value (); } // Constructor ReferenceType (Analysis::NodeMapping mappings, Mutability mut, std::unique_ptr<Type> type_no_bounds, location_t locus, - Lifetime lifetime); + tl::optional<Lifetime> lifetime); // Copy constructor with custom clone method ReferenceType (ReferenceType const &other); @@ -323,7 +323,8 @@ public: void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRTypeVisitor &vis) override; - Lifetime &get_lifetime () { return lifetime; } + Lifetime &get_lifetime () { return lifetime.value (); } + const Lifetime &get_lifetime () const { return lifetime.value (); } Mutability get_mut () const { return mut; } diff --git a/gcc/rust/hir/tree/rust-hir-visibility.h b/gcc/rust/hir/tree/rust-hir-visibility.h index a750d88..9dd6ff2 100644 --- a/gcc/rust/hir/tree/rust-hir-visibility.h +++ b/gcc/rust/hir/tree/rust-hir-visibility.h @@ -73,6 +73,8 @@ public: } std::string as_string () const; + + location_t get_locus () const { return locus; } }; } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc b/gcc/rust/hir/tree/rust-hir-visitor.cc new file mode 100644 index 0000000..1e201a5 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-visitor.cc @@ -0,0 +1,1202 @@ +// Copyright (C) 2021-2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-expr.h" +#include "rust-hir-full-decls.h" +#include "rust-hir-visitor.h" +#include "rust-hir-full.h" +#include "rust-system.h" + +namespace Rust { +namespace HIR { + +void +DefaultHIRVisitor::walk (Lifetime &) +{} + +void +DefaultHIRVisitor::walk (LifetimeParam &lifetime_param) +{ + visit_outer_attrs (lifetime_param); + lifetime_param.get_lifetime ().accept_vis (*this); + for (Lifetime &lifetime_bound : lifetime_param.get_lifetime_bounds ()) + lifetime_bound.accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_generic_args (GenericArgs &generic_args) +{ + for (auto &lifetime : generic_args.get_lifetime_args ()) + lifetime.accept_vis (*this); + for (auto &type : generic_args.get_type_args ()) + type->accept_vis (*this); + for (auto &binding : generic_args.get_binding_args ()) + binding.get_type ().accept_vis (*this); + for (auto &const_arg : generic_args.get_const_args ()) + const_arg.get_expression ()->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (PathInExpression &path_in_expr) +{ + visit_outer_attrs (path_in_expr); + if (!path_in_expr.is_lang_item ()) + for (auto &segment : path_in_expr.get_segments ()) + visit_path_expr_segment (segment); +} + +void +DefaultHIRVisitor::walk (TypePathSegment &) +{} + +void +DefaultHIRVisitor::walk (TypePathSegmentFunction &segment_function) +{ + TypePathFunction &function_path = segment_function.get_function_path (); + if (function_path.has_inputs ()) + for (auto ¶m : function_path.get_params ()) + param->accept_vis (*this); + if (function_path.has_return_type ()) + function_path.get_return_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypePathSegmentGeneric &segment_generic) +{ + if (segment_generic.has_generic_args ()) + visit_generic_args (segment_generic.get_generic_args ()); +} + +void +DefaultHIRVisitor::walk (TypePath &type_path) +{ + for (auto &segment : type_path.get_segments ()) + segment->accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_qualified_path_type (QualifiedPathType &path) +{ + path.get_type ().accept_vis (*this); + if (path.has_as_clause ()) + path.get_trait ().accept_vis (*this); +} + +// TODO: Implement visit_path_expr_segment +void +DefaultHIRVisitor::visit_path_expr_segment (PathExprSegment &segment) +{ + if (segment.has_generic_args ()) + visit_generic_args (segment.get_generic_args ()); +} + +void +DefaultHIRVisitor::walk (QualifiedPathInExpression &path_in_expr) +{ + visit_outer_attrs (path_in_expr); + visit_qualified_path_type (path_in_expr.get_path_type ()); + for (auto &segment : path_in_expr.get_segments ()) + visit_path_expr_segment (segment); +} + +void +DefaultHIRVisitor::walk (QualifiedPathInType &path_in_type) +{ + visit_qualified_path_type (path_in_type.get_path_type ()); + path_in_type.get_associated_segment ().accept_vis (*this); + for (auto &segment : path_in_type.get_segments ()) + segment->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LiteralExpr &expr) +{ + visit_outer_attrs (expr); +} + +void +DefaultHIRVisitor::walk (BorrowExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (DereferenceExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ErrorPropagationExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (NegationExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArithmeticOrLogicalExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ComparisonExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LazyBooleanExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypeCastExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); + expr.get_type_to_convert_to ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (AssignmentExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (CompoundAssignmentExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (GroupedExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_expr_in_parens ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayElemsValues &elems) +{ + for (auto &elem : elems.get_values ()) + elem->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayElemsCopied &elems) +{ + elems.get_elem_to_copy ().accept_vis (*this); + elems.get_num_copies_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_internal_elements ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayIndexExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_array_expr ().accept_vis (*this); + expr.get_index_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + for (auto &elem : expr.get_tuple_elems ()) + elem->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleIndexExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_tuple_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprStruct &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_struct_name ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprFieldIdentifier &) +{} + +void +DefaultHIRVisitor::walk (StructExprFieldIdentifierValue &field) +{ + field.get_value ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprFieldIndexValue &field) +{ + field.get_value ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprStructFields &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_struct_name ().accept_vis (*this); + if (expr.has_struct_base ()) + { + StructBase &base = expr.get_struct_base (); + base.get_base ().accept_vis (*this); + } + for (auto &field : expr.get_fields ()) + field->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprStructBase &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_struct_name ().accept_vis (*this); + StructBase &base = expr.get_struct_base (); + base.get_base ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (CallExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_fnexpr ().accept_vis (*this); + for (auto &arg : expr.get_arguments ()) + arg->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (MethodCallExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_receiver ().accept_vis (*this); + visit_path_expr_segment (expr.get_method_name ()); + for (auto &arg : expr.get_arguments ()) + arg->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (FieldAccessExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_receiver_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_closure_param (ClosureParam ¶m) +{ + visit_outer_attrs (param); + param.get_pattern ().accept_vis (*this); + if (param.has_type_given ()) + { + param.get_type ().accept_vis (*this); + } +} + +void +DefaultHIRVisitor::walk (ClosureExpr &expr) +{ + visit_outer_attrs (expr); + for (auto ¶m : expr.get_params ()) + visit_closure_param (param); + if (expr.has_return_type ()) + expr.get_return_type ().accept_vis (*this); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (BlockExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + for (auto &stmt : expr.get_statements ()) + stmt->accept_vis (*this); + if (expr.has_expr ()) + expr.get_final_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (AnonConst &expr) +{ + if (!expr.is_deferred ()) + expr.get_inner_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ContinueExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_label ()) + expr.get_label ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (BreakExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_label ()) + expr.get_label ().accept_vis (*this); + + if (expr.has_break_expr ()) + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeFromToExpr &expr) +{ + expr.get_from_expr ().accept_vis (*this); + expr.get_to_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeFromExpr &expr) +{ + expr.get_from_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeToExpr &expr) +{ + expr.get_to_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeFullExpr &) +{} + +void +DefaultHIRVisitor::walk (RangeFromToInclExpr &expr) +{ + expr.get_from_expr ().accept_vis (*this); + expr.get_to_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeToInclExpr &expr) +{ + expr.get_to_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ReturnExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_return_expr ()) + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (UnsafeBlockExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_block_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_loop_label (LoopLabel &label) +{ + label.get_lifetime ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LoopExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit_loop_label (expr.get_loop_label ()); + expr.get_loop_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (WhileLoopExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit_loop_label (expr.get_loop_label ()); + expr.get_predicate_expr ().accept_vis (*this); + expr.get_loop_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (WhileLetLoopExpr &expr) +{ + visit_outer_attrs (expr); + for (auto &pattern : expr.get_patterns ()) + pattern->accept_vis (*this); + if (expr.has_loop_label ()) + visit_loop_label (expr.get_loop_label ()); + expr.get_cond ().accept_vis (*this); + expr.get_loop_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (IfExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_if_condition ().accept_vis (*this); + expr.get_if_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (IfExprConseqElse &expr) +{ + expr.IfExpr::accept_vis (*this); + expr.get_else_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_match_arm (MatchArm &arm) +{ + // visit_outer_attrs (arm); + for (auto &pattern : arm.get_patterns ()) + pattern->accept_vis (*this); + if (arm.has_match_arm_guard ()) + arm.get_guard_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_match_case (MatchCase &arm) +{ + visit_match_arm (arm.get_arm ()); + arm.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (MatchExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_scrutinee_expr ().accept_vis (*this); + for (auto &arm : expr.get_match_cases ()) + visit_match_case (arm); +} + +void +DefaultHIRVisitor::walk (AwaitExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_awaited_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (AsyncBlockExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_block_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (InlineAsm &expr) +{ + visit_outer_attrs (expr); + auto &operands = expr.get_operands (); + using RegisterType = AST::InlineAsmOperand::RegisterType; + for (auto &operand : operands) + { + switch (operand.get_register_type ()) + { + case RegisterType::In: + { + operand.get_in ().expr->accept_vis (*this); + break; + } + case RegisterType::Out: + { + operand.get_out ().expr->accept_vis (*this); + break; + } + case RegisterType::InOut: + { + operand.get_in_out ().expr->accept_vis (*this); + break; + } + case RegisterType::SplitInOut: + { + operand.get_split_in_out ().in_expr->accept_vis (*this); + operand.get_split_in_out ().out_expr->accept_vis (*this); + break; + } + case RegisterType::Const: + { + operand.get_const ().anon_const.get_inner_expr ().accept_vis ( + *this); + break; + } + case RegisterType::Sym: + { + operand.get_sym ().expr->accept_vis (*this); + break; + } + case RegisterType::Label: + { + operand.get_label ().expr->accept_vis (*this); + break; + } + } + } +} + +void +DefaultHIRVisitor::walk (LlvmInlineAsm &expr) +{ + for (auto &output : expr.outputs) + output.expr->accept_vis (*this); + for (auto &input : expr.inputs) + input.expr->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (OffsetOf &expr) +{ + expr.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypeParam ¶m) +{ + visit_outer_attrs (param); + for (auto &bounds : param.get_type_param_bounds ()) + bounds->accept_vis (*this); + if (param.has_type ()) + param.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ConstGenericParam &const_param) +{ + visit_outer_attrs (const_param); + const_param.get_type ().accept_vis (*this); + if (const_param.has_default_expression ()) + const_param.get_default_expression ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LifetimeWhereClauseItem &item) +{ + item.get_lifetime ().accept_vis (*this); + for (auto &bound : item.get_lifetime_bounds ()) + bound.accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypeBoundWhereClauseItem &item) +{ + for (auto &lifetime : item.get_for_lifetimes ()) + lifetime.accept_vis (*this); + item.get_bound_type ().accept_vis (*this); + for (auto ¶m : item.get_type_param_bounds ()) + param->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (Module &module) +{ + visit_outer_attrs (module); + visit_inner_attrs (module); + for (auto &item : module.get_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ExternCrate &crate) +{ + visit_outer_attrs (crate); +} + +void +DefaultHIRVisitor::walk (UseTreeGlob &) +{} + +void +DefaultHIRVisitor::walk (UseTreeList &) +{} + +void +DefaultHIRVisitor::walk (UseTreeRebind &) +{} + +void +DefaultHIRVisitor::walk (UseDeclaration &) +{} + +void +DefaultHIRVisitor::visit_function_param (FunctionParam ¶m) +{ + param.get_param_name ().accept_vis (*this); + param.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (Function &function) +{ + visit_outer_attrs (function); + for (auto &generic : function.get_generic_params ()) + generic->accept_vis (*this); + for (auto ¶m : function.get_function_params ()) + visit_function_param (param); + if (function.has_return_type ()) + function.get_return_type ().accept_vis (*this); + if (function.has_where_clause ()) + visit_where_clause (function.get_where_clause ()); + function.get_definition ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypeAlias &type_alias) +{ + visit_outer_attrs (type_alias); + for (auto &generic : type_alias.get_generic_params ()) + generic->accept_vis (*this); + if (type_alias.has_where_clause ()) + visit_where_clause (type_alias.get_where_clause ()); + type_alias.get_type_aliased ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_struct_field (StructField &field) +{ + field.get_field_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructStruct &struct_item) +{ + visit_outer_attrs (struct_item); + for (auto &generic : struct_item.get_generic_params ()) + generic->accept_vis (*this); + if (struct_item.has_where_clause ()) + visit_where_clause (struct_item.get_where_clause ()); + for (auto &field : struct_item.get_fields ()) + visit_struct_field (field); +} + +void +DefaultHIRVisitor::walk (TupleStruct &tuple_struct) +{ + visit_outer_attrs (tuple_struct); + for (auto &generic : tuple_struct.get_generic_params ()) + generic->accept_vis (*this); + if (tuple_struct.has_where_clause ()) + visit_where_clause (tuple_struct.get_where_clause ()); + for (auto &field : tuple_struct.get_fields ()) + field.get_field_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (EnumItem &item) +{ + visit_outer_attrs (item); +} + +void +DefaultHIRVisitor::walk (EnumItemTuple &item_tuple) +{ + item_tuple.EnumItem::accept_vis (*this); + for (auto &field : item_tuple.get_tuple_fields ()) + field.get_field_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (EnumItemStruct &item_struct) +{ + item_struct.EnumItem::accept_vis (*this); + for (auto &field : item_struct.get_struct_fields ()) + field.get_field_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (EnumItemDiscriminant &item) +{ + item.EnumItem::accept_vis (*this); + item.get_discriminant_expression ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (Enum &enum_item) +{ + visit_outer_attrs (enum_item); + for (auto &generic : enum_item.get_generic_params ()) + generic->accept_vis (*this); + if (enum_item.has_where_clause ()) + visit_where_clause (enum_item.get_where_clause ()); + for (auto &item : enum_item.get_variants ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (Union &union_item) +{ + visit_outer_attrs (union_item); + for (auto &generic : union_item.get_generic_params ()) + generic->accept_vis (*this); + if (union_item.has_where_clause ()) + visit_where_clause (union_item.get_where_clause ()); + for (auto &variant : union_item.get_variants ()) + visit_struct_field (variant); +} + +void +DefaultHIRVisitor::walk (ConstantItem &const_item) +{ + visit_outer_attrs (const_item); + const_item.get_type ().accept_vis (*this); + const_item.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StaticItem &static_item) +{ + visit_outer_attrs (static_item); + static_item.get_type ().accept_vis (*this); + static_item.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_self_param (SelfParam &self_param) +{ + if (self_param.has_lifetime ()) + { + Lifetime lifetime = self_param.get_lifetime (); + lifetime.accept_vis (*this); + } + if (self_param.has_type ()) + self_param.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitItemFunc &item) +{ + visit_outer_attrs (item); + TraitFunctionDecl &decl = item.get_decl (); + for (auto &generic : decl.get_generic_params ()) + generic->accept_vis (*this); + if (decl.get_self ().has_value ()) + visit_self_param (decl.get_self ().value ()); + for (auto ¶m : decl.get_function_params ()) + visit_function_param (param); + if (decl.has_return_type ()) + decl.get_return_type ().accept_vis (*this); + if (decl.has_where_clause ()) + visit_where_clause (decl.get_where_clause ()); + if (item.has_definition ()) + item.get_block_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitItemConst &item) +{ + visit_outer_attrs (item); + item.get_type ().accept_vis (*this); + if (item.has_expr ()) + item.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitItemType &item) +{ + visit_outer_attrs (item); + for (auto &bound : item.get_type_param_bounds ()) + bound->accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_where_clause (const WhereClause &where_clause) +{ + for (auto &item : where_clause.get_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_where_clause (WhereClause &where_clause) +{ + for (auto &item : where_clause.get_items ()) + { + item->accept_vis (*this); + } +} + +void +DefaultHIRVisitor::walk (WhereClauseItem &node) +{} + +void +DefaultHIRVisitor::walk (Trait &trait) +{ + visit_outer_attrs (trait); + for (auto &generic : trait.get_generic_params ()) + generic->accept_vis (*this); + if (trait.has_where_clause ()) + visit_where_clause (trait.get_where_clause ()); + for (auto &bound : trait.get_type_param_bounds ()) + bound->accept_vis (*this); + for (auto &item : trait.get_trait_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ImplBlock &impl) +{ + visit_outer_attrs (impl); + for (auto &generic : impl.get_generic_params ()) + generic->accept_vis (*this); + if (impl.has_trait_ref ()) + impl.get_trait_ref ().accept_vis (*this); + impl.get_type ().accept_vis (*this); + if (impl.has_where_clause ()) + visit_where_clause (impl.get_where_clause ()); + visit_inner_attrs (impl); + for (auto &item : impl.get_impl_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ExternalStaticItem &item) +{ + visit_outer_attrs (item); + item.get_item_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_named_function_param (NamedFunctionParam ¶m) +{ + param.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ExternalFunctionItem &item) +{ + visit_outer_attrs (item); + for (auto &generic : item.get_generic_params ()) + generic->accept_vis (*this); + for (auto ¶m : item.get_function_params ()) + visit_named_function_param (param); + if (item.has_return_type ()) + item.get_return_type ().accept_vis (*this); + if (item.has_where_clause ()) + visit_where_clause (item.get_where_clause ()); +} + +void +DefaultHIRVisitor::walk (ExternalTypeItem &item) +{ + visit_outer_attrs (item); +} + +void +DefaultHIRVisitor::walk (ExternBlock &block) +{ + visit_outer_attrs (block); + visit_inner_attrs (block); + for (auto &item : block.get_extern_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LiteralPattern &) +{} + +void +DefaultHIRVisitor::walk (IdentifierPattern &pattern) +{ + if (pattern.has_subpattern ()) + pattern.get_subpattern ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (WildcardPattern &) +{} + +void +DefaultHIRVisitor::walk (RangePatternBoundLiteral &) +{} + +void +DefaultHIRVisitor::walk (RangePatternBoundPath &bound) +{ + bound.get_path ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangePatternBoundQualPath &bound) +{ + bound.get_qualified_path ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangePattern &pattern) +{ + pattern.get_lower_bound ().accept_vis (*this); + pattern.get_upper_bound ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ReferencePattern &pattern) +{ + pattern.get_referenced_pattern ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructPatternFieldTuplePat &field) +{ + visit_outer_attrs (field); + field.get_tuple_pattern ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructPatternFieldIdentPat &field) +{ + visit_outer_attrs (field); + field.get_pattern ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructPatternFieldIdent &field) +{ + visit_outer_attrs (field); +} + +void +DefaultHIRVisitor::walk (StructPattern &pattern) +{ + pattern.get_path ().accept_vis (*this); + StructPatternElements &elements = pattern.get_struct_pattern_elems (); + for (auto &field : elements.get_struct_pattern_fields ()) + field->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleStructItemsNoRest &tuple_items) +{ + for (auto &item : tuple_items.get_patterns ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleStructItemsHasRest &tuple_items) +{ + for (auto &lower : tuple_items.get_lower_patterns ()) + lower->accept_vis (*this); + for (auto &upper : tuple_items.get_upper_patterns ()) + upper->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleStructPattern &pattern) +{ + pattern.get_path ().accept_vis (*this); + pattern.get_items ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TuplePatternItemsNoRest &tuple_items) +{ + for (auto &pattern : tuple_items.get_patterns ()) + pattern->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TuplePatternItemsHasRest &tuple_items) +{ + for (auto &lower : tuple_items.get_lower_patterns ()) + lower->accept_vis (*this); + for (auto &upper : tuple_items.get_upper_patterns ()) + upper->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TuplePattern &pattern) +{ + pattern.get_items ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (SlicePatternItemsNoRest &items) +{ + for (auto &pattern : items.get_patterns ()) + pattern->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (SlicePatternItemsHasRest &items) +{ + for (auto &lower : items.get_lower_patterns ()) + lower->accept_vis (*this); + for (auto &upper : items.get_upper_patterns ()) + upper->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (SlicePattern &pattern) +{ + pattern.get_items ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (AltPattern &pattern) +{ + for (auto &item : pattern.get_alts ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (EmptyStmt &stmt) +{} + +void +DefaultHIRVisitor::walk (LetStmt &stmt) +{ + visit_outer_attrs (stmt); + stmt.get_pattern ().accept_vis (*this); + if (stmt.has_type ()) + stmt.get_type ().accept_vis (*this); + if (stmt.has_init_expr ()) + stmt.get_init_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ExprStmt &stmt) +{ + stmt.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitBound &bound) +{ + for (auto &lifetime : bound.get_for_lifetimes ()) + lifetime.accept_vis (*this); + bound.get_path ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ImplTraitType &type) +{ + for (auto &bound : type.get_type_param_bounds ()) + bound->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitObjectType &type) +{ + for (auto &bound : type.get_type_param_bounds ()) + bound->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ParenthesisedType &type) +{ + type.get_type_in_parens ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleType &type) +{ + for (auto &elem : type.get_elems ()) + elem->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (NeverType &type) +{} + +void +DefaultHIRVisitor::walk (RawPointerType &type) +{ + type.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ReferenceType &type) +{ + if (type.has_lifetime ()) + type.get_lifetime ().accept_vis (*this); + type.get_base_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayType &type) +{ + type.get_element_type ().accept_vis (*this); + type.get_size_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (SliceType &type) +{ + type.get_element_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (InferredType &type) +{} + +void +DefaultHIRVisitor::walk (BareFunctionType &type) +{ + for (auto &lifetime : type.get_for_lifetimes ()) + lifetime.accept_vis (*this); + for (auto ¶m : type.get_function_params ()) + param.get_type ().accept_vis (*this); + if (type.has_return_type ()) + type.get_return_type ().accept_vis (*this); +} + +} // namespace HIR +} // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 800e647..77760b0 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -20,6 +20,7 @@ #define RUST_HIR_VISITOR_H #include "rust-hir-full-decls.h" +#include "rust-ast.h" namespace Rust { namespace HIR { @@ -64,6 +65,8 @@ public: virtual void visit (MethodCallExpr &expr) = 0; virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ClosureExpr &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; @@ -84,6 +87,8 @@ public: virtual void visit (AwaitExpr &expr) = 0; virtual void visit (AsyncBlockExpr &expr) = 0; virtual void visit (InlineAsm &expr) = 0; + virtual void visit (LlvmInlineAsm &expr) = 0; + virtual void visit (OffsetOf &expr) = 0; virtual void visit (TypeParam ¶m) = 0; virtual void visit (ConstGenericParam ¶m) = 0; virtual void visit (LifetimeWhereClauseItem &item) = 0; @@ -127,12 +132,14 @@ public: virtual void visit (StructPatternFieldIdentPat &field) = 0; virtual void visit (StructPatternFieldIdent &field) = 0; virtual void visit (StructPattern &pattern) = 0; - virtual void visit (TupleStructItemsNoRange &tuple_items) = 0; - virtual void visit (TupleStructItemsRange &tuple_items) = 0; + virtual void visit (TupleStructItemsNoRest &tuple_items) = 0; + virtual void visit (TupleStructItemsHasRest &tuple_items) = 0; virtual void visit (TupleStructPattern &pattern) = 0; - virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0; - virtual void visit (TuplePatternItemsRanged &tuple_items) = 0; + virtual void visit (TuplePatternItemsNoRest &tuple_items) = 0; + virtual void visit (TuplePatternItemsHasRest &tuple_items) = 0; virtual void visit (TuplePattern &pattern) = 0; + virtual void visit (SlicePatternItemsNoRest &items) = 0; + virtual void visit (SlicePatternItemsHasRest &items) = 0; virtual void visit (SlicePattern &pattern) = 0; virtual void visit (AltPattern &pattern) = 0; virtual void visit (EmptyStmt &stmt) = 0; @@ -152,6 +159,316 @@ public: virtual void visit (BareFunctionType &type) = 0; }; +class DefaultHIRVisitor : public HIRFullVisitor +{ +public: + virtual void visit_where_clause (WhereClause &); + virtual void visit_where_clause (const WhereClause &); + virtual void visit_named_function_param (NamedFunctionParam ¶m); + virtual void visit_function_param (FunctionParam ¶m); + virtual void visit_self_param (SelfParam ¶m); + virtual void visit_match_arm (MatchArm &arm); + virtual void visit_match_case (MatchCase &); + virtual void visit_struct_field (StructField &field); + virtual void visit_generic_args (GenericArgs &args); + virtual void visit_qualified_path_type (QualifiedPathType &); + virtual void visit_path_expr_segment (PathExprSegment &segment); + virtual void visit_closure_param (ClosureParam ¶m); + virtual void visit_loop_label (LoopLabel &); + + virtual void visit_attribute (AST::Attribute &attr) + { + visit_attribute (static_cast<const AST::Attribute &> (attr)); + } + virtual void visit_attribute (const AST::Attribute &attr) {} + template <typename T> void visit_outer_attrs (T &node) + { + for (auto &attr : node.get_outer_attrs ()) + visit_attribute (attr); + } + template <typename T> void visit_inner_attrs (T &node) + { + for (auto &attr : node.get_inner_attrs ()) + visit_attribute (attr); + } + + virtual void visit (WhereClauseItem &node) { walk (node); } + + virtual void visit (Lifetime &node) override { walk (node); } + virtual void visit (LifetimeParam &node) override { walk (node); } + virtual void visit (PathInExpression &node) override { walk (node); } + virtual void visit (TypePathSegment &node) override { walk (node); } + virtual void visit (TypePathSegmentGeneric &node) override { walk (node); } + virtual void visit (TypePathSegmentFunction &node) override { walk (node); } + virtual void visit (TypePath &node) override { walk (node); } + virtual void visit (QualifiedPathInExpression &node) override { walk (node); } + virtual void visit (QualifiedPathInType &node) override { walk (node); } + virtual void visit (LiteralExpr &node) override { walk (node); } + virtual void visit (BorrowExpr &node) override { walk (node); } + virtual void visit (DereferenceExpr &node) override { walk (node); } + virtual void visit (ErrorPropagationExpr &node) override { walk (node); } + virtual void visit (NegationExpr &node) override { walk (node); } + virtual void visit (ArithmeticOrLogicalExpr &node) override { walk (node); } + virtual void visit (ComparisonExpr &node) override { walk (node); } + virtual void visit (LazyBooleanExpr &node) override { walk (node); } + virtual void visit (TypeCastExpr &node) override { walk (node); } + virtual void visit (AssignmentExpr &node) override { walk (node); } + virtual void visit (CompoundAssignmentExpr &node) override { walk (node); } + virtual void visit (GroupedExpr &node) override { walk (node); } + virtual void visit (ArrayElemsValues &node) override { walk (node); } + virtual void visit (ArrayElemsCopied &node) override { walk (node); } + virtual void visit (ArrayExpr &node) override { walk (node); } + virtual void visit (ArrayIndexExpr &node) override { walk (node); } + virtual void visit (TupleExpr &node) override { walk (node); } + virtual void visit (TupleIndexExpr &node) override { walk (node); } + virtual void visit (StructExprStruct &node) override { walk (node); } + virtual void visit (StructExprFieldIdentifier &node) override { walk (node); } + virtual void visit (StructExprFieldIdentifierValue &node) override + { + walk (node); + } + virtual void visit (StructExprFieldIndexValue &node) override { walk (node); } + virtual void visit (StructExprStructFields &node) override { walk (node); } + virtual void visit (StructExprStructBase &node) override { walk (node); } + virtual void visit (CallExpr &node) override { walk (node); } + virtual void visit (MethodCallExpr &node) override { walk (node); } + virtual void visit (FieldAccessExpr &node) override { walk (node); } + virtual void visit (ClosureExpr &node) override { walk (node); } + virtual void visit (BlockExpr &node) override { walk (node); } + virtual void visit (AnonConst &node) override { walk (node); } + virtual void visit (ConstBlock &node) override { walk (node); } + virtual void visit (ContinueExpr &node) override { walk (node); } + virtual void visit (BreakExpr &node) override { walk (node); } + virtual void visit (RangeFromToExpr &node) override { walk (node); } + virtual void visit (RangeFromExpr &node) override { walk (node); } + virtual void visit (RangeToExpr &node) override { walk (node); } + virtual void visit (RangeFullExpr &node) override { walk (node); } + virtual void visit (RangeFromToInclExpr &node) override { walk (node); } + virtual void visit (RangeToInclExpr &node) override { walk (node); } + virtual void visit (ReturnExpr &node) override { walk (node); } + virtual void visit (UnsafeBlockExpr &node) override { walk (node); } + virtual void visit (LoopExpr &node) override { walk (node); } + virtual void visit (WhileLoopExpr &node) override { walk (node); } + virtual void visit (WhileLetLoopExpr &node) override { walk (node); } + virtual void visit (IfExpr &node) override { walk (node); } + virtual void visit (IfExprConseqElse &node) override { walk (node); } + virtual void visit (MatchExpr &node) override { walk (node); } + virtual void visit (AwaitExpr &node) override { walk (node); } + virtual void visit (AsyncBlockExpr &node) override { walk (node); } + virtual void visit (InlineAsm &node) override { walk (node); } + virtual void visit (LlvmInlineAsm &node) override { walk (node); } + virtual void visit (OffsetOf &node) override { walk (node); } + virtual void visit (TypeParam &node) override { walk (node); } + virtual void visit (ConstGenericParam &node) override { walk (node); } + virtual void visit (LifetimeWhereClauseItem &node) override { walk (node); } + virtual void visit (TypeBoundWhereClauseItem &node) override { walk (node); } + virtual void visit (Module &node) override { walk (node); } + virtual void visit (ExternCrate &node) override { walk (node); } + virtual void visit (UseTreeGlob &node) override { walk (node); } + virtual void visit (UseTreeList &node) override { walk (node); } + virtual void visit (UseTreeRebind &node) override { walk (node); } + virtual void visit (UseDeclaration &node) override { walk (node); } + virtual void visit (Function &node) override { walk (node); } + virtual void visit (TypeAlias &node) override { walk (node); } + virtual void visit (StructStruct &node) override { walk (node); } + virtual void visit (TupleStruct &node) override { walk (node); } + virtual void visit (EnumItem &node) override { walk (node); } + virtual void visit (EnumItemTuple &node) override { walk (node); } + virtual void visit (EnumItemStruct &node) override { walk (node); } + virtual void visit (EnumItemDiscriminant &node) override { walk (node); } + virtual void visit (Enum &node) override { walk (node); } + virtual void visit (Union &node) override { walk (node); } + virtual void visit (ConstantItem &node) override { walk (node); } + virtual void visit (StaticItem &node) override { walk (node); } + virtual void visit (TraitItemFunc &node) override { walk (node); } + virtual void visit (TraitItemConst &node) override { walk (node); } + virtual void visit (TraitItemType &node) override { walk (node); } + virtual void visit (Trait &node) override { walk (node); } + virtual void visit (ImplBlock &node) override { walk (node); } + virtual void visit (ExternalStaticItem &node) override { walk (node); } + virtual void visit (ExternalFunctionItem &node) override { walk (node); } + virtual void visit (ExternalTypeItem &node) override { walk (node); } + virtual void visit (ExternBlock &node) override { walk (node); } + virtual void visit (LiteralPattern &node) override { walk (node); } + virtual void visit (IdentifierPattern &node) override { walk (node); } + virtual void visit (WildcardPattern &node) override { walk (node); } + virtual void visit (RangePatternBoundLiteral &node) override { walk (node); } + virtual void visit (RangePatternBoundPath &node) override { walk (node); } + virtual void visit (RangePatternBoundQualPath &node) override { walk (node); } + virtual void visit (RangePattern &node) override { walk (node); } + virtual void visit (ReferencePattern &node) override { walk (node); } + virtual void visit (StructPatternFieldTuplePat &node) override + { + walk (node); + } + virtual void visit (StructPatternFieldIdentPat &node) override + { + walk (node); + } + virtual void visit (StructPatternFieldIdent &node) override { walk (node); } + virtual void visit (StructPattern &node) override { walk (node); } + virtual void visit (TupleStructItemsNoRest &node) override { walk (node); } + virtual void visit (TupleStructItemsHasRest &node) override { walk (node); } + virtual void visit (TupleStructPattern &node) override { walk (node); } + virtual void visit (TuplePatternItemsNoRest &node) override { walk (node); } + virtual void visit (TuplePatternItemsHasRest &node) override { walk (node); } + virtual void visit (TuplePattern &node) override { walk (node); } + virtual void visit (SlicePatternItemsNoRest &node) override { walk (node); } + virtual void visit (SlicePatternItemsHasRest &node) override { walk (node); } + virtual void visit (SlicePattern &node) override { walk (node); } + virtual void visit (AltPattern &node) override { walk (node); } + virtual void visit (EmptyStmt &node) override { walk (node); } + virtual void visit (LetStmt &node) override { walk (node); } + virtual void visit (ExprStmt &node) override { walk (node); } + virtual void visit (TraitBound &node) override { walk (node); } + virtual void visit (ImplTraitType &node) override { walk (node); } + virtual void visit (TraitObjectType &node) override { walk (node); } + virtual void visit (ParenthesisedType &node) override { walk (node); } + virtual void visit (TupleType &node) override { walk (node); } + virtual void visit (NeverType &node) override { walk (node); } + virtual void visit (RawPointerType &node) override { walk (node); } + virtual void visit (ReferenceType &node) override { walk (node); } + virtual void visit (ArrayType &node) override { walk (node); } + virtual void visit (SliceType &node) override { walk (node); } + virtual void visit (InferredType &node) override { walk (node); } + virtual void visit (BareFunctionType &node) override { walk (node); } + +protected: + virtual void walk (WhereClauseItem &) final; + + virtual void walk (Lifetime &) final; + virtual void walk (LifetimeParam &) final; + virtual void walk (PathInExpression &) final; + virtual void walk (TypePathSegment &) final; + virtual void walk (TypePathSegmentGeneric &) final; + virtual void walk (TypePathSegmentFunction &) final; + virtual void walk (TypePath &) final; + virtual void walk (QualifiedPathInExpression &) final; + virtual void walk (QualifiedPathInType &) final; + + virtual void walk (LiteralExpr &) final; + virtual void walk (BorrowExpr &) final; + virtual void walk (DereferenceExpr &) final; + virtual void walk (ErrorPropagationExpr &) final; + virtual void walk (NegationExpr &) final; + virtual void walk (ArithmeticOrLogicalExpr &) final; + virtual void walk (ComparisonExpr &) final; + virtual void walk (LazyBooleanExpr &) final; + virtual void walk (TypeCastExpr &) final; + virtual void walk (AssignmentExpr &) final; + virtual void walk (CompoundAssignmentExpr &) final; + virtual void walk (GroupedExpr &) final; + + virtual void walk (ArrayElemsValues &) final; + virtual void walk (ArrayElemsCopied &) final; + virtual void walk (ArrayExpr &) final; + virtual void walk (ArrayIndexExpr &) final; + virtual void walk (TupleExpr &) final; + virtual void walk (TupleIndexExpr &) final; + virtual void walk (StructExprStruct &) final; + virtual void walk (StructExprFieldIdentifier &) final; + virtual void walk (StructExprFieldIdentifierValue &) final; + virtual void walk (StructExprFieldIndexValue &) final; + virtual void walk (StructExprStructFields &) final; + virtual void walk (StructExprStructBase &) final; + virtual void walk (CallExpr &) final; + virtual void walk (MethodCallExpr &) final; + virtual void walk (FieldAccessExpr &) final; + virtual void walk (ClosureExpr &) final; + virtual void walk (BlockExpr &) final; + virtual void walk (AnonConst &) final; + virtual void walk (ConstBlock &) final; + virtual void walk (ContinueExpr &) final; + virtual void walk (BreakExpr &) final; + virtual void walk (RangeFromToExpr &) final; + virtual void walk (RangeFromExpr &) final; + virtual void walk (RangeToExpr &) final; + virtual void walk (RangeFullExpr &) final; + virtual void walk (RangeFromToInclExpr &) final; + virtual void walk (RangeToInclExpr &) final; + virtual void walk (ReturnExpr &) final; + virtual void walk (UnsafeBlockExpr &) final; + virtual void walk (LoopExpr &) final; + virtual void walk (WhileLoopExpr &) final; + virtual void walk (WhileLetLoopExpr &) final; + virtual void walk (IfExpr &) final; + virtual void walk (IfExprConseqElse &) final; + virtual void walk (MatchExpr &) final; + virtual void walk (AwaitExpr &) final; + virtual void walk (AsyncBlockExpr &) final; + virtual void walk (InlineAsm &) final; + virtual void walk (LlvmInlineAsm &) final; + virtual void walk (OffsetOf &) final; + virtual void walk (TypeParam &) final; + virtual void walk (ConstGenericParam &) final; + virtual void walk (LifetimeWhereClauseItem &) final; + virtual void walk (TypeBoundWhereClauseItem &) final; + virtual void walk (Module &) final; + virtual void walk (ExternCrate &) final; + virtual void walk (UseTreeGlob &) final; + virtual void walk (UseTreeList &) final; + virtual void walk (UseTreeRebind &) final; + virtual void walk (UseDeclaration &) final; + virtual void walk (Function &) final; + virtual void walk (TypeAlias &) final; + virtual void walk (StructStruct &) final; + virtual void walk (TupleStruct &) final; + virtual void walk (EnumItem &) final; + virtual void walk (EnumItemTuple &) final; + virtual void walk (EnumItemStruct &) final; + virtual void walk (EnumItemDiscriminant &) final; + virtual void walk (Enum &) final; + virtual void walk (Union &) final; + virtual void walk (ConstantItem &) final; + virtual void walk (StaticItem &) final; + virtual void walk (TraitItemFunc &) final; + virtual void walk (TraitItemConst &) final; + virtual void walk (TraitItemType &) final; + virtual void walk (Trait &) final; + virtual void walk (ImplBlock &) final; + virtual void walk (ExternalStaticItem &) final; + virtual void walk (ExternalFunctionItem &) final; + virtual void walk (ExternalTypeItem &) final; + virtual void walk (ExternBlock &) final; + virtual void walk (LiteralPattern &) final; + virtual void walk (IdentifierPattern &) final; + virtual void walk (WildcardPattern &) final; + virtual void walk (RangePatternBoundLiteral &) final; + virtual void walk (RangePatternBoundPath &) final; + virtual void walk (RangePatternBoundQualPath &) final; + virtual void walk (RangePattern &) final; + virtual void walk (ReferencePattern &) final; + virtual void walk (StructPatternFieldTuplePat &) final; + virtual void walk (StructPatternFieldIdentPat &) final; + virtual void walk (StructPatternFieldIdent &) final; + virtual void walk (StructPattern &) final; + virtual void walk (TupleStructItemsNoRest &) final; + virtual void walk (TupleStructItemsHasRest &) final; + virtual void walk (TupleStructPattern &) final; + virtual void walk (TuplePatternItemsNoRest &) final; + virtual void walk (TuplePatternItemsHasRest &) final; + virtual void walk (TuplePattern &) final; + virtual void walk (SlicePatternItemsNoRest &) final; + virtual void walk (SlicePatternItemsHasRest &) final; + virtual void walk (SlicePattern &) final; + virtual void walk (AltPattern &) final; + virtual void walk (EmptyStmt &) final; + virtual void walk (LetStmt &) final; + virtual void walk (ExprStmt &) final; + virtual void walk (TraitBound &) final; + virtual void walk (ImplTraitType &) final; + virtual void walk (TraitObjectType &) final; + virtual void walk (ParenthesisedType &) final; + virtual void walk (TupleType &) final; + virtual void walk (NeverType &) final; + virtual void walk (RawPointerType &) final; + virtual void walk (ReferenceType &) final; + virtual void walk (ArrayType &) final; + virtual void walk (SliceType &) final; + virtual void walk (InferredType &) final; + virtual void walk (BareFunctionType &) final; +}; + class HIRFullVisitorBase : public HIRFullVisitor { public: @@ -200,6 +517,8 @@ public: virtual void visit (FieldAccessExpr &) override {} virtual void visit (ClosureExpr &) override {} virtual void visit (BlockExpr &) override {} + virtual void visit (AnonConst &) override {} + virtual void visit (ConstBlock &) override {} virtual void visit (ContinueExpr &) override {} virtual void visit (BreakExpr &) override {} virtual void visit (RangeFromToExpr &) override {} @@ -220,6 +539,8 @@ public: virtual void visit (AwaitExpr &) override {} virtual void visit (AsyncBlockExpr &) override {} virtual void visit (InlineAsm &) override {} + virtual void visit (LlvmInlineAsm &) override {} + virtual void visit (OffsetOf &) override {} virtual void visit (TypeParam &) override {} virtual void visit (ConstGenericParam &) override {} @@ -271,13 +592,16 @@ public: virtual void visit (StructPatternFieldIdent &) override {} virtual void visit (StructPattern &) override {} - virtual void visit (TupleStructItemsNoRange &) override {} - virtual void visit (TupleStructItemsRange &) override {} + virtual void visit (TupleStructItemsNoRest &) override {} + virtual void visit (TupleStructItemsHasRest &) override {} virtual void visit (TupleStructPattern &) override {} - virtual void visit (TuplePatternItemsMultiple &) override {} - virtual void visit (TuplePatternItemsRanged &) override {} + virtual void visit (TuplePatternItemsNoRest &) override {} + virtual void visit (TuplePatternItemsHasRest &) override {} virtual void visit (TuplePattern &) override {} + + virtual void visit (SlicePatternItemsNoRest &) override {} + virtual void visit (SlicePatternItemsHasRest &) override {} virtual void visit (SlicePattern &) override {} virtual void visit (AltPattern &) override {} @@ -425,6 +749,8 @@ public: virtual void visit (MethodCallExpr &expr) = 0; virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; virtual void visit (RangeFromToExpr &expr) = 0; @@ -441,6 +767,8 @@ public: virtual void visit (IfExpr &expr) = 0; virtual void visit (IfExprConseqElse &expr) = 0; virtual void visit (InlineAsm &expr) = 0; + virtual void visit (OffsetOf &expr) = 0; + virtual void visit (LlvmInlineAsm &expr) = 0; virtual void visit (MatchExpr &expr) = 0; virtual void visit (AwaitExpr &expr) = 0; virtual void visit (AsyncBlockExpr &expr) = 0; diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 822eaff..614fec7 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -577,7 +577,8 @@ UseTreeGlob::as_string () const return "*"; case GLOBAL: return "::*"; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { std::string path_str = path.as_string (); return path_str + "::*"; } @@ -600,7 +601,8 @@ UseTreeList::as_string () const case GLOBAL: path_str = "::{"; break; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { path_str = path.as_string () + "::{"; break; } @@ -1048,6 +1050,36 @@ BlockExpr::as_string () const } std::string +AnonConst::as_string () const +{ + std::string istr = indent_spaces (enter); + std::string str = istr + "AnonConst:\n" + istr; + + if (expr.has_value ()) + str += get_inner_expr ().as_string (); + else + str += "_"; + + str += "\n" + indent_spaces (out); + + return str; +} + +std::string +ConstBlock::as_string () const +{ + std::string istr = indent_spaces (enter); + + std::string str = istr + "ConstBlock:\n" + istr; + + str += get_const_expr ().as_string (); + + str += "\n" + indent_spaces (out); + + return str; +} + +std::string TypeAlias::as_string () const { std::string str = VisItem::as_string (); @@ -1314,7 +1346,7 @@ ContinueExpr::as_string () const if (has_label ()) { - str += label.as_string (); + str += get_label ().as_string (); } return str; @@ -1704,7 +1736,7 @@ WhileLoopExpr::as_string () const } else { - str += loop_label.as_string (); + str += get_loop_label ().as_string (); } str += "\n Conditional expr: " + condition->as_string (); @@ -1726,7 +1758,7 @@ WhileLetLoopExpr::as_string () const } else { - str += loop_label.as_string (); + str += get_loop_label ().as_string (); } str += "\n Match arm patterns: "; @@ -1761,7 +1793,7 @@ LoopExpr::as_string () const } else { - str += loop_label.as_string (); + str += get_loop_label ().as_string (); } str += "\n Loop block: " + loop_block->as_string (); @@ -1816,7 +1848,7 @@ BreakExpr::as_string () const if (has_label ()) { - str += label.as_string () + " "; + str += get_label ().as_string () + " "; } if (has_break_expr ()) @@ -2101,11 +2133,6 @@ QualifiedPathInType::as_string () const std::string Lifetime::as_string () const { - if (is_error ()) - { - return "error lifetime"; - } - switch (lifetime_type) { case AST::Lifetime::LifetimeType::NAMED: @@ -2212,8 +2239,8 @@ PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const // create segment and add to vector std::string segment_str = segment.as_string (); - simple_segments.push_back ( - AST::SimplePathSegment (std::move (segment_str), segment.get_locus ())); + simple_segments.emplace_back (std::move (segment_str), + segment.get_locus ()); } // kind of a HACK to get locus depending on opening scope resolution @@ -2254,9 +2281,8 @@ TypePath::as_simple_path () const // create segment and add to vector std::string segment_str = segment->as_string (); - simple_segments.push_back ( - AST::SimplePathSegment (std::move (segment_str), - segment->get_locus ())); + simple_segments.emplace_back (std::move (segment_str), + segment->get_locus ()); } return AST::SimplePath (std::move (simple_segments), @@ -2360,11 +2386,11 @@ RangePatternBoundLiteral::as_string () const } std::string -SlicePattern::as_string () const +SlicePatternItemsNoRest::as_string () const { - std::string str ("SlicePattern: "); + std::string str; - for (const auto &pattern : items) + for (const auto &pattern : patterns) { str += "\n " + pattern->as_string (); } @@ -2373,6 +2399,46 @@ SlicePattern::as_string () const } std::string +SlicePatternItemsHasRest::as_string () const +{ + std::string str; + + str += "\n Lower patterns: "; + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + { + str += "\n " + lower->as_string (); + } + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + { + str += "\n " + upper->as_string (); + } + } + + return str; +} + +std::string +SlicePattern::as_string () const +{ + return "SlicePattern: " + items->as_string (); +} + +std::string AltPattern::as_string () const { std::string str ("AltPattern: "); @@ -2386,7 +2452,7 @@ AltPattern::as_string () const } std::string -TuplePatternItemsMultiple::as_string () const +TuplePatternItemsNoRest::as_string () const { std::string str; @@ -2399,7 +2465,7 @@ TuplePatternItemsMultiple::as_string () const } std::string -TuplePatternItemsRanged::as_string () const +TuplePatternItemsHasRest::as_string () const { std::string str; @@ -2453,10 +2519,29 @@ StructPatternField::as_string () const * just the body */ for (const auto &attr : outer_attrs) { - str += "\n " + attr.as_string (); + str += "\n " + attr.as_string (); } } + str += "\n item type: "; + switch (get_item_type ()) + { + case ItemType::TUPLE_PAT: + str += "TUPLE_PAT"; + break; + case ItemType::IDENT_PAT: + str += "IDENT_PAT"; + break; + case ItemType::IDENT: + str += "IDENT"; + break; + default: + str += "UNKNOWN"; + break; + } + + str += "\n mapping: " + mappings.as_string (); + return str; } @@ -2549,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 @@ -2584,16 +2669,16 @@ IdentifierPattern::as_string () const str += variable_ident.as_string (); - if (has_pattern_to_bind ()) + if (has_subpattern ()) { - str += " @ " + to_bind->as_string (); + str += " @ " + subpattern->as_string (); } return str; } std::string -TupleStructItemsNoRange::as_string () const +TupleStructItemsNoRest::as_string () const { std::string str; @@ -2606,7 +2691,7 @@ TupleStructItemsNoRange::as_string () const } std::string -TupleStructItemsRange::as_string () const +TupleStructItemsHasRest::as_string () const { std::string str ("\n Lower patterns: "); @@ -2760,7 +2845,7 @@ ReferenceType::as_string () const if (has_lifetime ()) { - str += lifetime.as_string () + " "; + str += get_lifetime ().as_string () + " "; } if (is_mut ()) @@ -3411,7 +3496,7 @@ TraitFunctionDecl::as_string () const str += "\n Function params: "; if (is_method ()) { - str += self.as_string () + (has_params () ? ", " : ""); + str += get_self_unchecked ().as_string () + (has_params () ? ", " : ""); } if (has_params ()) @@ -3497,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 ()) { @@ -3525,70 +3622,63 @@ TraitItemType::as_string () const std::string SelfParam::as_string () const { - if (is_error ()) - { - return "error"; - } - else + if (has_type ()) { - if (has_type ()) + // type (i.e. not ref, no lifetime) + std::string str; + + if (is_mut ()) { - // type (i.e. not ref, no lifetime) - std::string str; + str += "mut "; + } - if (is_mut ()) - { - str += "mut "; - } + str += "self : "; - str += "self : "; + str += type->as_string (); - str += type->as_string (); + return str; + } + else if (has_lifetime ()) + { + // ref and lifetime + std::string str = "&" + get_lifetime ().as_string () + " "; - return str; - } - else if (has_lifetime ()) + if (is_mut ()) { - // ref and lifetime - std::string str = "&" + lifetime.as_string () + " "; + str += "mut "; + } - if (is_mut ()) - { - str += "mut "; - } + str += "self"; - str += "self"; + return str; + } + else if (is_ref ()) + { + // ref with no lifetime + std::string str = "&"; - return str; - } - else if (is_ref ()) + if (is_mut ()) { - // ref with no lifetime - std::string str = "&"; + str += " mut "; + } - if (is_mut ()) - { - str += " mut "; - } + str += "self"; - str += "self"; + return str; + } + else + { + // no ref, no type + std::string str; - return str; - } - else + if (is_mut ()) { - // no ref, no type - std::string str; - - if (is_mut ()) - { - str += "mut "; - } + str += "mut "; + } - str += "self"; + str += "self"; - return str; - } + return str; } } @@ -3834,6 +3924,17 @@ InlineAsm::accept_vis (HIRFullVisitor &vis) } void +LlvmInlineAsm::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} +void +LlvmInlineAsm::accept_vis (HIRExpressionVisitor &vis) +{ + vis.visit (*this); +} + +void BorrowExpr::accept_vis (HIRExpressionVisitor &vis) { vis.visit (*this); @@ -4056,6 +4157,18 @@ BlockExpr::accept_vis (HIRFullVisitor &vis) } void +AnonConst::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void ContinueExpr::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); @@ -4428,13 +4541,13 @@ StructPattern::accept_vis (HIRFullVisitor &vis) } void -TupleStructItemsNoRange::accept_vis (HIRFullVisitor &vis) +TupleStructItemsNoRest::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); } void -TupleStructItemsRange::accept_vis (HIRFullVisitor &vis) +TupleStructItemsHasRest::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); } @@ -4446,13 +4559,13 @@ TupleStructPattern::accept_vis (HIRFullVisitor &vis) } void -TuplePatternItemsMultiple::accept_vis (HIRFullVisitor &vis) +TuplePatternItemsNoRest::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); } void -TuplePatternItemsRanged::accept_vis (HIRFullVisitor &vis) +TuplePatternItemsHasRest::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); } @@ -4464,6 +4577,18 @@ TuplePattern::accept_vis (HIRFullVisitor &vis) } void +SlicePatternItemsNoRest::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void +SlicePatternItemsHasRest::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void SlicePattern::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); @@ -5028,6 +5153,18 @@ BlockExpr::accept_vis (HIRExpressionVisitor &vis) } void +AnonConst::accept_vis (HIRExpressionVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (HIRExpressionVisitor &vis) +{ + vis.visit (*this); +} + +void Function::accept_vis (HIRStmtVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt index 9cdbce2..d9824f1 100644 --- a/gcc/rust/lang.opt +++ b/gcc/rust/lang.opt @@ -205,7 +205,7 @@ EnumValue Enum(frust_compile_until) String(end) Value(13) frust-name-resolution-2.0 -Rust Var(flag_name_resolution_2_0) +Rust Var(flag_name_resolution_2_0) Init(1) Use the temporary and experimental name resolution pipeline instead of the stable one frust-borrowcheck @@ -229,4 +229,8 @@ frust-overflow-checks Rust Var(flag_overflow_checks) Init(1) Enable the overflow checks in code generation +frust-assume-builtin-offset-of +Rust Var(flag_assume_builtin_offset_of) +Define a built-in offset_of macro in the compiler and assume it is present + ; This comment is to ensure we retain the blank line above. 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 b143e70..a99b5ed 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -236,10 +236,11 @@ Lexer::dump_and_skip (int n) out << "<id="; out << tok->token_id_to_str (); - out << (tok->has_str () ? (std::string (", text=") + tok->get_str () - + std::string (", typehint=") - + std::string (tok->get_type_hint_str ())) - : "") + out << (tok->should_have_str () + ? (std::string (", text=") + tok->get_str () + + std::string (", typehint=") + + std::string (tok->get_type_hint_str ())) + : "") << " "; out << Linemap::location_to_string (loc) << '\n'; } @@ -1317,7 +1318,8 @@ Lexer::parse_escape (char opening_char) switch (current_char.value) { - case 'x': { + case 'x': + { auto hex_escape_pair = parse_partial_hex_escape (); long hexLong = hex_escape_pair.first; additional_length_offset += hex_escape_pair.second; @@ -1400,7 +1402,8 @@ Lexer::parse_utf8_escape () switch (current_char.value) { - case 'x': { + case 'x': + { auto hex_escape_pair = parse_partial_hex_escape (); long hexLong = hex_escape_pair.first; additional_length_offset += hex_escape_pair.second; @@ -1438,7 +1441,8 @@ Lexer::parse_utf8_escape () case '"': output_char = '"'; break; - case 'u': { + case 'u': + { auto unicode_escape_pair = parse_partial_unicode_escape (); output_char = unicode_escape_pair.first; additional_length_offset += unicode_escape_pair.second; @@ -1894,6 +1898,11 @@ Lexer::parse_raw_byte_string (location_t loc) break; } } + else if (current_char.is_eof ()) + { + rust_error_at (string_begin_locus, "unended raw byte string literal"); + return Token::make (END_OF_FILE, get_current_location ()); + } else if (current_char.value > 127) { rust_error_at (get_current_location (), @@ -1901,11 +1910,6 @@ Lexer::parse_raw_byte_string (location_t loc) current_char.as_string ().c_str ()); current_char = 0; } - else if (current_char.is_eof ()) - { - rust_error_at (string_begin_locus, "unended raw byte string literal"); - return Token::make (END_OF_FILE, get_current_location ()); - } length++; current_column++; @@ -2635,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/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h index 10293e0..383ffac 100644 --- a/gcc/rust/lex/rust-lex.h +++ b/gcc/rust/lex/rust-lex.h @@ -263,8 +263,7 @@ private: #if CHECKING_P namespace selftest { -void -rust_input_source_test (); +void rust_input_source_test (); } // namespace selftest diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index 8493889..43682af 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -20,6 +20,7 @@ #include "rust-token.h" #include "rust-diagnostics.h" #include "rust-unicode.h" +#include "rust-ast.h" namespace Rust { // Hackily defined way to get token description for enum value using x-macros @@ -88,7 +89,8 @@ token_id_keyword_string (TokenId id) switch (id) { #define RS_TOKEN_KEYWORD_2015(id, str_ptr) \ - case id: { \ + case id: \ + { \ static const std::string str (str_ptr); \ return str; \ } \ @@ -176,29 +178,6 @@ nfc_normalize_token_string (location_t loc, TokenId id, const std::string &str) return str; } -const std::string & -Token::get_str () const -{ - if (token_id_is_keyword (token_id)) - return token_id_keyword_string (token_id); - - // FIXME: attempt to return null again - // gcc_assert(str != NULL); - - // HACK: allow referencing an empty string - static const std::string empty = ""; - - if (str == NULL) - { - rust_error_at (get_locus (), - "attempted to get string for %qs, which has no string. " - "returning empty string instead", - get_token_description ()); - return empty; - } - return *str; -} - namespace { enum class Context { @@ -234,6 +213,13 @@ escape_special_chars (const std::string &source, Context ctx) } // namespace +TokenPtr +Token::make_identifier (const Identifier &ident) +{ + std::string str = ident; + return make_identifier (ident.get_locus (), std::move (str)); +} + std::string Token::as_string () const { diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index c683ecd..71a7503 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -22,8 +22,13 @@ #include "rust-system.h" #include "rust-linemap.h" #include "rust-unicode.h" +#include "rust-diagnostics.h" namespace Rust { + +// used by Rust::Token::make_identifier +class Identifier; + // "Primitive core types" in Rust - the different int and float types, as well // as some others enum PrimitiveCoreType @@ -221,25 +226,20 @@ typedef std::shared_ptr<Token> TokenPtr; typedef std::shared_ptr<const Token> const_TokenPtr; // Hackily defined way to get token description for enum value using x-macros -const char * -get_token_description (TokenId id); +const char *get_token_description (TokenId id); /* Hackily defined way to get token description as a string for enum value using * x-macros */ -const char * -token_id_to_str (TokenId id); +const char *token_id_to_str (TokenId id); /* checks if a token is a keyword */ -bool -token_id_is_keyword (TokenId id); +bool token_id_is_keyword (TokenId id); /* gets the string associated with a keyword */ -const std::string & -token_id_keyword_string (TokenId id); +const std::string &token_id_keyword_string (TokenId id); // Get type hint description as a string. -const char * -get_type_hint_string (PrimitiveCoreType type); +const char *get_type_hint_string (PrimitiveCoreType type); /* Normalize string if a token is a identifier */ -std::string -nfc_normalize_token_string (location_t loc, TokenId id, const std::string &str); +std::string nfc_normalize_token_string (location_t loc, TokenId id, + const std::string &str); // Represents a single token. Create using factory static methods. class Token @@ -250,7 +250,7 @@ private: // Token location. location_t locus; // Associated text (if any) of token. - std::unique_ptr<std::string> str; + std::string str; // TODO: maybe remove issues and just store std::string as value? /* Type hint for token based on lexer data (e.g. type suffix). Does not exist * for most tokens. */ @@ -258,23 +258,21 @@ private: // Token constructor from token id and location. Has a null string. Token (TokenId token_id, location_t location) - : token_id (token_id), locus (location), str (nullptr), - type_hint (CORETYPE_UNKNOWN) + : token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN) {} // Token constructor from token id, location, and a string. - Token (TokenId token_id, location_t location, std::string &¶mStr) + Token (TokenId token_id, location_t location, std::string paramStr) : token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN) { // Normalize identifier tokens - str = std::make_unique<std::string> ( - nfc_normalize_token_string (location, token_id, paramStr)); + str = nfc_normalize_token_string (location, token_id, std::move (paramStr)); } // Token constructor from token id, location, and a char. Token (TokenId token_id, location_t location, char paramChar) - : token_id (token_id), locus (location), - str (new std::string (1, paramChar)), type_hint (CORETYPE_UNKNOWN) + : token_id (token_id), locus (location), str (1, paramChar), + type_hint (CORETYPE_UNKNOWN) { // Do not need to normalize 1byte char } @@ -284,19 +282,17 @@ private: : token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN) { // Normalize identifier tokens - str = std::make_unique<std::string> ( - nfc_normalize_token_string (location, token_id, - paramCodepoint.as_string ())); + str = nfc_normalize_token_string (location, token_id, + paramCodepoint.as_string ()); } // Token constructor from token id, location, a string, and type hint. - Token (TokenId token_id, location_t location, std::string &¶mStr, + Token (TokenId token_id, location_t location, std::string paramStr, PrimitiveCoreType parType) : token_id (token_id), locus (location), type_hint (parType) { // Normalize identifier tokens - str = std::make_unique<std::string> ( - nfc_normalize_token_string (location, token_id, paramStr)); + str = nfc_normalize_token_string (location, token_id, std::move (paramStr)); } public: @@ -323,14 +319,16 @@ public: } // Makes and returns a new TokenPtr of type IDENTIFIER. - static TokenPtr make_identifier (location_t locus, std::string &&str) + static TokenPtr make_identifier (location_t locus, std::string str) { // return std::make_shared<Token> (IDENTIFIER, locus, str); return TokenPtr (new Token (IDENTIFIER, locus, std::move (str))); } + static TokenPtr make_identifier (const Identifier &ident); + // Makes and returns a new TokenPtr of type INT_LITERAL. - static TokenPtr make_int (location_t locus, std::string &&str, + static TokenPtr make_int (location_t locus, std::string str, PrimitiveCoreType type_hint = CORETYPE_UNKNOWN) { // return std::make_shared<Token> (INT_LITERAL, locus, str, type_hint); @@ -339,7 +337,7 @@ public: } // Makes and returns a new TokenPtr of type FLOAT_LITERAL. - static TokenPtr make_float (location_t locus, std::string &&str, + static TokenPtr make_float (location_t locus, std::string str, PrimitiveCoreType type_hint = CORETYPE_UNKNOWN) { // return std::make_shared<Token> (FLOAT_LITERAL, locus, str, type_hint); @@ -348,7 +346,7 @@ public: } // Makes and returns a new TokenPtr of type STRING_LITERAL. - static TokenPtr make_string (location_t locus, std::string &&str) + static TokenPtr make_string (location_t locus, std::string str) { // return std::make_shared<Token> (STRING_LITERAL, locus, str, // CORETYPE_STR); @@ -371,32 +369,32 @@ public: } // Makes and returns a new TokenPtr of type BYTE_STRING_LITERAL (fix). - static TokenPtr make_byte_string (location_t locus, std::string &&str) + static TokenPtr make_byte_string (location_t locus, std::string str) { // return std::make_shared<Token> (BYTE_STRING_LITERAL, locus, str); return TokenPtr (new Token (BYTE_STRING_LITERAL, locus, std::move (str))); } // Makes and returns a new TokenPtr of type RAW_STRING_LITERAL. - static TokenPtr make_raw_string (location_t locus, std::string &&str) + static TokenPtr make_raw_string (location_t locus, std::string str) { return TokenPtr (new Token (RAW_STRING_LITERAL, locus, std::move (str))); } // Makes and returns a new TokenPtr of type INNER_DOC_COMMENT. - static TokenPtr make_inner_doc_comment (location_t locus, std::string &&str) + static TokenPtr make_inner_doc_comment (location_t locus, std::string str) { return TokenPtr (new Token (INNER_DOC_COMMENT, locus, std::move (str))); } // Makes and returns a new TokenPtr of type OUTER_DOC_COMMENT. - static TokenPtr make_outer_doc_comment (location_t locus, std::string &&str) + static TokenPtr make_outer_doc_comment (location_t locus, std::string str) { return TokenPtr (new Token (OUTER_DOC_COMMENT, locus, std::move (str))); } // Makes and returns a new TokenPtr of type LIFETIME. - static TokenPtr make_lifetime (location_t locus, std::string &&str) + static TokenPtr make_lifetime (location_t locus, std::string str) { // return std::make_shared<Token> (LIFETIME, locus, str); return TokenPtr (new Token (LIFETIME, locus, std::move (str))); @@ -412,16 +410,18 @@ public: void set_locus (location_t locus) { this->locus = locus; } // Gets string description of the token. - const std::string & - get_str () const; /*{ -// FIXME: put in header again when fix null problem -//gcc_assert(str != nullptr); -if (str == nullptr) { -error_at(get_locus(), "attempted to get string for '%s', which has no string. -returning empty string instead.", get_token_description()); return ""; -} -return *str; -}*/ + const std::string &get_str () const + { + if (token_id_is_keyword (token_id)) + return token_id_keyword_string (token_id); + + if (!should_have_str ()) + rust_internal_error_at ( + locus, "attempting to get string for %qs, which should have no string", + get_token_description ()); + + return str; + } // Gets token's type hint info. PrimitiveCoreType get_type_hint () const @@ -463,14 +463,11 @@ return *str; } } - /* Returns whether the token actually has a string (regardless of whether it - * should or not). */ - bool has_str () const { return str != nullptr; } - // Returns whether the token should have a string. bool should_have_str () const { - return is_literal () || token_id == IDENTIFIER || token_id == LIFETIME; + return is_literal () || token_id == IDENTIFIER || token_id == LIFETIME + || token_id == INNER_DOC_COMMENT || token_id == OUTER_DOC_COMMENT; } // Returns whether the token is a pure decimal int literal diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc index 771bec6..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" @@ -91,8 +92,8 @@ ExportContext::emit_function (const HIR::Function &fn) AST::Function &function = static_cast<AST::Function &> (vis_item); std::vector<std::unique_ptr<AST::ExternalItem>> external_items; - external_items.push_back (std::unique_ptr<AST::ExternalItem> ( - static_cast<AST::ExternalItem *> (&function))); + external_items.emplace_back ( + static_cast<AST::ExternalItem *> (&function)); AST::ExternBlock extern_block (get_string_from_abi (Rust::ABI::RUST), std::move (external_items), @@ -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); } @@ -263,8 +262,7 @@ PublicInterface::write_to_path (const std::string &path) const FILE *nfd = fopen (path.c_str (), "wb"); if (nfd == NULL) { - rust_error_at (UNDEF_LOCATION, - "failed to open file %qs for writing: %s", + rust_error_at (UNDEF_LOCATION, "failed to open file %qs for writing: %s", path.c_str (), xstrerror (errno)); return; } 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/metadata/rust-import-archive.cc b/gcc/rust/metadata/rust-import-archive.cc index cf24607..f64de4e 100644 --- a/gcc/rust/metadata/rust-import-archive.cc +++ b/gcc/rust/metadata/rust-import-archive.cc @@ -683,7 +683,7 @@ public: const Header &operator* () const { return this->header_; } - const Header *operator-> () const { return &this->header_; } + const Header *operator->() const { return &this->header_; } Archive_iterator &operator++ () { diff --git a/gcc/rust/metadata/rust-imports.h b/gcc/rust/metadata/rust-imports.h index a497c67..65a2af1 100644 --- a/gcc/rust/metadata/rust-imports.h +++ b/gcc/rust/metadata/rust-imports.h @@ -11,8 +11,7 @@ namespace Rust { -extern void -add_search_path (const std::string &path); +extern void add_search_path (const std::string &path); class Import { diff --git a/gcc/rust/parse/rust-cfg-parser.h b/gcc/rust/parse/rust-cfg-parser.h index 0d64016..61db240 100644 --- a/gcc/rust/parse/rust-cfg-parser.h +++ b/gcc/rust/parse/rust-cfg-parser.h @@ -36,15 +36,14 @@ namespace Rust { * * @return false if the given input was invalid, true otherwise */ -bool -parse_cfg_option (std::string &input, std::string &key, std::string &value); +bool parse_cfg_option (std::string &input, std::string &key, + std::string &value); } // namespace Rust #if CHECKING_P namespace selftest { -extern void -rust_cfg_parser_test (void); +extern void rust_cfg_parser_test (void); } // namespace selftest #endif // CHECKING_P diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/parse/rust-parse-impl-lexer.cc index 2703438..fec91e8 100644 --- a/gcc/rust/ast/rust-macro.cc +++ b/gcc/rust/parse/rust-parse-impl-lexer.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -16,10 +16,10 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#include "rust-macro.h" +#include "rust-parse-impl.h" namespace Rust { -namespace AST { -} // namespace AST +template class Parser<Lexer>; + } // namespace Rust diff --git a/gcc/rust/parse/rust-parse-impl-macro.cc b/gcc/rust/parse/rust-parse-impl-macro.cc new file mode 100644 index 0000000..e632887 --- /dev/null +++ b/gcc/rust/parse/rust-parse-impl-macro.cc @@ -0,0 +1,26 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-parse-impl.h" +#include "rust-macro-invoc-lexer.h" + +namespace Rust { + +template class Parser<MacroInvocLexer>; + +} // namespace Rust diff --git a/gcc/rust/parse/rust-parse-impl-proc-macro.cc b/gcc/rust/parse/rust-parse-impl-proc-macro.cc new file mode 100644 index 0000000..edc484f --- /dev/null +++ b/gcc/rust/parse/rust-parse-impl-proc-macro.cc @@ -0,0 +1,34 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-parse-impl.h" +#include "rust-proc-macro-invoc-lexer.h" + +namespace Rust { + +template std::unique_ptr<AST::Item> +Parser<ProcMacroInvocLexer>::parse_item (bool); + +template std::unique_ptr<AST::Stmt> + Parser<ProcMacroInvocLexer>::parse_stmt (ParseRestrictions); + +// instantiate entire class (or just more functions) if necessary + +// template class Parser<ProcMacroInvocLexer>; + +} // namespace Rust diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 71d7250..6cb8f0e 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -19,13 +19,17 @@ /* Template implementation for Rust::Parser. Previously in rust-parse.cc (before * Parser was template). Separated from rust-parse.h for readability. */ -/* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h +/* DO NOT INCLUDE ANYWHERE - this is automatically included + * by rust-parse-impl-*.cc * This is also the reason why there are no include guards. */ +#include "expected.h" +#include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" #include "rust-item.h" #include "rust-common.h" +#include "rust-parse.h" #include "rust-token.h" #define INCLUDE_ALGORITHM #include "rust-diagnostics.h" @@ -227,19 +231,22 @@ Parser<ManagedTokenSource>::skip_generics_right_angle () // this is good - skip token lexer.skip_token (); return true; - case RIGHT_SHIFT: { + case RIGHT_SHIFT: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, RIGHT_ANGLE); lexer.skip_token (); return true; } - case GREATER_OR_EQUAL: { + case GREATER_OR_EQUAL: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, EQUAL); lexer.skip_token (); return true; } - case RIGHT_SHIFT_EQ: { + case RIGHT_SHIFT_EQ: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, GREATER_OR_EQUAL); lexer.skip_token (); @@ -424,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; @@ -651,10 +654,7 @@ Parser<ManagedTokenSource>::parse_simple_path () // Parse all other simple path segments while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION) { - // Skip scope resolution operator - lexer.skip_token (); - - AST::SimplePathSegment new_segment = parse_simple_path_segment (); + AST::SimplePathSegment new_segment = parse_simple_path_segment (1); // Return path as currently constructed if segment in error state. if (new_segment.is_error ()) @@ -682,35 +682,36 @@ Parser<ManagedTokenSource>::parse_simple_path () } /* Parses a single SimplePathSegment (does not handle the scope resolution - * operators) */ + * operators) + * Starts parsing at an offset of base_peek */ template <typename ManagedTokenSource> AST::SimplePathSegment -Parser<ManagedTokenSource>::parse_simple_path_segment () +Parser<ManagedTokenSource>::parse_simple_path_segment (int base_peek) { using namespace Values; - const_TokenPtr t = lexer.peek_token (); + const_TokenPtr t = lexer.peek_token (base_peek); switch (t->get_id ()) { case IDENTIFIER: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (t->get_str (), t->get_locus ()); case SUPER: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::SUPER, t->get_locus ()); case SELF: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::SELF, t->get_locus ()); case CRATE: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::CRATE, t->get_locus ()); case DOLLAR_SIGN: - if (lexer.peek_token (1)->get_id () == CRATE) + if (lexer.peek_token (base_peek + 1)->get_id () == CRATE) { - lexer.skip_token (1); + lexer.skip_token (base_peek + 1); return AST::SimplePathSegment ("$crate", t->get_locus ()); } @@ -790,7 +791,8 @@ Parser<ManagedTokenSource>::parse_attr_input () { case LEFT_PAREN: case LEFT_SQUARE: - case LEFT_CURLY: { + case LEFT_CURLY: + { // must be a delimited token tree, so parse that std::unique_ptr<AST::AttrInput> input_tree ( new AST::DelimTokenTree (parse_delim_token_tree ())); @@ -799,7 +801,8 @@ Parser<ManagedTokenSource>::parse_attr_input () return input_tree; } - case EQUAL: { + case EQUAL: + { // = LiteralExpr lexer.skip_token (); @@ -877,7 +880,10 @@ Parser<ManagedTokenSource>::parse_attr_input () return attr_input_lit; } break; + case RIGHT_PAREN: case RIGHT_SQUARE: + case RIGHT_CURLY: + case END_OF_FILE: // means AttrInput is missing, which is allowed return nullptr; default: @@ -972,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)); @@ -1043,6 +1040,7 @@ Parser<ManagedTokenSource>::parse_identifier_or_keyword_token () } else { + add_error (Error (t->get_locus (), "expected keyword or identifier")); return nullptr; } } @@ -1068,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; @@ -1706,10 +1705,9 @@ Parser<ManagedTokenSource>::parse_decl_macro_def (AST::Visibility vis, return nullptr; } - AST::MacroRule macro_rule - = AST::MacroRule (std::move (matcher), std::move (transcriber), locus); std::vector<AST::MacroRule> macro_rules; - macro_rules.push_back (macro_rule); + macro_rules.emplace_back (std::move (matcher), std::move (transcriber), + locus); return std::unique_ptr<AST::MacroRulesDefinition> ( AST::MacroRulesDefinition::decl_macro (std::move (rule_name), @@ -1851,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)); @@ -2117,7 +2108,8 @@ Parser<ManagedTokenSource>::parse_macro_match () { case LEFT_PAREN: case LEFT_SQUARE: - case LEFT_CURLY: { + case LEFT_CURLY: + { // must be macro matcher as delimited AST::MacroMatcher matcher = parse_macro_matcher (); if (matcher.is_error ()) @@ -2131,7 +2123,8 @@ Parser<ManagedTokenSource>::parse_macro_match () return std::unique_ptr<AST::MacroMatcher> ( new AST::MacroMatcher (std::move (matcher))); } - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // have to do more lookahead to determine if fragment or repetition const_TokenPtr t2 = lexer.peek_token (1); switch (t2->get_id ()) @@ -2402,7 +2395,8 @@ Parser<ManagedTokenSource>::parse_visibility () skip_token (RIGHT_PAREN); return AST::Visibility::create_super (path_loc, vis_loc); - case IN: { + case IN: + { lexer.skip_token (); // parse the "in" path as well @@ -2466,7 +2460,8 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis, new AST::Module (std::move (name), std::move (vis), std::move (outer_attrs), locus, safety, lexer.get_filename (), inline_module_stack)); - case LEFT_CURLY: { + case LEFT_CURLY: + { lexer.skip_token (); // parse inner attributes @@ -2730,7 +2725,8 @@ Parser<ManagedTokenSource>::parse_use_tree () return std::unique_ptr<AST::UseTreeGlob> ( new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH, AST::SimplePath::create_empty (), locus)); - case LEFT_CURLY: { + case LEFT_CURLY: + { // nested tree UseTree type lexer.skip_token (); @@ -2794,58 +2790,12 @@ Parser<ManagedTokenSource>::parse_use_tree () } else { - /* Due to aforementioned implementation issues, the trailing :: token is - * consumed by the path, so it can not be used as a disambiguator. - * NOPE, not true anymore - TODO what are the consequences of this? */ - const_TokenPtr t = lexer.peek_token (); + switch (t->get_id ()) { - case ASTERISK: - // glob UseTree type - lexer.skip_token (); - - return std::unique_ptr<AST::UseTreeGlob> ( - new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, - std::move (path), locus)); - case LEFT_CURLY: { - // nested tree UseTree type - lexer.skip_token (); - - std::vector<std::unique_ptr<AST::UseTree>> use_trees; - - // TODO: think of better control structure - const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_CURLY) - { - std::unique_ptr<AST::UseTree> use_tree = parse_use_tree (); - if (use_tree == nullptr) - { - break; - } - - use_trees.push_back (std::move (use_tree)); - - if (lexer.peek_token ()->get_id () != COMMA) - break; - - lexer.skip_token (); - t = lexer.peek_token (); - } - - // skip end curly delimiter - if (!skip_token (RIGHT_CURLY)) - { - // skip after somewhere? - return nullptr; - } - - return std::unique_ptr<AST::UseTreeList> ( - new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED, - std::move (path), std::move (use_trees), - locus)); - } - case AS: { + case AS: + { // rebind UseTree type lexer.skip_token (); @@ -2884,16 +2834,72 @@ Parser<ManagedTokenSource>::parse_use_tree () // don't skip semicolon - handled in parse_use_tree // lexer.skip_token(); - - return std::unique_ptr<AST::UseTreeRebind> ( - new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path), - locus)); case COMMA: case RIGHT_CURLY: // this may occur in recursive calls - assume it is ok and ignore it return std::unique_ptr<AST::UseTreeRebind> ( new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path), locus)); + case SCOPE_RESOLUTION: + // keep going + break; + default: + add_error (Error (t->get_locus (), + "unexpected token %qs in use tree with valid path", + t->get_token_description ())); + return nullptr; + } + + skip_token (); + t = lexer.peek_token (); + + switch (t->get_id ()) + { + case ASTERISK: + // glob UseTree type + lexer.skip_token (); + + return std::unique_ptr<AST::UseTreeGlob> ( + new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, + std::move (path), locus)); + case LEFT_CURLY: + { + // nested tree UseTree type + lexer.skip_token (); + + std::vector<std::unique_ptr<AST::UseTree>> use_trees; + + // TODO: think of better control structure + const_TokenPtr t = lexer.peek_token (); + while (t->get_id () != RIGHT_CURLY) + { + std::unique_ptr<AST::UseTree> use_tree = parse_use_tree (); + if (use_tree == nullptr) + { + break; + } + + use_trees.push_back (std::move (use_tree)); + + if (lexer.peek_token ()->get_id () != COMMA) + break; + + lexer.skip_token (); + t = lexer.peek_token (); + } + + // skip end curly delimiter + if (!skip_token (RIGHT_CURLY)) + { + // skip after somewhere? + return nullptr; + } + + return std::unique_ptr<AST::UseTreeList> ( + new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED, + std::move (path), std::move (use_trees), + locus)); + } default: add_error (Error (t->get_locus (), "unexpected token %qs in use tree with valid path", @@ -2985,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> ( @@ -3100,9 +3107,10 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) switch (token->get_id ()) { - case LIFETIME: { + case LIFETIME: + { auto lifetime = parse_lifetime (false); - if (lifetime.is_error ()) + if (!lifetime) { rust_error_at ( token->get_locus (), @@ -3122,11 +3130,12 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) } param = std::unique_ptr<AST::LifetimeParam> (new AST::LifetimeParam ( - std::move (lifetime), std::move (lifetime_bounds), + std::move (lifetime.value ()), std::move (lifetime_bounds), std::move (outer_attrs), token->get_locus ())); break; } - case IDENTIFIER: { + case IDENTIFIER: + { auto type_ident = token->get_str (); lexer.skip_token (); @@ -3161,7 +3170,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) std::move (outer_attrs))); break; } - case CONST: { + case CONST: + { lexer.skip_token (); auto name_token = expect_token (IDENTIFIER); @@ -3174,24 +3184,28 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) return nullptr; // optional default value - auto default_expr = AST::GenericArg::create_error (); + tl::optional<AST::GenericArg> default_expr = tl::nullopt; if (lexer.peek_token ()->get_id () == EQUAL) { lexer.skip_token (); auto tok = lexer.peek_token (); default_expr = parse_generic_arg (); - if (default_expr.is_error ()) - rust_error_at (tok->get_locus (), - "invalid token for start of default value for " - "const generic parameter: expected %<block%>, " - "%<identifier%> or %<literal%>, got %qs", - token_id_to_str (tok->get_id ())); + if (!default_expr) + { + rust_error_at (tok->get_locus (), + "invalid token for start of default value for " + "const generic parameter: expected %<block%>, " + "%<identifier%> or %<literal%>, got %qs", + token_id_to_str (tok->get_id ())); + return nullptr; + } // At this point, we *know* that we are parsing a const // expression - if (default_expr.get_kind () == AST::GenericArg::Kind::Either) - default_expr = default_expr.disambiguate_to_const (); + if (default_expr.value ().get_kind () + == AST::GenericArg::Kind::Either) + default_expr = default_expr.value ().disambiguate_to_const (); } param = std::unique_ptr<AST::ConstGenericParam> ( @@ -3230,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 ())) @@ -3239,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); @@ -3261,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; @@ -3276,16 +3318,16 @@ Parser<ManagedTokenSource>::parse_lifetime_params () while (lexer.peek_token ()->get_id () != END_OF_FILE) { - AST::LifetimeParam lifetime_param = parse_lifetime_param (); + auto lifetime_param = parse_lifetime_param (); - if (lifetime_param.is_error ()) + if (!lifetime_param) { // can't treat as error as only way to get out with trailing comma break; } - lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> ( - new AST::LifetimeParam (std::move (lifetime_param)))); + lifetime_params.emplace_back ( + new AST::LifetimeParam (std::move (lifetime_param.value ()))); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3311,9 +3353,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token) // if end_token is not specified, it defaults to EOF, so should work fine while (!is_end_token (lexer.peek_token ()->get_id ())) { - AST::LifetimeParam lifetime_param = parse_lifetime_param (); + auto lifetime_param = parse_lifetime_param (); - if (lifetime_param.is_error ()) + if (!lifetime_param) { /* TODO: is it worth throwing away all lifetime params just because * one failed? */ @@ -3324,8 +3366,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token) return {}; } - lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> ( - new AST::LifetimeParam (std::move (lifetime_param)))); + lifetime_params.emplace_back ( + new AST::LifetimeParam (std::move (lifetime_param))); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3341,7 +3383,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token) /* Parses lifetime generic parameters (objects). Will also consume any * trailing comma. No extra checks for end token. - * TODO: is this best solution? implements most of the same algorithm. */ + * TODO: is this best solution? implements most of the same algorithm. + * TODO: seems to be unused, remove? */ template <typename ManagedTokenSource> std::vector<AST::LifetimeParam> Parser<ManagedTokenSource>::parse_lifetime_params_objs () @@ -3351,15 +3394,15 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs () // bad control structure as end token cannot be guaranteed while (true) { - AST::LifetimeParam lifetime_param = parse_lifetime_param (); + auto lifetime_param = parse_lifetime_param (); - if (lifetime_param.is_error ()) + if (!lifetime_param) { // not an error as only way to exit if trailing comma break; } - lifetime_params.push_back (std::move (lifetime_param)); + lifetime_params.push_back (std::move (lifetime_param.value ())); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3386,9 +3429,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ( while (!is_end_token (lexer.peek_token ()->get_id ())) { - AST::LifetimeParam lifetime_param = parse_lifetime_param (); + auto lifetime_param = parse_lifetime_param (); - if (lifetime_param.is_error ()) + if (!lifetime_param) { /* TODO: is it worth throwing away all lifetime params just because * one failed? */ @@ -3399,7 +3442,7 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ( return {}; } - lifetime_params.push_back (std::move (lifetime_param)); + lifetime_params.push_back (std::move (lifetime_param.value ())); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3458,7 +3501,7 @@ Parser<ManagedTokenSource>::parse_non_ptr_sequence ( /* Parses a single lifetime generic parameter (not including comma). */ template <typename ManagedTokenSource> -AST::LifetimeParam +tl::expected<AST::LifetimeParam, ParseLifetimeParamError> Parser<ManagedTokenSource>::parse_lifetime_param () { // parse outer attributes, which are optional and may not exist @@ -3468,8 +3511,8 @@ Parser<ManagedTokenSource>::parse_lifetime_param () const_TokenPtr lifetime_tok = lexer.peek_token (); if (lifetime_tok->get_id () != LIFETIME) { - // if lifetime is missing, must not be a lifetime param, so return null - return AST::LifetimeParam::create_error (); + // if lifetime is missing, must not be a lifetime param, so return error + return tl::make_unexpected<ParseLifetimeParamError> ({}); } lexer.skip_token (); AST::Lifetime lifetime (AST::Lifetime::NAMED, lifetime_tok->get_str (), @@ -3815,12 +3858,13 @@ template <typename ManagedTokenSource> std::unique_ptr<AST::LifetimeWhereClauseItem> Parser<ManagedTokenSource>::parse_lifetime_where_clause_item () { - AST::Lifetime lifetime = parse_lifetime (false); - if (lifetime.is_error ()) + auto parsed_lifetime = parse_lifetime (false); + if (!parsed_lifetime) { // TODO: error here? return nullptr; } + auto lifetime = parsed_lifetime.value (); if (!skip_token (COLON)) { @@ -4013,7 +4057,7 @@ Parser<ManagedTokenSource>::parse_type_param_bound () { case LIFETIME: return std::unique_ptr<AST::Lifetime> ( - new AST::Lifetime (parse_lifetime (false))); + new AST::Lifetime (parse_lifetime (false).value ())); case LEFT_PAREN: case QUESTION_MARK: case FOR: @@ -4086,13 +4130,13 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds () while (true) { - AST::Lifetime lifetime = parse_lifetime (false); + auto lifetime = parse_lifetime (false); // quick exit for parsing failure - if (lifetime.is_error ()) + if (!lifetime) break; - lifetime_bounds.push_back (std::move (lifetime)); + lifetime_bounds.push_back (std::move (lifetime.value ())); /* plus is maybe not allowed at end - spec defines it weirdly, so * assuming allowed at end */ @@ -4116,9 +4160,9 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token) while (!is_end_token (lexer.peek_token ()->get_id ())) { - AST::Lifetime lifetime = parse_lifetime (false); + auto lifetime = parse_lifetime (false); - if (lifetime.is_error ()) + if (!lifetime) { /* TODO: is it worth throwing away all lifetime bound info just * because one failed? */ @@ -4129,7 +4173,7 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token) return {}; } - lifetime_bounds.push_back (std::move (lifetime)); + lifetime_bounds.push_back (std::move (lifetime.value ())); /* plus is maybe not allowed at end - spec defines it weirdly, so * assuming allowed at end */ @@ -4146,14 +4190,20 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token) /* Parses a lifetime token (named, 'static, or '_). Also handles lifetime not * existing. */ template <typename ManagedTokenSource> -AST::Lifetime +tl::expected<AST::Lifetime, ParseLifetimeError> Parser<ManagedTokenSource>::parse_lifetime (bool allow_elided) { const_TokenPtr lifetime_tok = lexer.peek_token (); if (lifetime_tok->get_id () != LIFETIME) { - return (allow_elided) ? AST::Lifetime::elided () - : AST::Lifetime::error (); + if (allow_elided) + { + return AST::Lifetime::elided (); + } + else + { + return tl::make_unexpected<ParseLifetimeError> ({}); + } } lexer.skip_token (); @@ -4345,7 +4395,8 @@ Parser<ManagedTokenSource>::parse_struct (AST::Visibility vis, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct with body // skip curly bracket @@ -4748,7 +4799,8 @@ Parser<ManagedTokenSource>::parse_enum_item () const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple enum item lexer.skip_token (); @@ -4769,7 +4821,8 @@ Parser<ManagedTokenSource>::parse_enum_item () std::move (item_name), std::move (vis), std::move (tuple_fields), std::move (outer_attrs), item_name_tok->get_locus ())); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct enum item lexer.skip_token (); @@ -4786,7 +4839,8 @@ Parser<ManagedTokenSource>::parse_enum_item () std::move (item_name), std::move (vis), std::move (struct_fields), std::move (outer_attrs), item_name_tok->get_locus ())); } - case EQUAL: { + case EQUAL: + { // discriminant enum item lexer.skip_token (); @@ -5149,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 @@ -5169,13 +5230,14 @@ 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. template <typename ManagedTokenSource> -std::unique_ptr<AST::TraitItemConst> +std::unique_ptr<AST::ConstantItem> Parser<ManagedTokenSource>::parse_trait_const (AST::AttrVec outer_attrs) { location_t locus = lexer.peek_token ()->get_locus (); @@ -5213,10 +5275,9 @@ Parser<ManagedTokenSource>::parse_trait_const (AST::AttrVec outer_attrs) return nullptr; } - return std::unique_ptr<AST::TraitItemConst> ( - new AST::TraitItemConst (std::move (ident), std::move (type), - std::move (const_body), std::move (outer_attrs), - locus)); + return std::unique_ptr<AST::ConstantItem> (new AST::ConstantItem ( + std::move (ident), AST::Visibility::create_private (), std::move (type), + std::move (const_body), std::move (outer_attrs), locus)); } /* Parses a struct "impl" item (both inherent impl and trait impl can be @@ -5439,7 +5500,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item () case SUPER: case SELF: case CRATE: - case PUB: { + case PUB: + { // visibility, so not a macro invocation semi - must be constant, // function, or method AST::Visibility vis = parse_visibility (); @@ -5570,7 +5632,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method ( // param auto initial_param = parse_self_param (); - if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + if (!initial_param.has_value () + && initial_param.error () != ParseSelfError::NOT_SELF) return nullptr; /* FIXME: ensure that self param doesn't accidently consume tokens for a @@ -5769,7 +5832,8 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( // param auto initial_param = parse_self_param (); - if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + if (!initial_param.has_value () + && initial_param.error () != ParseSelfError::NOT_SELF) return nullptr; // FIXME: ensure that self param doesn't accidently consume tokens for a @@ -5953,7 +6017,8 @@ Parser<ManagedTokenSource>::parse_external_item () { case IDENTIFIER: return parse_macro_invocation_semi (outer_attrs); - case STATIC_KW: { + case STATIC_KW: + { // parse extern static item lexer.skip_token (); @@ -6154,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; } @@ -6242,7 +6303,7 @@ Parser<ManagedTokenSource>::parse_type_path () } template <typename ManagedTokenSource> -AST::GenericArg +tl::optional<AST::GenericArg> Parser<ManagedTokenSource>::parse_generic_arg () { auto tok = lexer.peek_token (); @@ -6250,7 +6311,8 @@ Parser<ManagedTokenSource>::parse_generic_arg () switch (tok->get_id ()) { - case IDENTIFIER: { + case IDENTIFIER: + { // This is a bit of a weird situation: With an identifier token, we // could either have a valid type or a macro (FIXME: anything else?). So // we need one bit of lookahead to differentiate if this is really @@ -6263,7 +6325,7 @@ Parser<ManagedTokenSource>::parse_generic_arg () if (type) return AST::GenericArg::create_type (std::move (type)); else - return AST::GenericArg::create_error (); + return tl::nullopt; } else if (next_tok->get_id () == COLON) { @@ -6280,7 +6342,7 @@ Parser<ManagedTokenSource>::parse_generic_arg () if (type) return AST::GenericArg::create_type (std::move (type)); else - return AST::GenericArg::create_error (); + return tl::nullopt; } lexer.skip_token (); return AST::GenericArg::create_ambiguous (tok->get_str (), @@ -6298,20 +6360,21 @@ Parser<ManagedTokenSource>::parse_generic_arg () case FALSE_LITERAL: expr = parse_literal_expr (); break; - // FIXME: Because of this, error reporting is garbage for const generic - // parameter's default values - default: { + // FIXME: Because of this, error reporting is garbage for const generic + // parameter's default values + default: + { auto type = parse_type (); // FIXME: Find a better way to do this? if (type) return AST::GenericArg::create_type (std::move (type)); else - return AST::GenericArg::create_error (); + return tl::nullopt; } } if (!expr) - return AST::GenericArg::create_error (); + return tl::nullopt; return AST::GenericArg::create_const (std::move (expr)); } @@ -6340,14 +6403,14 @@ Parser<ManagedTokenSource>::parse_path_generic_args () location_t locus = t->get_locus (); while (!is_right_angle_tok (t->get_id ())) { - AST::Lifetime lifetime = parse_lifetime (false); - if (lifetime.is_error ()) + auto lifetime = parse_lifetime (false); + if (!lifetime) { // not necessarily an error break; } - lifetime_args.push_back (std::move (lifetime)); + lifetime_args.push_back (std::move (lifetime.value ())); // if next token isn't comma, then it must be end of list if (lexer.peek_token ()->get_id () != COMMA) @@ -6376,9 +6439,9 @@ Parser<ManagedTokenSource>::parse_path_generic_args () break; auto arg = parse_generic_arg (); - if (!arg.is_error ()) + if (arg) { - generic_args.emplace_back (std::move (arg)); + generic_args.emplace_back (std::move (arg.value ())); } // FIXME: Do we need to break if we encounter an error? @@ -6499,7 +6562,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment () switch (t->get_id ()) { case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // parse generic args AST::GenericArgs generic_args = parse_path_generic_args (); @@ -6508,7 +6572,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment () has_separating_scope_resolution, std::move (generic_args), locus)); } - case LEFT_PAREN: { + case LEFT_PAREN: + { // parse type path function AST::TypePathFunction type_path_function = parse_type_path_function (locus); @@ -6961,10 +7026,12 @@ Parser<ManagedTokenSource>::parse_self_param () // now test whether it has a lifetime if (lexer.peek_token ()->get_id () == LIFETIME) { - lifetime = parse_lifetime (true); - // something went wrong somehow - if (lifetime.is_error ()) + if (auto parsed_lifetime = parse_lifetime (true)) + { + lifetime = parsed_lifetime.value (); + } + else { Error error (lexer.peek_token ()->get_locus (), "failed to parse lifetime in self param"); @@ -7055,16 +7122,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, case SELF: case SELF_ALIAS: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { AST::PathInExpression path = parse_path_in_expression (); std::unique_ptr<AST::Expr> null_denotation; if (lexer.peek_token ()->get_id () == EXCLAM) { - // Bind a reference to avoid -Wredundant-move on post-P1825R0 - // compilers. Change to non-reference type and remove the moves - // below once C++20 is required to build gcc. - std::unique_ptr<AST::MacroInvocation> &&invoc + std::unique_ptr<AST::MacroInvocation> invoc = parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); @@ -7072,7 +7137,7 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, { invoc->add_semicolon (); // Macro invocation with semicolon. - return std::move (invoc); + return invoc; } TokenId after_macro = lexer.peek_token ()->get_id (); @@ -7080,14 +7145,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, if (restrictions.allow_close_after_expr_stmt && (after_macro == RIGHT_PAREN || after_macro == RIGHT_CURLY || after_macro == RIGHT_SQUARE)) - return std::move (invoc); + return invoc; if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type () == AST::CURLY && after_macro != DOT && after_macro != QUESTION_MARK) { rust_debug ("braced macro statement"); - return std::move (invoc); + return invoc; } null_denotation = std::move (invoc); @@ -7153,9 +7218,9 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, // Parses a block expression, including the curly braces at start and end. template <typename ManagedTokenSource> std::unique_ptr<AST::BlockExpr> -Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label, - location_t pratt_parsed_loc) +Parser<ManagedTokenSource>::parse_block_expr ( + AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label, + location_t pratt_parsed_loc) { location_t locus = pratt_parsed_loc; if (locus == UNKNOWN_LOCATION) @@ -7180,11 +7245,7 @@ Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs, 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; } @@ -7225,6 +7286,51 @@ Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs, std::move (label), locus, end_locus)); } +/* Parse an anonymous const expression. This can be a regular const expression + * or an underscore for deferred const inference */ +template <typename ManagedTokenSource> +tl::expected<AST::AnonConst, AnonConstError> +Parser<ManagedTokenSource>::parse_anon_const () +{ + auto current = lexer.peek_token (); + auto locus = current->get_locus (); + + // Special case deferred inference constants + if (maybe_skip_token (UNDERSCORE)) + return AST::AnonConst (locus); + + auto expr = parse_expr (); + + if (!expr) + return tl::make_unexpected (AnonConstError::InvalidSizeExpr); + + return AST::AnonConst (std::move (expr), locus); +} + +/* Parse a "const block", a block preceded by the `const` keyword whose + * statements can be const evaluated and used in constant contexts */ +template <typename ManagedTokenSource> +std::unique_ptr<AST::ConstBlock> +Parser<ManagedTokenSource>::parse_const_block_expr (AST::AttrVec outer_attrs, + location_t locus) +{ + auto block = parse_block_expr (); + + if (!block) + { + add_error (Error (locus, "failed to parse inner block in const block")); + skip_after_end_block (); + + return nullptr; + } + + auto block_locus = block->get_locus (); + + return std::make_unique<AST::ConstBlock> (AST::AnonConst (std::move (block), + block_locus), + locus, std::move (outer_attrs)); +} + /* Parses a "grouped" expression (expression in parentheses), used to control * precedence. */ template <typename ManagedTokenSource> @@ -7505,6 +7611,34 @@ Parser<ManagedTokenSource>::parse_return_expr (AST::AttrVec outer_attrs, locus)); } +// Parses a try expression. +template <typename ManagedTokenSource> +std::unique_ptr<AST::TryExpr> +Parser<ManagedTokenSource>::parse_try_expr (AST::AttrVec outer_attrs, + location_t pratt_parsed_loc) +{ + location_t locus = pratt_parsed_loc; + if (locus == UNKNOWN_LOCATION) + { + locus = lexer.peek_token ()->get_locus (); + skip_token (TRY); + } + + std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr (); + + if (!block_expr) + { + Error error (lexer.peek_token ()->get_locus (), + "failed to parse try block expression"); + add_error (std::move (error)); + + return nullptr; + } + + return std::unique_ptr<AST::TryExpr> ( + new AST::TryExpr (std::move (block_expr), std::move (outer_attrs), locus)); +} + /* Parses a break expression (including any label to break to AND any return * expression). */ template <typename ManagedTokenSource> @@ -7519,12 +7653,10 @@ Parser<ManagedTokenSource>::parse_break_expr (AST::AttrVec outer_attrs, skip_token (BREAK); } - // parse label (lifetime) if it exists - create dummy first - AST::Lifetime label = AST::Lifetime::error (); - if (lexer.peek_token ()->get_id () == LIFETIME) - { - label = parse_lifetime (false); - } + auto parsed_label = parse_lifetime (false); + auto label = (parsed_label) + ? tl::optional<AST::Lifetime> (parsed_label.value ()) + : tl::nullopt; // parse break return expression if it exists ParseRestrictions restrictions; @@ -7550,12 +7682,10 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs, skip_token (CONTINUE); } - // parse label (lifetime) if it exists - create dummy first - AST::Lifetime label = AST::Lifetime::error (); - if (lexer.peek_token ()->get_id () == LIFETIME) - { - label = parse_lifetime (false); - } + auto parsed_label = parse_lifetime (false); + auto label = (parsed_label) + ? tl::optional<AST::Lifetime> (parsed_label.value ()) + : tl::nullopt; return std::unique_ptr<AST::ContinueExpr> ( new AST::ContinueExpr (std::move (label), std::move (outer_attrs), locus)); @@ -7563,14 +7693,15 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs, // Parses a loop label used in loop expressions. template <typename ManagedTokenSource> -AST::LoopLabel +tl::expected<AST::LoopLabel, ParseLoopLabelError> Parser<ManagedTokenSource>::parse_loop_label (const_TokenPtr tok) { // parse lifetime - if doesn't exist, assume no label if (tok->get_id () != LIFETIME) { // not necessarily an error - return AST::LoopLabel::error (); + return tl::unexpected<ParseLoopLabelError> ( + ParseLoopLabelError::NOT_LOOP_LABEL); } /* FIXME: check for named lifetime requirement here? or check in semantic * analysis phase? */ @@ -7579,10 +7710,12 @@ Parser<ManagedTokenSource>::parse_loop_label (const_TokenPtr tok) if (!skip_token (COLON)) { // skip somewhere? - return AST::LoopLabel::error (); + return tl::unexpected<ParseLoopLabelError> ( + ParseLoopLabelError::MISSING_COLON); } - return AST::LoopLabel (std::move (label), tok->get_locus ()); + return tl::expected<AST::LoopLabel, ParseLoopLabelError> ( + AST::LoopLabel (std::move (label), tok->get_locus ())); } /* Parses an if expression of any kind, including with else, else if, else if @@ -7635,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) @@ -7663,7 +7789,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // double selection - else // parse else block expr (required) std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr (); @@ -7684,7 +7811,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs, std::move (else_body), std::move (outer_attrs), locus)); } - case IF: { + case IF: + { // multiple selection - else if or else if let // branch on whether next token is 'let' or not if (lexer.peek_token (1)->get_id () == LET) @@ -7845,7 +7973,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // double selection - else // parse else block expr (required) std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr (); @@ -7867,7 +7996,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs, std::move (else_body), std::move (outer_attrs), locus)); } - case IF: { + case IF: + { // multiple selection - else if or else if let // branch on whether next token is 'let' or not if (lexer.peek_token (1)->get_id () == LET) @@ -7935,16 +8065,16 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs, template <typename ManagedTokenSource> std::unique_ptr<AST::LoopExpr> Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label, + tl::optional<AST::LoopLabel> label, location_t pratt_parsed_loc) { location_t locus = pratt_parsed_loc; if (locus == UNKNOWN_LOCATION) { - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (label) + locus = label->get_locus (); else - locus = label.get_locus (); + locus = lexer.peek_token ()->get_locus (); if (!skip_token (LOOP)) { @@ -7954,20 +8084,14 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs, } else { - if (!label.is_error ()) - locus = label.get_locus (); + if (label) + locus = label->get_locus (); } // 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), @@ -7978,17 +8102,17 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs, * via parse_labelled_loop_expr, which would call this. */ template <typename ManagedTokenSource> std::unique_ptr<AST::WhileLoopExpr> -Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label, - location_t pratt_parsed_loc) +Parser<ManagedTokenSource>::parse_while_loop_expr ( + AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label, + location_t pratt_parsed_loc) { location_t locus = pratt_parsed_loc; if (locus == UNKNOWN_LOCATION) { - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (label) + locus = label->get_locus (); else - locus = label.get_locus (); + locus = lexer.peek_token ()->get_locus (); if (!skip_token (WHILE)) { @@ -7998,8 +8122,8 @@ Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs, } else { - if (!label.is_error ()) - locus = label.get_locus (); + if (label) + locus = label->get_locus (); } // ensure it isn't a while let loop @@ -8051,14 +8175,14 @@ Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs, * parsed via parse_labelled_loop_expr, which would call this. */ template <typename ManagedTokenSource> std::unique_ptr<AST::WhileLetLoopExpr> -Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label) +Parser<ManagedTokenSource>::parse_while_let_loop_expr ( + AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label) { location_t locus = UNKNOWN_LOCATION; - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (label) + locus = label->get_locus (); else - locus = label.get_locus (); + locus = lexer.peek_token ()->get_locus (); maybe_skip_token (WHILE); /* check for possible accidental recognition of a while loop as a while let @@ -8079,7 +8203,14 @@ Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs, // 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)) { @@ -8125,14 +8256,14 @@ Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs, * parse_labelled_loop_expr, which would call this. */ template <typename ManagedTokenSource> std::unique_ptr<AST::ForLoopExpr> -Parser<ManagedTokenSource>::parse_for_loop_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label) +Parser<ManagedTokenSource>::parse_for_loop_expr ( + AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label) { location_t locus = UNKNOWN_LOCATION; - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (label) + locus = label->get_locus (); else - locus = label.get_locus (); + locus = lexer.peek_token ()->get_locus (); maybe_skip_token (FOR); // parse pattern, which is required @@ -8210,8 +8341,9 @@ Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok, } // parse loop label (required) - AST::LoopLabel label = parse_loop_label (tok); - if (label.is_error ()) + // TODO: Convert this return type to tl::expected instead of tl::optional + auto parsed_label = parse_loop_label (tok); + if (!parsed_label) { Error error (lexer.peek_token ()->get_locus (), "failed to parse loop label in labelled loop expr"); @@ -8221,6 +8353,10 @@ Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok, return nullptr; } + auto label = parsed_label + ? tl::optional<AST::LoopLabel> (parsed_label.value ()) + : tl::nullopt; + // branch on next token const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) @@ -8914,7 +9050,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) // slice type or array type - requires further disambiguation return parse_slice_or_array_type (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in type AST::QualifiedPathInType path = parse_qualified_path_in_type (); if (path.is_error ()) @@ -8943,7 +9080,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) case LOGICAL_AND: // reference type return parse_reference_type (); - case LIFETIME: { + case LIFETIME: + { /* probably a lifetime bound, so probably type param bounds in * TraitObjectType */ std::vector<std::unique_ptr<AST::TypeParamBound>> bounds @@ -8959,7 +9097,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) case SELF_ALIAS: case CRATE: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { // macro invocation or type path - requires further disambiguation. /* for parsing path component of each rule, perhaps parse it as a * typepath and attempt conversion to simplepath if a trailing '!' is @@ -8989,7 +9128,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) t = lexer.peek_token (); switch (t->get_id ()) { - case EXCLAM: { + case EXCLAM: + { // macro invocation // convert to simple path AST::SimplePath macro_path = path.as_simple_path (); @@ -9015,7 +9155,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) std::move (tok_tree)), {}, locus); } - case PLUS: { + case PLUS: + { // type param bounds std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; @@ -9100,14 +9241,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) t = lexer.peek_token (); if (t->get_id () != PLUS) { - // convert trait bound to value object - AST::TraitBound value_bound (*initial_bound); - - // DEBUG: removed as unique ptr, so should auto-delete - // delete initial_bound; - return std::unique_ptr<AST::ImplTraitTypeOneBound> ( - new AST::ImplTraitTypeOneBound (std::move (value_bound), + new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } @@ -9135,7 +9270,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) new AST::ImplTraitType (std::move (bounds), locus)); } case DYN: - case QUESTION_MARK: { + case QUESTION_MARK: + { // either TraitObjectType or TraitObjectTypeOneBound bool has_dyn = false; if (t->get_id () == DYN) @@ -9388,7 +9524,8 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type () case SELF: case SELF_ALIAS: case CRATE: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path, so trait type // parse type path to finish parsing trait bound @@ -9598,8 +9735,12 @@ Parser<ManagedTokenSource>::parse_reference_type_inner (location_t locus) AST::Lifetime lifetime = AST::Lifetime::elided (); if (lexer.peek_token ()->get_id () == LIFETIME) { - lifetime = parse_lifetime (true); - if (lifetime.is_error ()) + auto parsed_lifetime = parse_lifetime (true); + if (parsed_lifetime) + { + lifetime = parsed_lifetime.value (); + } + else { Error error (lexer.peek_token ()->get_locus (), "failed to parse lifetime in reference type"); @@ -9730,13 +9871,15 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type () return std::unique_ptr<AST::SliceType> ( new AST::SliceType (std::move (inner_type), locus)); - case SEMICOLON: { + case SEMICOLON: + { // array type lexer.skip_token (); // parse required array size expression - std::unique_ptr<AST::Expr> size = parse_expr (); - if (size == nullptr) + auto size = parse_anon_const (); + + if (!size) { Error error (lexer.peek_token ()->get_locus (), "failed to parse size expression in array type"); @@ -9751,7 +9894,8 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type () } return std::unique_ptr<AST::ArrayType> ( - new AST::ArrayType (std::move (inner_type), std::move (size), locus)); + new AST::ArrayType (std::move (inner_type), std::move (*size), + locus)); } default: // error @@ -9781,7 +9925,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () // slice type or array type - requires further disambiguation return parse_slice_or_array_type (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in type AST::QualifiedPathInType path = parse_qualified_path_in_type (); if (path.is_error ()) @@ -9822,7 +9967,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () case SELF_ALIAS: case CRATE: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { // macro invocation or type path - requires further disambiguation. /* for parsing path component of each rule, perhaps parse it as a * typepath and attempt conversion to simplepath if a trailing '!' is @@ -9850,7 +9996,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () t = lexer.peek_token (); switch (t->get_id ()) { - case EXCLAM: { + case EXCLAM: + { // macro invocation // convert to simple path AST::SimplePath macro_path = path.as_simple_path (); @@ -9934,14 +10081,12 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () return nullptr; } - // convert trait bound to value object - AST::TraitBound value_bound (*initial_bound); - return std::unique_ptr<AST::ImplTraitTypeOneBound> ( - new AST::ImplTraitTypeOneBound (std::move (value_bound), locus)); + new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } case DYN: - case QUESTION_MARK: { + case QUESTION_MARK: + { // either TraitObjectTypeOneBound bool has_dyn = false; if (t->get_id () == DYN) @@ -10204,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)); } } @@ -10282,7 +10427,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path in expression AST::PathInExpression path = parse_path_in_expression (); if (path.is_error ()) @@ -10298,7 +10444,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound () new AST::RangePatternBoundPath (std::move (path))); } case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in expression AST::QualifiedPathInExpression path = parse_qualified_path_in_expression (); @@ -10340,16 +10487,22 @@ Parser<ManagedTokenSource>::parse_pattern () return first; std::vector<std::unique_ptr<AST::Pattern>> alts; - alts.push_back (std::move (first)); + if (first != nullptr) + alts.push_back (std::move (first)); do { lexer.skip_token (); - alts.push_back (parse_pattern_no_alt ()); + auto follow = parse_pattern_no_alt (); + if (follow != nullptr) + alts.push_back (std::move (follow)); } while (lexer.peek_token ()->get_id () == PIPE); + if (alts.empty ()) + return nullptr; + /* alternates */ return std::unique_ptr<AST::Pattern> ( new AST::AltPattern (std::move (alts), start_locus)); @@ -10443,7 +10596,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () // slice pattern return parse_slice_pattern (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in expression or qualified range pattern bound AST::QualifiedPathInExpression path = parse_qualified_path_in_expression (); @@ -10479,7 +10633,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path in expression or range pattern bound AST::PathInExpression path = parse_path_in_expression (); @@ -10488,7 +10643,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () { case DOT_DOT_EQ: case DOT_DOT: - case ELLIPSIS: { + case ELLIPSIS: + { // qualified range pattern bound, so parse rest of range pattern AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ()); lexer.skip_token (); @@ -10506,7 +10662,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () case EXCLAM: return parse_macro_invocation_partial (std::move (path), AST::AttrVec ()); - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple struct lexer.skip_token (); @@ -10531,7 +10688,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () new AST::TupleStructPattern (std::move (path), std::move (items))); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct lexer.skip_token (); @@ -10663,9 +10821,9 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () return nullptr; } - // create ranged tuple pattern items with only upper items - std::unique_ptr<AST::TuplePatternItemsRanged> items ( - new AST::TuplePatternItemsRanged ( + // create tuple pattern items with only upper pattern items + std::unique_ptr<AST::TuplePatternItemsHasRest> items ( + new AST::TuplePatternItemsHasRest ( std::vector<std::unique_ptr<AST::Pattern>> (), std::move (patterns))); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); @@ -10673,8 +10831,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () else if (lexer.peek_token ()->get_id () == RIGHT_PAREN) { skip_token (RIGHT_PAREN); - auto items = std::unique_ptr<AST::TuplePatternItemsMultiple> ( - new AST::TuplePatternItemsMultiple ( + auto items = std::unique_ptr<AST::TuplePatternItemsNoRest> ( + new AST::TuplePatternItemsNoRest ( std::vector<std::unique_ptr<AST::Pattern>> ())); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); @@ -10701,7 +10859,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () return std::unique_ptr<AST::GroupedPattern> ( new AST::GroupedPattern (std::move (initial_pattern), paren_locus)); - case COMMA: { + case COMMA: + { // tuple pattern lexer.skip_token (); @@ -10737,8 +10896,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () // non-ranged tuple pattern lexer.skip_token (); - std::unique_ptr<AST::TuplePatternItemsMultiple> items ( - new AST::TuplePatternItemsMultiple (std::move (patterns))); + std::unique_ptr<AST::TuplePatternItemsNoRest> items ( + new AST::TuplePatternItemsNoRest (std::move (patterns))); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); } @@ -10778,9 +10937,9 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () return nullptr; } - std::unique_ptr<AST::TuplePatternItemsRanged> items ( - new AST::TuplePatternItemsRanged (std::move (patterns), - std::move (upper_patterns))); + std::unique_ptr<AST::TuplePatternItemsHasRest> items ( + new AST::TuplePatternItemsHasRest (std::move (patterns), + std::move (upper_patterns))); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); } @@ -10814,27 +10973,47 @@ Parser<ManagedTokenSource>::parse_slice_pattern () { location_t square_locus = lexer.peek_token ()->get_locus (); std::vector<std::unique_ptr<AST::Pattern>> patterns; + tl::optional<std::vector<std::unique_ptr<AST::Pattern>>> upper_patterns + = tl::nullopt; + + // lambda function to determine which vector to push new patterns into + auto get_pattern_ref + = [&] () -> std::vector<std::unique_ptr<AST::Pattern>> & { + return upper_patterns.has_value () ? upper_patterns.value () : patterns; + }; + skip_token (LEFT_SQUARE); if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) { skip_token (RIGHT_SQUARE); + std::unique_ptr<AST::SlicePatternItemsNoRest> items ( + new AST::SlicePatternItemsNoRest (std::move (patterns))); return std::unique_ptr<AST::SlicePattern> ( - new AST::SlicePattern (std::move (patterns), square_locus)); + new AST::SlicePattern (std::move (items), square_locus)); } // parse initial pattern (required) - std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern (); - if (initial_pattern == nullptr) + if (lexer.peek_token ()->get_id () == DOT_DOT) { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse initial pattern in slice pattern"); - add_error (std::move (error)); - - return nullptr; + lexer.skip_token (); + upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> (); } + else + { + // Not a rest pattern `..`, parse normally + std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern (); + if (initial_pattern == nullptr) + { + Error error (lexer.peek_token ()->get_locus (), + "failed to parse initial pattern in slice pattern"); + add_error (std::move (error)); - patterns.push_back (std::move (initial_pattern)); + return nullptr; + } + + patterns.push_back (std::move (initial_pattern)); + } const_TokenPtr t = lexer.peek_token (); while (t->get_id () == COMMA) @@ -10845,6 +11024,23 @@ Parser<ManagedTokenSource>::parse_slice_pattern () if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) break; + if (lexer.peek_token ()->get_id () == DOT_DOT) + { + if (upper_patterns.has_value ()) + { + // DOT_DOT has been parsed before + Error error (lexer.peek_token ()->get_locus (), "%s", + "`..` can only be used once per slice pattern"); + add_error (std::move (error)); + + return nullptr; + } + upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> (); + lexer.skip_token (); + t = lexer.peek_token (); + continue; + } + // parse pattern (required) std::unique_ptr<AST::Pattern> pattern = parse_pattern (); if (pattern == nullptr) @@ -10855,7 +11051,7 @@ Parser<ManagedTokenSource>::parse_slice_pattern () return nullptr; } - patterns.push_back (std::move (pattern)); + get_pattern_ref ().push_back (std::move (pattern)); t = lexer.peek_token (); } @@ -10865,8 +11061,21 @@ Parser<ManagedTokenSource>::parse_slice_pattern () return nullptr; } + if (upper_patterns.has_value ()) + { + // Slice pattern with rest + std::unique_ptr<AST::SlicePatternItemsHasRest> items ( + new AST::SlicePatternItemsHasRest ( + std::move (patterns), std::move (upper_patterns.value ()))); + return std::unique_ptr<AST::SlicePattern> ( + new AST::SlicePattern (std::move (items), square_locus)); + } + + // Rest-less slice pattern + std::unique_ptr<AST::SlicePatternItemsNoRest> items ( + new AST::SlicePatternItemsNoRest (std::move (patterns))); return std::unique_ptr<AST::SlicePattern> ( - new AST::SlicePattern (std::move (patterns), square_locus)); + new AST::SlicePattern (std::move (items), square_locus)); } /* Parses an identifier pattern (pattern that binds a value matched to a @@ -10913,7 +11122,7 @@ Parser<ManagedTokenSource>::parse_identifier_pattern () lexer.skip_token (); // parse required pattern to bind - bind_pattern = parse_pattern (); + bind_pattern = parse_pattern_no_alt (); if (bind_pattern == nullptr) { Error error (lexer.peek_token ()->get_locus (), @@ -10958,7 +11167,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () { case EXCLAM: return parse_macro_invocation_partial (std::move (path), AST::AttrVec ()); - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple struct lexer.skip_token (); @@ -10991,7 +11201,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () return std::unique_ptr<AST::TupleStructPattern> ( new AST::TupleStructPattern (std::move (path), std::move (items))); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct lexer.skip_token (); @@ -11012,7 +11223,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () } case DOT_DOT_EQ: case DOT_DOT: - case ELLIPSIS: { + case ELLIPSIS: + { // range AST::RangeKind kind = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ()); @@ -11029,14 +11241,16 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () std::move (upper_bound), kind, t->get_locus ())); } - case PATTERN_BIND: { + case PATTERN_BIND: + { // only allow on single-segment paths if (path.is_single_segment ()) { // identifier with pattern bind lexer.skip_token (); - std::unique_ptr<AST::Pattern> bind_pattern = parse_pattern (); + std::unique_ptr<AST::Pattern> bind_pattern + = parse_pattern_no_alt (); if (bind_pattern == nullptr) { Error error ( @@ -11121,9 +11335,9 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () rust_debug ( "finished parsing tuple struct items ranged (upper/none only)"); - return std::unique_ptr<AST::TupleStructItemsRange> ( - new AST::TupleStructItemsRange (std::move (lower_patterns), - std::move (upper_patterns))); + return std::unique_ptr<AST::TupleStructItemsHasRest> ( + new AST::TupleStructItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns))); } // has at least some lower patterns @@ -11165,9 +11379,10 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () switch (t->get_id ()) { case RIGHT_PAREN: - return std::unique_ptr<AST::TupleStructItemsNoRange> ( - new AST::TupleStructItemsNoRange (std::move (lower_patterns))); - case DOT_DOT: { + return std::unique_ptr<AST::TupleStructItemsNoRest> ( + new AST::TupleStructItemsNoRest (std::move (lower_patterns))); + case DOT_DOT: + { // has an upper range that must be parsed separately lexer.skip_token (); @@ -11197,9 +11412,9 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () t = lexer.peek_token (); } - return std::unique_ptr<AST::TupleStructItemsRange> ( - new AST::TupleStructItemsRange (std::move (lower_patterns), - std::move (upper_patterns))); + return std::unique_ptr<AST::TupleStructItemsHasRest> ( + new AST::TupleStructItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns))); } default: // error @@ -11219,7 +11434,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems () std::vector<std::unique_ptr<AST::StructPatternField>> fields; AST::AttrVec etc_attrs; - bool has_etc = false; + bool has_rest = false; // try parsing struct pattern fields const_TokenPtr t = lexer.peek_token (); @@ -11232,7 +11447,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems () { lexer.skip_token (); etc_attrs = std::move (outer_attrs); - has_etc = true; + has_rest = true; break; } @@ -11257,7 +11472,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems () t = lexer.peek_token (); } - if (has_etc) + if (has_rest) return AST::StructPatternElements (std::move (fields), std::move (etc_attrs)); else @@ -11287,7 +11502,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case INT_LITERAL: { + case INT_LITERAL: + { // tuple index std::string index_str = t->get_str (); int index = atoi (index_str.c_str ()); @@ -11321,7 +11537,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( // branch on next token switch (lexer.peek_token (1)->get_id ()) { - case COLON: { + case COLON: + { // identifier-pattern Identifier ident{t}; lexer.skip_token (); @@ -11346,7 +11563,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( t->get_locus ())); } case COMMA: - case RIGHT_CURLY: { + case RIGHT_CURLY: + { // identifier only Identifier ident = {t}; lexer.skip_token (); @@ -11365,7 +11583,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( return nullptr; } case REF: - case MUT: { + case MUT: + { // only identifier bool has_ref = false; if (t->get_id () == REF) @@ -11437,7 +11656,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () t = lexer.peek_token (); switch (t->get_id ()) { - case LET: { + case LET: + { // let statement std::unique_ptr<AST::LetStmt> stmt ( parse_let_stmt (std::move (outer_attrs))); @@ -11455,42 +11675,48 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () case STATIC_KW: case AUTO: case TRAIT: - case IMPL: { + case IMPL: + { std::unique_ptr<AST::VisItem> item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } - /* TODO: implement union keyword but not really because of - * context-dependence crappy hack way to parse a union written below to - * separate it from the good code. */ - // case UNION: - case UNSAFE: { // maybe - unsafe traits are a thing + /* TODO: implement union keyword but not really because of + * context-dependence crappy hack way to parse a union written below to + * separate it from the good code. */ + // case UNION: + case UNSAFE: + { // maybe - unsafe traits are a thing /* if any of these (should be all possible VisItem prefixes), parse a * VisItem - can't parse item because would require reparsing outer * attributes */ const_TokenPtr t2 = lexer.peek_token (1); switch (t2->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // unsafe block: parse as expression expr = parse_expr (std::move (outer_attrs), restrictions); break; } case AUTO: - case TRAIT: { + case TRAIT: + { // unsafe trait std::unique_ptr<AST::VisItem> item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } case EXTERN_KW: - case FN_KW: { + case FN_KW: + { // unsafe function std::unique_ptr<AST::VisItem> item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } - case IMPL: { + case IMPL: + { // unsafe trait impl std::unique_ptr<AST::VisItem> item ( parse_vis_item (std::move (outer_attrs))); @@ -11535,7 +11761,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { AST::PathInExpression path = parse_path_in_expression (); std::unique_ptr<AST::Expr> null_denotation; @@ -11544,6 +11771,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () std::unique_ptr<AST::MacroInvocation> invoc = parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); + if (invoc == nullptr) + return ExprOrStmt::create_error (); if (restrictions.consume_semi && maybe_skip_token (SEMICOLON)) { @@ -11555,9 +11784,12 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () TokenId after_macro = lexer.peek_token ()->get_id (); - if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type () - == AST::CURLY - && after_macro != DOT && after_macro != QUESTION_MARK) + AST::DelimType delim_type = invoc->get_invoc_data () + .get_delim_tok_tree () + .get_delim_type (); + + if (delim_type == AST::CURLY && after_macro != DOT + && after_macro != QUESTION_MARK) { rust_debug ("braced macro statement"); return ExprOrStmt ( @@ -11659,7 +11891,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_field () std::move (outer_attrs), t->get_locus ())); } - case INT_LITERAL: { + case INT_LITERAL: + { // parse tuple index field int index = atoi (t->get_str ().c_str ()); lexer.skip_token (); @@ -11704,11 +11937,12 @@ Parser<ManagedTokenSource>::parse_struct_expr_field () } // "Unexpected token" panic mode - flags gcc error at unexpected token +// TODO: seems to be unused, remove? template <typename ManagedTokenSource> void Parser<ManagedTokenSource>::unexpected_token (const_TokenPtr t) { - Error error (t->get_locus (), "unexpected token %qs\n", + Error error (t->get_locus (), "unexpected token %qs", t->get_token_description ()); add_error (std::move (error)); } @@ -11899,7 +12133,7 @@ Parser<ManagedTokenSource>::skip_after_end_attribute () { const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_SQUARE) + while (t->get_id () != RIGHT_SQUARE && t->get_id () != END_OF_FILE) { lexer.skip_token (); t = lexer.peek_token (); @@ -11930,20 +12164,14 @@ Parser<ManagedTokenSource>::parse_expr (int right_binding_power, return nullptr; } - if (current_token->get_id () == LEFT_SHIFT) - { - lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE); - current_token = lexer.peek_token (); - } - - lexer.skip_token (); - ParseRestrictions null_denotation_restrictions = restrictions; null_denotation_restrictions.expr_can_be_stmt = false; // parse null denotation (unary part of expression) std::unique_ptr<AST::Expr> expr - = null_denotation (current_token, {}, null_denotation_restrictions); + = null_denotation ({}, null_denotation_restrictions); + if (expr == nullptr) + return nullptr; return left_denotations (std::move (expr), right_binding_power, std::move (outer_attrs), restrictions); @@ -12011,8 +12239,7 @@ Parser<ManagedTokenSource>::parse_expr (AST::AttrVec outer_attrs, /* Determines action to take when finding token at beginning of expression. */ template <typename ManagedTokenSource> std::unique_ptr<AST::Expr> -Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, - AST::AttrVec outer_attrs, +Parser<ManagedTokenSource>::null_denotation (AST::AttrVec outer_attrs, ParseRestrictions restrictions) { /* note: tok is previous character in input stream, not current one, as @@ -12022,6 +12249,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, * denotation and then a left denotation), null denotations handle primaries * and unary operands (but only prefix unary operands) */ + auto tok = lexer.peek_token (); + switch (tok->get_id ()) { case IDENTIFIER: @@ -12029,27 +12258,27 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, case SELF_ALIAS: case DOLLAR_SIGN: case CRATE: - case SUPER: { + case SUPER: + case SCOPE_RESOLUTION: + { // DEBUG rust_debug ("beginning null denotation identifier handling"); /* best option: parse as path, then extract identifier, macro, * struct/enum, or just path info from it */ - AST::PathInExpression path = parse_path_in_expression_pratt (tok); + AST::PathInExpression path = parse_path_in_expression (); return null_denotation_path (std::move (path), std::move (outer_attrs), restrictions); } - case SCOPE_RESOLUTION: { - // TODO: fix: this is for global paths, i.e. std::string::whatever - Error error (tok->get_locus (), - "found null denotation scope resolution operator, and " - "have not written handling for it"); - add_error (std::move (error)); - - return nullptr; - } default: + if (tok->get_id () == LEFT_SHIFT) + { + lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE); + tok = lexer.peek_token (); + } + + lexer.skip_token (); return null_denotation_not_path (std::move (tok), std::move (outer_attrs), restrictions); } @@ -12082,7 +12311,8 @@ Parser<ManagedTokenSource>::null_denotation_path ( // macro return parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); - case LEFT_CURLY: { + case LEFT_CURLY: + { bool not_a_block = lexer.peek_token (1)->get_id () == IDENTIFIER && (lexer.peek_token (2)->get_id () == COMMA || (lexer.peek_token (2)->get_id () == COLON @@ -12158,7 +12388,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( { // FIXME: Handle in null_denotation_path? case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path // HACK: add outer attrs to path AST::QualifiedPathInExpression path @@ -12216,23 +12447,24 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( return parse_grouped_or_tuple_expr (std::move (outer_attrs), tok->get_locus ()); - /*case PLUS: { // unary plus operator - // invoke parse_expr recursively with appropriate priority, etc. for - below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS); + /*case PLUS: { // unary plus operator + // invoke parse_expr recursively with appropriate priority, etc. for + below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS); - if (expr == nullptr) - return nullptr; - // can only apply to integer and float expressions - if (expr->get_type() != integer_type_node || expr->get_type() != - float_type_node) { rust_error_at(tok->get_locus(), "operand of unary - plus must be int or float but it is %s", print_type(expr->get_type())); - return nullptr; - } + if (expr == nullptr) + return nullptr; + // can only apply to integer and float expressions + if (expr->get_type() != integer_type_node || expr->get_type() != + float_type_node) { rust_error_at(tok->get_locus(), "operand of unary + plus must be int or float but it is %s", print_type(expr->get_type())); + return nullptr; + } - return Tree(expr, tok->get_locus()); - }*/ - // Rust has no unary plus operator - case MINUS: { // unary minus + return Tree(expr, tok->get_locus()); + }*/ + // Rust has no unary plus operator + case MINUS: + { // unary minus ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) @@ -12259,7 +12491,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( new AST::NegationExpr (std::move (expr), NegationOperator::NEGATE, std::move (outer_attrs), tok->get_locus ())); } - case EXCLAM: { // logical or bitwise not + case EXCLAM: + { // logical or bitwise not ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) @@ -12284,7 +12517,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( new AST::NegationExpr (std::move (expr), NegationOperator::NOT, std::move (outer_attrs), tok->get_locus ())); } - case ASTERISK: { + case ASTERISK: + { /* pointer dereference only - HACK: as struct expressions should * always be value expressions, cannot be dereferenced */ ParseRestrictions entered_from_unary; @@ -12297,7 +12531,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( new AST::DereferenceExpr (std::move (expr), std::move (outer_attrs), tok->get_locus ())); } - case AMP: { + case AMP: + { // (single) "borrow" expression - shared (mutable) or immutable std::unique_ptr<AST::Expr> expr = nullptr; Mutability mutability = Mutability::Imm; @@ -12354,7 +12589,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( new AST::BorrowExpr (std::move (expr), mutability, raw_borrow, false, std::move (outer_attrs), tok->get_locus ())); } - case LOGICAL_AND: { + case LOGICAL_AND: + { // (double) "borrow" expression - shared (mutable) or immutable std::unique_ptr<AST::Expr> expr = nullptr; Mutability mutability = Mutability::Imm; @@ -12393,6 +12629,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( case RETURN_KW: // FIXME: is this really a null denotation expression? return parse_return_expr (std::move (outer_attrs), tok->get_locus ()); + case TRY: + // FIXME: is this really a null denotation expression? + return parse_try_expr (std::move (outer_attrs), tok->get_locus ()); case BREAK: // FIXME: is this really a null denotation expression? return parse_break_expr (std::move (outer_attrs), tok->get_locus ()); @@ -12400,8 +12639,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( return parse_continue_expr (std::move (outer_attrs), tok->get_locus ()); case LEFT_CURLY: // ok - this is an expression with block for once. - return parse_block_expr (std::move (outer_attrs), - AST::LoopLabel::error (), tok->get_locus ()); + return parse_block_expr (std::move (outer_attrs), tl::nullopt, + tok->get_locus ()); case IF: // if or if let, so more lookahead to find out if (lexer.peek_token ()->get_id () == LET) @@ -12417,7 +12656,7 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( case LIFETIME: return parse_labelled_loop_expr (tok, std::move (outer_attrs)); case LOOP: - return parse_loop_expr (std::move (outer_attrs), AST::LoopLabel::error (), + return parse_loop_expr (std::move (outer_attrs), tl::nullopt, tok->get_locus ()); case WHILE: if (lexer.peek_token ()->get_id () == LET) @@ -12426,13 +12665,11 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( } else { - return parse_while_loop_expr (std::move (outer_attrs), - AST::LoopLabel::error (), + return parse_while_loop_expr (std::move (outer_attrs), tl::nullopt, tok->get_locus ()); } case FOR: - return parse_for_loop_expr (std::move (outer_attrs), - AST::LoopLabel::error ()); + return parse_for_loop_expr (std::move (outer_attrs), tl::nullopt); case MATCH_KW: // also an expression with block return parse_match_expr (std::move (outer_attrs), tok->get_locus ()); @@ -12450,6 +12687,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( "use of %qs is not allowed on the right-side of an assignment", tok->get_token_description ())); return nullptr; + case CONST: + return parse_const_block_expr (std::move (outer_attrs), + tok->get_locus ()); default: if (!restrictions.expr_can_be_null) add_error (Error (tok->get_locus (), @@ -12472,8 +12712,9 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok, // Token passed in has already been skipped, so peek gives "next" token switch (tok->get_id ()) { - // FIXME: allow for outer attributes to be applied - case QUESTION_MARK: { + // FIXME: allow for outer attributes to be applied + case QUESTION_MARK: + { location_t left_locus = left->get_locus (); // error propagation expression - unary postfix return std::unique_ptr<AST::ErrorPropagationExpr> ( @@ -12727,7 +12968,8 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok, "function - this should probably be handled elsewhere")); return nullptr; - case DOT: { + case DOT: + { /* field expression or method call - relies on parentheses after next * identifier or await if token after is "await" (unary postfix) or * tuple index if token after is a decimal int literal */ @@ -12801,12 +13043,6 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok, // array or slice index expression (pseudo binary infix) return parse_index_expr (tok, std::move (left), std::move (outer_attrs), restrictions); - case FLOAT_LITERAL: - /* HACK: get around lexer mis-identifying '.0' or '.1' or whatever as a - * float literal - TODO does this happen anymore? It shouldn't. */ - return parse_tuple_index_expr_float (tok, std::move (left), - std::move (outer_attrs), - restrictions); default: add_error (Error (tok->get_locus (), "found unexpected token %qs in left denotation", @@ -14043,7 +14279,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_struct_partial ( * algorithm should work too. As such, AST type not happening. */ case IDENTIFIER: case HASH: - case INT_LITERAL: { + case INT_LITERAL: + { // struct with struct expr fields // parse struct expr fields @@ -14201,119 +14438,6 @@ Parser<ManagedTokenSource>::parse_struct_expr_tuple_partial ( std::move (outer_attrs), path_locus)); } -/* Parses a path in expression with the first token passed as a parameter (as - * it is skipped in token stream). Note that this only parses segment-first - * paths, not global ones. */ -template <typename ManagedTokenSource> -AST::PathInExpression -Parser<ManagedTokenSource>::parse_path_in_expression_pratt (const_TokenPtr tok) -{ - // HACK-y way of making up for pratt-parsing consuming first token - - // DEBUG - rust_debug ("current peek token when starting path pratt parse: '%s'", - lexer.peek_token ()->get_token_description ()); - - // create segment vector - std::vector<AST::PathExprSegment> segments; - - std::string initial_str; - - switch (tok->get_id ()) - { - case IDENTIFIER: - initial_str = tok->get_str (); - break; - case SUPER: - initial_str = Values::Keywords::SUPER; - break; - case SELF: - initial_str = Values::Keywords::SELF; - break; - case SELF_ALIAS: - initial_str = Values::Keywords::SELF_ALIAS; - break; - case CRATE: - initial_str = Values::Keywords::CRATE; - break; - case DOLLAR_SIGN: - if (lexer.peek_token ()->get_id () == CRATE) - { - initial_str = "$crate"; - break; - } - gcc_fallthrough (); - default: - add_error (Error (tok->get_locus (), - "unrecognised token %qs in path in expression", - tok->get_token_description ())); - - return AST::PathInExpression::create_error (); - } - - // parse required initial segment - AST::PathExprSegment initial_segment (initial_str, tok->get_locus ()); - // parse generic args (and turbofish), if they exist - /* use lookahead to determine if they actually exist (don't want to - * accidently parse over next ident segment) */ - if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION - && lexer.peek_token (1)->get_id () == LEFT_ANGLE) - { - // skip scope resolution - lexer.skip_token (); - - AST::GenericArgs generic_args = parse_path_generic_args (); - - initial_segment - = AST::PathExprSegment (AST::PathIdentSegment (initial_str, - tok->get_locus ()), - tok->get_locus (), std::move (generic_args)); - } - if (initial_segment.is_error ()) - { - // skip after somewhere? - // don't necessarily throw error but yeah - - // DEBUG - rust_debug ("initial segment is error - returning null"); - - return AST::PathInExpression::create_error (); - } - segments.push_back (std::move (initial_segment)); - - // parse optional segments (as long as scope resolution operator exists) - const_TokenPtr t = lexer.peek_token (); - while (t->get_id () == SCOPE_RESOLUTION) - { - // skip scope resolution operator - lexer.skip_token (); - - // parse the actual segment - it is an error if it doesn't exist now - AST::PathExprSegment segment = parse_path_expr_segment (); - if (segment.is_error ()) - { - // skip after somewhere? - Error error (t->get_locus (), - "could not parse path expression segment"); - add_error (std::move (error)); - - return AST::PathInExpression::create_error (); - } - - segments.push_back (std::move (segment)); - - t = lexer.peek_token (); - } - - // DEBUG: - rust_debug ( - "current token (just about to return path to null denotation): '%s'", - lexer.peek_token ()->get_token_description ()); - - return AST::PathInExpression (std::move (segments), {}, tok->get_locus (), - false); -} - // Parses a closure expression with pratt parsing (from null denotation). template <typename ManagedTokenSource> std::unique_ptr<AST::ClosureExpr> @@ -14340,7 +14464,8 @@ Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok, case OR: // no parameters, don't skip token break; - case PIPE: { + case PIPE: + { // actually may have parameters // don't skip token const_TokenPtr t = lexer.peek_token (); @@ -14450,35 +14575,6 @@ Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok, } } -/* Parses a tuple index expression (pratt-parsed) from a 'float' token as a - * result of lexer misidentification. */ -template <typename ManagedTokenSource> -std::unique_ptr<AST::TupleIndexExpr> -Parser<ManagedTokenSource>::parse_tuple_index_expr_float ( - const_TokenPtr tok, std::unique_ptr<AST::Expr> tuple_expr, - AST::AttrVec outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) -{ - // only works on float literals - if (tok->get_id () != FLOAT_LITERAL) - return nullptr; - - // DEBUG: - rust_debug ("exact string form of float: '%s'", tok->get_str ().c_str ()); - - // get float string and remove dot and initial 0 - std::string index_str = tok->get_str (); - index_str.erase (index_str.begin ()); - - // get int from string - int index = atoi (index_str.c_str ()); - - location_t locus = tuple_expr->get_locus (); - - return std::unique_ptr<AST::TupleIndexExpr> ( - new AST::TupleIndexExpr (std::move (tuple_expr), index, - std::move (outer_attrs), locus)); -} - // Returns true if the next token is END, ELSE, or EOF; template <typename ManagedTokenSource> bool diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc index 43d15aa..860fd11 100644 --- a/gcc/rust/parse/rust-parse.cc +++ b/gcc/rust/parse/rust-parse.cc @@ -42,8 +42,7 @@ extract_module_path (const AST::AttrVec &inner_attrs, { rust_error_at ( path_attr.get_locus (), - // Split the format string so that -Wformat-diag does not complain... - "path attributes must contain a filename: '%s'", "#![path = \"file\"]"); + "path attributes must contain a filename: %<#[path = \"file\"]%>"); return name; } @@ -67,8 +66,7 @@ extract_module_path (const AST::AttrVec &inner_attrs, { rust_error_at ( path_attr.get_locus (), - // Split the format string so that -Wformat-diag does not complain... - "path attributes must contain a filename: '%s'", "#[path = \"file\"]"); + "path attributes must contain a filename: %<#[path = \"file\"]%>"); return name; } @@ -80,6 +78,15 @@ extract_module_path (const AST::AttrVec &inner_attrs, // a character that is not an equal sign or whitespace auto filename_begin = path_value.find_first_not_of ("=\t "); + // If the path consists of only whitespace, then we have an error + if (filename_begin == std::string::npos) + { + rust_error_at ( + path_attr.get_locus (), + "path attributes must contain a filename: %<#[path = \"file\"]%>"); + return name; + } + auto path = path_value.substr (filename_begin); // On windows, the path might mix '/' and '\' separators. Replace the @@ -144,10 +151,9 @@ peculiar_fragment_match_compatible_fragment ( = contains (fragment_follow_set[last_spec.get_kind ()], spec.get_kind ()); if (!is_valid) - rust_error_at ( - match_locus, - "fragment specifier %qs is not allowed after %qs fragments", - spec.as_string ().c_str (), last_spec.as_string ().c_str ()); + rust_error_at (match_locus, + "fragment specifier %qs is not allowed after %qs fragments", + spec.as_string ().c_str (), last_spec.as_string ().c_str ()); return is_valid; } @@ -244,7 +250,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, // the error. switch (match.get_macro_match_type ()) { - case AST::MacroMatch::Tok: { + case AST::MacroMatch::Tok: + { auto tok = static_cast<const AST::Token *> (&match); if (contains (allowed_toks, tok->get_id ())) return true; @@ -254,7 +261,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, break; } break; - case AST::MacroMatch::Repetition: { + case AST::MacroMatch::Repetition: + { auto repetition = static_cast<const AST::MacroMatchRepetition *> (&match); auto &matches = repetition->get_matches (); @@ -263,7 +271,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, return peculiar_fragment_match_compatible (last_match, *first_frag); break; } - case AST::MacroMatch::Matcher: { + case AST::MacroMatch::Matcher: + { auto matcher = static_cast<const AST::MacroMatcher *> (&match); auto first_token = matcher->get_delim_type (); TokenId delim_id; @@ -289,7 +298,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, error_locus = matcher->get_match_locus (); break; } - case AST::MacroMatch::Fragment: { + case AST::MacroMatch::Fragment: + { auto last_spec = last_match.get_frag_spec (); auto fragment = static_cast<const AST::MacroMatchFragment *> (&match); if (last_spec.has_follow_set_fragment_restrictions ()) @@ -328,10 +338,11 @@ is_match_compatible (const AST::MacroMatch &last_match, switch (last_match.get_macro_match_type ()) { - // This is our main stop condition: When we are finally looking at the - // last match (or its actual last component), and it is a fragment, it - // may contain some follow up restrictions. - case AST::MacroMatch::Fragment: { + // This is our main stop condition: When we are finally looking at the + // last match (or its actual last component), and it is a fragment, it + // may contain some follow up restrictions. + case AST::MacroMatch::Fragment: + { auto fragment = static_cast<const AST::MacroMatchFragment *> (&last_match); if (fragment->get_frag_spec ().has_follow_set_restrictions ()) @@ -339,7 +350,8 @@ is_match_compatible (const AST::MacroMatch &last_match, else return true; } - case AST::MacroMatch::Repetition: { + case AST::MacroMatch::Repetition: + { // A repetition on the left hand side means we want to make sure the // last match of the repetition is compatible with the new match auto repetition diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 6c50ba9..7b40463 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -17,6 +17,7 @@ along with GCC; see the file COPYING3. If not see #ifndef RUST_PARSE_H #define RUST_PARSE_H +#include "rust-ast.h" #include "rust-item.h" #include "rust-lex.h" #include "rust-ast-full.h" @@ -25,6 +26,33 @@ along with GCC; see the file COPYING3. If not see #include "expected.h" namespace Rust { + +class ParseLifetimeParamError +{ +}; + +class ParseLifetimeError +{ +}; + +enum class AnonConstError +{ + InvalidSizeExpr, +}; + +enum class ParseLoopLabelError +{ + NOT_LOOP_LABEL, + MISSING_COLON, +}; + +enum class ParseSelfError +{ + SELF_PTR, + PARSING, + NOT_SELF, +}; + /* HACK: used to resolve the expression-or-statement problem at the end of a * block by allowing either to be returned (technically). Tagged union would * probably take up the same amount of space. */ @@ -95,12 +123,6 @@ struct ParseRestrictions bool allow_close_after_expr_stmt = false; }; -enum ParseSelfError -{ - SELF_PTR, - PARSING, - NOT_SELF, -}; // Parser implementation for gccrs. // TODO: if updated to C++20, ManagedTokenSource would be useful as a concept template <typename ManagedTokenSource> class Parser @@ -148,9 +170,15 @@ public: std::unique_ptr<AST::BlockExpr> parse_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), - AST::LoopLabel label = AST::LoopLabel::error (), + tl::optional<AST::LoopLabel> = tl::nullopt, location_t pratt_parsed_loc = UNKNOWN_LOCATION); + tl::expected<AST::AnonConst, AnonConstError> parse_anon_const (); + + std::unique_ptr<AST::ConstBlock> + parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + location_t loc = UNKNOWN_LOCATION); + bool is_macro_rules_def (const_TokenPtr t); std::unique_ptr<AST::Item> parse_item (bool called_from_statement); std::unique_ptr<AST::Pattern> parse_pattern (); @@ -184,6 +212,11 @@ public: std::unique_ptr<AST::MacroInvocation> parse_macro_invocation (AST::AttrVec outer_attrs); + /* + * This has to be public for parsing expressions with outer attributes + */ + AST::AttrVec parse_outer_attributes (); + private: void skip_after_semicolon (); void skip_after_end (); @@ -200,7 +233,6 @@ private: // AST-related stuff - maybe move or something? AST::Attribute parse_inner_attribute (); - AST::AttrVec parse_outer_attributes (); AST::Attribute parse_outer_attribute (); std::unique_ptr<AST::AttrInput> parse_attr_input (); std::tuple<AST::SimplePath, std::unique_ptr<AST::AttrInput>, location_t> @@ -208,11 +240,11 @@ private: // Path-related AST::SimplePath parse_simple_path (); - AST::SimplePathSegment parse_simple_path_segment (); + AST::SimplePathSegment parse_simple_path_segment (int base_peek = 0); AST::TypePath parse_type_path (); std::unique_ptr<AST::TypePathSegment> parse_type_path_segment (); AST::PathIdentSegment parse_path_ident_segment (); - AST::GenericArg parse_generic_arg (); + tl::optional<AST::GenericArg> parse_generic_arg (); AST::GenericArgs parse_path_generic_args (); AST::GenericArgsBinding parse_generic_args_binding (); AST::TypePathFunction parse_type_path_function (location_t locus); @@ -277,7 +309,8 @@ private: ParseFunction parsing_function, EndTokenPred is_end_token, std::string error_msg = "failed to parse generic param in generic params") -> std::vector<decltype (parsing_function ())>; - AST::LifetimeParam parse_lifetime_param (); + tl::expected<AST::LifetimeParam, ParseLifetimeParamError> + parse_lifetime_param (); std::vector<std::unique_ptr<AST::TypeParam>> parse_type_params (); template <typename EndTokenPred> std::vector<std::unique_ptr<AST::TypeParam>> @@ -306,7 +339,8 @@ private: std::vector<AST::Lifetime> parse_lifetime_bounds (); template <typename EndTokenPred> std::vector<AST::Lifetime> parse_lifetime_bounds (EndTokenPred is_end_token); - AST::Lifetime parse_lifetime (bool allow_elided); + tl::expected<AST::Lifetime, ParseLifetimeError> + parse_lifetime (bool allow_elided); AST::Lifetime lifetime_from_token (const_TokenPtr tok); std::unique_ptr<AST::ExternalTypeItem> parse_external_type_item (AST::Visibility vis, AST::AttrVec outer_attrs); @@ -338,7 +372,7 @@ private: AST::AttrVec outer_attrs); std::unique_ptr<AST::TraitItemType> parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility); - std::unique_ptr<AST::TraitItemConst> + std::unique_ptr<AST::ConstantItem> parse_trait_const (AST::AttrVec outer_attrs); tl::expected<std::unique_ptr<AST::Param>, ParseSelfError> parse_self_param (); @@ -363,7 +397,7 @@ private: AST::AttrVec outer_attrs = AST::AttrVec (), ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr<AST::Expr> - null_denotation (const_TokenPtr t, AST::AttrVec outer_attrs = AST::AttrVec (), + null_denotation (AST::AttrVec outer_attrs = AST::AttrVec (), ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr<AST::Expr> null_denotation_path (AST::PathInExpression path, AST::AttrVec outer_attrs, @@ -568,7 +602,6 @@ private: std::unique_ptr<AST::CallExpr> parse_struct_expr_tuple_partial (AST::PathInExpression path, AST::AttrVec outer_attrs); - AST::PathInExpression parse_path_in_expression_pratt (const_TokenPtr tok); std::unique_ptr<AST::ClosureExpr> parse_closure_expr_pratt (const_TokenPtr tok, AST::AttrVec outer_attrs = AST::AttrVec ()); @@ -588,18 +621,18 @@ private: location_t pratt_parsed_loc = UNKNOWN_LOCATION); std::unique_ptr<AST::LoopExpr> parse_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), - AST::LoopLabel label = AST::LoopLabel::error (), + tl::optional<AST::LoopLabel> label = tl::nullopt, location_t pratt_parsed_loc = UNKNOWN_LOCATION); std::unique_ptr<AST::WhileLoopExpr> parse_while_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), - AST::LoopLabel label = AST::LoopLabel::error (), + tl::optional<AST::LoopLabel> label = tl::nullopt, location_t pratt_parsed_loc = UNKNOWN_LOCATION); std::unique_ptr<AST::WhileLetLoopExpr> parse_while_let_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), - AST::LoopLabel label = AST::LoopLabel::error ()); + tl::optional<AST::LoopLabel> label = tl::nullopt); std::unique_ptr<AST::ForLoopExpr> parse_for_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), - AST::LoopLabel label = AST::LoopLabel::error ()); + tl::optional<AST::LoopLabel> label = tl::nullopt); std::unique_ptr<AST::MatchExpr> parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); @@ -609,7 +642,8 @@ private: std::unique_ptr<AST::Expr> parse_labelled_loop_expr (const_TokenPtr tok, AST::AttrVec outer_attrs = AST::AttrVec ()); - AST::LoopLabel parse_loop_label (const_TokenPtr tok); + tl::expected<AST::LoopLabel, ParseLoopLabelError> + parse_loop_label (const_TokenPtr tok); std::unique_ptr<AST::AsyncBlockExpr> parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ()); std::unique_ptr<AST::GroupedExpr> parse_grouped_expr (AST::AttrVec outer_attrs @@ -627,6 +661,9 @@ private: std::unique_ptr<AST::ReturnExpr> parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); + std::unique_ptr<AST::TryExpr> + parse_try_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + location_t pratt_parsed_loc = UNKNOWN_LOCATION); std::unique_ptr<AST::BreakExpr> parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); @@ -745,11 +782,15 @@ private: } ~InlineModuleStackScope () { parser.inline_module_stack.pop_back (); } }; + + // don't want to make things *only* AttributeParser uses public + // TODO: fold more of AttributeParser into Parser? + friend struct ::Rust::AST::AttributeParser; }; -std::string -extract_module_path (const AST::AttrVec &inner_attrs, - const AST::AttrVec &outer_attrs, const std::string &name); +std::string extract_module_path (const AST::AttrVec &inner_attrs, + const AST::AttrVec &outer_attrs, + const std::string &name); /** * Check if a MacroMatch is allowed to follow the last parsed MacroMatch. @@ -759,12 +800,8 @@ extract_module_path (const AST::AttrVec &inner_attrs, * * @return true if the follow-up is valid, false otherwise */ -bool -is_match_compatible (const AST::MacroMatch &last_match, - const AST::MacroMatch ¤t_match); +bool is_match_compatible (const AST::MacroMatch &last_match, + const AST::MacroMatch ¤t_match); } // namespace Rust -// as now template, include implementations of all methods -#include "rust-parse-impl.h" - #endif // RUST_PARSE_H diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc deleted file mode 100644 index 6c35a22..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ /dev/null @@ -1,663 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-path.h" -#include "rust-item.h" -#include "rust-path.h" - -namespace Rust { -namespace Resolver { - -bool -ResolverBase::resolve_visibility (const AST::Visibility &vis) -{ - if (vis.has_path ()) - { - auto path = vis.get_path (); - ResolvePath::go (path); - - // Do we need to lookup something here? - // Is it just about resolving the names correctly so we can look them up - // later? - } - - return true; -} - -// Default visitors implementations - -void -ResolverBase::visit (AST::Token &) -{} - -void -ResolverBase::visit (AST::DelimTokenTree &) -{} - -void -ResolverBase::visit (AST::AttrInputMetaItemContainer &) -{} - -void -ResolverBase::visit (AST::IdentifierExpr &) -{} - -void -ResolverBase::visit (AST::Lifetime &) -{} - -void -ResolverBase::visit (AST::LifetimeParam &) -{} - -void -ResolverBase::visit (AST::ConstGenericParam &) -{} - -void -ResolverBase::visit (AST::PathInExpression &) -{} - -void -ResolverBase::visit (AST::TypePathSegment &) -{} - -void -ResolverBase::visit (AST::TypePathSegmentGeneric &) -{} - -void -ResolverBase::visit (AST::TypePathSegmentFunction &) -{} - -void -ResolverBase::visit (AST::TypePath &) -{} - -void -ResolverBase::visit (AST::QualifiedPathInExpression &) -{} - -void -ResolverBase::visit (AST::QualifiedPathInType &) -{} - -void -ResolverBase::visit (AST::LiteralExpr &) -{} - -void -ResolverBase::visit (AST::AttrInputLiteral &) -{} - -void -ResolverBase::visit (AST::AttrInputMacro &) -{} - -void -ResolverBase::visit (AST::MetaItemLitExpr &) -{} - -void -ResolverBase::visit (AST::MetaItemPathLit &) -{} - -void -ResolverBase::visit (AST::BorrowExpr &) -{} - -void -ResolverBase::visit (AST::DereferenceExpr &) -{} - -void -ResolverBase::visit (AST::ErrorPropagationExpr &) -{} - -void -ResolverBase::visit (AST::NegationExpr &) -{} - -void -ResolverBase::visit (AST::ArithmeticOrLogicalExpr &) -{} - -void -ResolverBase::visit (AST::ComparisonExpr &) -{} - -void -ResolverBase::visit (AST::LazyBooleanExpr &) -{} - -void -ResolverBase::visit (AST::TypeCastExpr &) -{} - -void -ResolverBase::visit (AST::AssignmentExpr &) -{} - -void -ResolverBase::visit (AST::CompoundAssignmentExpr &) -{} - -void -ResolverBase::visit (AST::GroupedExpr &) -{} - -void -ResolverBase::visit (AST::ArrayElemsValues &) -{} - -void -ResolverBase::visit (AST::ArrayElemsCopied &) -{} - -void -ResolverBase::visit (AST::ArrayExpr &) -{} - -void -ResolverBase::visit (AST::ArrayIndexExpr &) -{} - -void -ResolverBase::visit (AST::TupleExpr &) -{} - -void -ResolverBase::visit (AST::TupleIndexExpr &) -{} - -void -ResolverBase::visit (AST::StructExprStruct &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIdentifier &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIdentifierValue &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIndexValue &) -{} - -void -ResolverBase::visit (AST::StructExprStructFields &) -{} - -void -ResolverBase::visit (AST::StructExprStructBase &) -{} - -void -ResolverBase::visit (AST::CallExpr &) -{} - -void -ResolverBase::visit (AST::MethodCallExpr &) -{} - -void -ResolverBase::visit (AST::FieldAccessExpr &) -{} - -void -ResolverBase::visit (AST::ClosureExprInner &) -{} - -void -ResolverBase::visit (AST::BlockExpr &) -{} - -void -ResolverBase::visit (AST::ClosureExprInnerTyped &) -{} - -void -ResolverBase::visit (AST::ContinueExpr &) -{} - -void -ResolverBase::visit (AST::BreakExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromToExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromExpr &) -{} - -void -ResolverBase::visit (AST::RangeToExpr &) -{} - -void -ResolverBase::visit (AST::RangeFullExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromToInclExpr &) -{} - -void -ResolverBase::visit (AST::RangeToInclExpr &) -{} - -void -ResolverBase::visit (AST::BoxExpr &) -{} - -void -ResolverBase::visit (AST::ReturnExpr &) -{} - -void -ResolverBase::visit (AST::UnsafeBlockExpr &) -{} - -void -ResolverBase::visit (AST::LoopExpr &) -{} - -void -ResolverBase::visit (AST::WhileLoopExpr &) -{} - -void -ResolverBase::visit (AST::WhileLetLoopExpr &) -{} - -void -ResolverBase::visit (AST::ForLoopExpr &) -{} - -void -ResolverBase::visit (AST::IfExpr &) -{} - -void -ResolverBase::visit (AST::IfExprConseqElse &) -{} - -void -ResolverBase::visit (AST::IfLetExpr &) -{} - -void -ResolverBase::visit (AST::IfLetExprConseqElse &) -{} - -void -ResolverBase::visit (AST::MatchExpr &) -{} - -void -ResolverBase::visit (AST::AwaitExpr &) -{} - -void -ResolverBase::visit (AST::AsyncBlockExpr &) -{} - -void -ResolverBase::visit (AST::InlineAsm &) -{} - -void -ResolverBase::visit (AST::TypeParam &) -{} - -void -ResolverBase::visit (AST::LifetimeWhereClauseItem &) -{} - -void -ResolverBase::visit (AST::TypeBoundWhereClauseItem &) -{} - -void -ResolverBase::visit (AST::Module &) -{} - -void -ResolverBase::visit (AST::ExternCrate &) -{} - -void -ResolverBase::visit (AST::UseTreeGlob &) -{} - -void -ResolverBase::visit (AST::UseTreeList &) -{} - -void -ResolverBase::visit (AST::UseTreeRebind &) -{} - -void -ResolverBase::visit (AST::UseDeclaration &) -{} - -void -ResolverBase::visit (AST::Function &) -{} - -void -ResolverBase::visit (AST::TypeAlias &) -{} - -void -ResolverBase::visit (AST::StructStruct &) -{} - -void -ResolverBase::visit (AST::TupleStruct &) -{} - -void -ResolverBase::visit (AST::EnumItem &) -{} - -void -ResolverBase::visit (AST::EnumItemTuple &) -{} - -void -ResolverBase::visit (AST::EnumItemStruct &) -{} - -void -ResolverBase::visit (AST::EnumItemDiscriminant &) -{} - -void -ResolverBase::visit (AST::Enum &) -{} - -void -ResolverBase::visit (AST::Union &) -{} - -void -ResolverBase::visit (AST::ConstantItem &) -{} - -void -ResolverBase::visit (AST::StaticItem &) -{} - -void -ResolverBase::visit (AST::TraitItemConst &) -{} - -void -ResolverBase::visit (AST::TraitItemType &) -{} - -void -ResolverBase::visit (AST::Trait &) -{} - -void -ResolverBase::visit (AST::InherentImpl &) -{} - -void -ResolverBase::visit (AST::TraitImpl &) -{} - -void -ResolverBase::visit (AST::ExternalTypeItem &) -{} - -void -ResolverBase::visit (AST::ExternalStaticItem &) -{} - -void -ResolverBase::visit (AST::ExternBlock &) -{} - -void -ResolverBase::visit (AST::MacroMatchFragment &) -{} - -void -ResolverBase::visit (AST::MacroMatchRepetition &) -{} - -void -ResolverBase::visit (AST::MacroMatcher &) -{} - -void -ResolverBase::visit (AST::MacroRulesDefinition &) -{} - -void -ResolverBase::visit (AST::MacroInvocation &) -{} - -void -ResolverBase::visit (AST::MetaItemPath &) -{} - -void -ResolverBase::visit (AST::MetaItemSeq &) -{} - -void -ResolverBase::visit (AST::MetaWord &) -{} - -void -ResolverBase::visit (AST::MetaNameValueStr &) -{} - -void -ResolverBase::visit (AST::MetaListPaths &) -{} - -void -ResolverBase::visit (AST::MetaListNameValueStr &) -{} - -void -ResolverBase::visit (AST::LiteralPattern &) -{} - -void -ResolverBase::visit (AST::IdentifierPattern &) -{} - -void -ResolverBase::visit (AST::WildcardPattern &) -{} - -void -ResolverBase::visit (AST::RestPattern &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundLiteral &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundPath &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundQualPath &) -{} - -void -ResolverBase::visit (AST::RangePattern &) -{} - -void -ResolverBase::visit (AST::ReferencePattern &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldTuplePat &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldIdentPat &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldIdent &) -{} - -void -ResolverBase::visit (AST::StructPattern &) -{} - -void -ResolverBase::visit (AST::TupleStructItemsNoRange &) -{} - -void -ResolverBase::visit (AST::TupleStructItemsRange &) -{} - -void -ResolverBase::visit (AST::TupleStructPattern &) -{} - -void -ResolverBase::visit (AST::TuplePatternItemsMultiple &) -{} - -void -ResolverBase::visit (AST::TuplePatternItemsRanged &) -{} - -void -ResolverBase::visit (AST::TuplePattern &) -{} - -void -ResolverBase::visit (AST::GroupedPattern &) -{} - -void -ResolverBase::visit (AST::SlicePattern &) -{} - -void -ResolverBase::visit (AST::AltPattern &) -{} - -void -ResolverBase::visit (AST::EmptyStmt &) -{} - -void -ResolverBase::visit (AST::LetStmt &) -{} - -void -ResolverBase::visit (AST::ExprStmt &) -{} - -void -ResolverBase::visit (AST::TraitBound &) -{} - -void -ResolverBase::visit (AST::ImplTraitType &) -{} - -void -ResolverBase::visit (AST::TraitObjectType &) -{} - -void -ResolverBase::visit (AST::ParenthesisedType &) -{} - -void -ResolverBase::visit (AST::ImplTraitTypeOneBound &) -{} - -void -ResolverBase::visit (AST::TraitObjectTypeOneBound &) -{} - -void -ResolverBase::visit (AST::TupleType &) -{} - -void -ResolverBase::visit (AST::NeverType &) -{} - -void -ResolverBase::visit (AST::RawPointerType &) -{} - -void -ResolverBase::visit (AST::ReferenceType &) -{} - -void -ResolverBase::visit (AST::ArrayType &) -{} - -void -ResolverBase::visit (AST::SliceType &) -{} - -void -ResolverBase::visit (AST::InferredType &) -{} - -void -ResolverBase::visit (AST::BareFunctionType &) -{} - -void -ResolverBase::visit (AST::SelfParam &) -{} - -void -ResolverBase::visit (AST::VariadicParam &) -{} - -void -ResolverBase::visit (AST::FunctionParam &) -{} - -void -ResolverBase::visit (AST::FormatArgs &fmt) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h deleted file mode 100644 index 0d497f8..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ /dev/null @@ -1,224 +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_AST_RESOLVE_BASE_H -#define RUST_AST_RESOLVE_BASE_H - -#include "rust-ast-visitor.h" -#include "rust-ast.h" -#include "rust-name-resolver.h" -#include "rust-diagnostics.h" -#include "rust-location.h" - -namespace Rust { -namespace Resolver { - -class ResolverBase : public AST::ASTVisitor -{ -public: - virtual ~ResolverBase () {} - - void visit (AST::Token &); - void visit (AST::DelimTokenTree &); - void visit (AST::AttrInputMetaItemContainer &); - void visit (AST::IdentifierExpr &); - void visit (AST::Lifetime &); - void visit (AST::LifetimeParam &); - void visit (AST::ConstGenericParam &); - void visit (AST::PathInExpression &); - void visit (AST::TypePathSegment &); - void visit (AST::TypePathSegmentGeneric &); - void visit (AST::TypePathSegmentFunction &); - void visit (AST::TypePath &); - void visit (AST::QualifiedPathInExpression &); - void visit (AST::QualifiedPathInType &); - void visit (AST::LiteralExpr &); - void visit (AST::AttrInputLiteral &); - void visit (AST::AttrInputMacro &); - void visit (AST::MetaItemLitExpr &); - void visit (AST::MetaItemPathLit &); - void visit (AST::BorrowExpr &); - void visit (AST::DereferenceExpr &); - void visit (AST::ErrorPropagationExpr &); - void visit (AST::NegationExpr &); - void visit (AST::ArithmeticOrLogicalExpr &); - void visit (AST::ComparisonExpr &); - void visit (AST::LazyBooleanExpr &); - void visit (AST::TypeCastExpr &); - void visit (AST::AssignmentExpr &); - void visit (AST::CompoundAssignmentExpr &); - void visit (AST::GroupedExpr &); - void visit (AST::ArrayElemsValues &); - void visit (AST::ArrayElemsCopied &); - void visit (AST::ArrayExpr &); - void visit (AST::ArrayIndexExpr &); - void visit (AST::TupleExpr &); - void visit (AST::TupleIndexExpr &); - void visit (AST::StructExprStruct &); - void visit (AST::StructExprFieldIdentifier &); - void visit (AST::StructExprFieldIdentifierValue &); - void visit (AST::StructExprFieldIndexValue &); - void visit (AST::StructExprStructFields &); - void visit (AST::StructExprStructBase &); - void visit (AST::CallExpr &); - void visit (AST::MethodCallExpr &); - void visit (AST::FieldAccessExpr &); - void visit (AST::ClosureExprInner &); - void visit (AST::BlockExpr &); - void visit (AST::ClosureExprInnerTyped &); - void visit (AST::ContinueExpr &); - void visit (AST::BreakExpr &); - void visit (AST::RangeFromToExpr &); - void visit (AST::RangeFromExpr &); - void visit (AST::RangeToExpr &); - void visit (AST::RangeFullExpr &); - void visit (AST::RangeFromToInclExpr &); - void visit (AST::RangeToInclExpr &); - void visit (AST::BoxExpr &); - void visit (AST::ReturnExpr &); - void visit (AST::UnsafeBlockExpr &); - void visit (AST::LoopExpr &); - void visit (AST::WhileLoopExpr &); - void visit (AST::WhileLetLoopExpr &); - void visit (AST::ForLoopExpr &); - void visit (AST::IfExpr &); - void visit (AST::IfExprConseqElse &); - void visit (AST::IfLetExpr &); - void visit (AST::IfLetExprConseqElse &); - - void visit (AST::MatchExpr &); - void visit (AST::AwaitExpr &); - void visit (AST::AsyncBlockExpr &); - void visit (AST::InlineAsm &); - - void visit (AST::TypeParam &); - - void visit (AST::LifetimeWhereClauseItem &); - void visit (AST::TypeBoundWhereClauseItem &); - void visit (AST::Module &); - void visit (AST::ExternCrate &); - - void visit (AST::UseTreeGlob &); - void visit (AST::UseTreeList &); - void visit (AST::UseTreeRebind &); - void visit (AST::UseDeclaration &); - void visit (AST::Function &); - void visit (AST::TypeAlias &); - void visit (AST::StructStruct &); - void visit (AST::TupleStruct &); - void visit (AST::EnumItem &); - void visit (AST::EnumItemTuple &); - void visit (AST::EnumItemStruct &); - void visit (AST::EnumItemDiscriminant &); - void visit (AST::Enum &); - void visit (AST::Union &); - void visit (AST::ConstantItem &); - void visit (AST::StaticItem &); - void visit (AST::TraitItemConst &); - void visit (AST::TraitItemType &); - void visit (AST::Trait &); - void visit (AST::InherentImpl &); - void visit (AST::TraitImpl &); - - void visit (AST::ExternalTypeItem &); - void visit (AST::ExternalStaticItem &); - void visit (AST::ExternBlock &); - - void visit (AST::MacroMatchFragment &); - void visit (AST::MacroMatchRepetition &); - void visit (AST::MacroMatcher &); - void visit (AST::MacroRulesDefinition &); - void visit (AST::MacroInvocation &); - void visit (AST::MetaItemPath &); - void visit (AST::MetaItemSeq &); - void visit (AST::MetaWord &); - void visit (AST::MetaNameValueStr &); - void visit (AST::MetaListPaths &); - void visit (AST::MetaListNameValueStr &); - - void visit (AST::LiteralPattern &); - void visit (AST::IdentifierPattern &); - void visit (AST::WildcardPattern &); - void visit (AST::RestPattern &); - - void visit (AST::RangePatternBoundLiteral &); - void visit (AST::RangePatternBoundPath &); - void visit (AST::RangePatternBoundQualPath &); - void visit (AST::RangePattern &); - void visit (AST::ReferencePattern &); - - void visit (AST::StructPatternFieldTuplePat &); - void visit (AST::StructPatternFieldIdentPat &); - void visit (AST::StructPatternFieldIdent &); - void visit (AST::StructPattern &); - - void visit (AST::TupleStructItemsNoRange &); - void visit (AST::TupleStructItemsRange &); - void visit (AST::TupleStructPattern &); - - void visit (AST::TuplePatternItemsMultiple &); - void visit (AST::TuplePatternItemsRanged &); - void visit (AST::TuplePattern &); - void visit (AST::GroupedPattern &); - void visit (AST::SlicePattern &); - void visit (AST::AltPattern &); - - void visit (AST::EmptyStmt &); - void visit (AST::LetStmt &); - void visit (AST::ExprStmt &); - - void visit (AST::TraitBound &); - void visit (AST::ImplTraitType &); - void visit (AST::TraitObjectType &); - void visit (AST::ParenthesisedType &); - void visit (AST::ImplTraitTypeOneBound &); - void visit (AST::TraitObjectTypeOneBound &); - void visit (AST::TupleType &); - void visit (AST::NeverType &); - void visit (AST::RawPointerType &); - void visit (AST::ReferenceType &); - void visit (AST::ArrayType &); - void visit (AST::SliceType &); - void visit (AST::InferredType &); - void visit (AST::BareFunctionType &); - void visit (AST::FunctionParam ¶m); - void visit (AST::VariadicParam ¶m); - void visit (AST::SelfParam ¶m); - - void visit (AST::FormatArgs &fmt); - -protected: - ResolverBase () - : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()), - resolved_node (UNKNOWN_NODEID) - {} - - /** - * Resolve a visibility's path through the name resolver - */ - bool resolve_visibility (const AST::Visibility &vis); - - Resolver *resolver; - Analysis::Mappings &mappings; - NodeId resolved_node; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_BASE_H diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc deleted file mode 100644 index dc7f76d..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ /dev/null @@ -1,785 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-stmt.h" -#include "rust-ast-resolve-struct-expr-field.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" -#include "rust-expr.h" -#include "rust-ice-finalizer.h" - -namespace Rust { -namespace Resolver { - -void -ResolveExpr::go (AST::Expr &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, bool funny_error) -{ - ResolveExpr resolver (prefix, canonical_prefix, funny_error); - expr.accept_vis (resolver); -} - -void -ResolveExpr::visit (AST::TupleIndexExpr &expr) -{ - ResolveExpr::go (expr.get_tuple_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::TupleExpr &expr) -{ - if (expr.is_unit ()) - return; - - for (auto &elem : expr.get_tuple_elems ()) - ResolveExpr::go (*elem, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::PathInExpression &expr) -{ - ResolvePath::go (expr); -} - -void -ResolveExpr::visit (AST::QualifiedPathInExpression &expr) -{ - ResolvePath::go (expr); -} - -void -ResolveExpr::visit (AST::ReturnExpr &expr) -{ - if (expr.has_returned_expr ()) - ResolveExpr::go (expr.get_returned_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::CallExpr &expr) -{ - ResolveExpr::go (expr.get_function_expr (), prefix, canonical_prefix); - for (auto ¶m : expr.get_params ()) - ResolveExpr::go (*param, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::MethodCallExpr &expr) -{ - ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix); - - if (expr.get_method_name ().has_generic_args ()) - { - AST::GenericArgs &args = expr.get_method_name ().get_generic_args (); - ResolveGenericArgs::go (args, prefix, canonical_prefix); - } - - auto const &in_params = expr.get_params (); - for (auto ¶m : in_params) - ResolveExpr::go (*param, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ErrorPropagationExpr &expr) -{ - ResolveExpr::go (expr.get_propagating_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::AssignmentExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IdentifierExpr &expr) -{ - if (resolver->get_name_scope ().lookup ( - CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), - &resolved_node)) - { - resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - } - else if (resolver->get_type_scope ().lookup ( - CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), - &resolved_node)) - { - resolver->insert_resolved_type (expr.get_node_id (), resolved_node); - } - else if (funny_error) - { - /* This was a "break rust" or "break gcc", and the identifier failed to - resolve. Emit a funny ICE. We set the finalizer to our custom one, - and use the lower-level emit_diagnostic () instead of the more common - internal_error_no_backtrace () in order to pass our locus. */ - diagnostic_text_finalizer (global_dc) = funny_ice_text_finalizer; - emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1, - "are you trying to break %s? how dare you?", - expr.as_string ().c_str ()); - } - else - { - rust_error_at (expr.get_locus (), ErrorCode::E0425, - "cannot find value %qs in this scope", - expr.as_string ().c_str ()); - } -} - -void -ResolveExpr::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::CompoundAssignmentExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ComparisonExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LazyBooleanExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::NegationExpr &expr) -{ - ResolveExpr::go (expr.get_negated_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::TypeCastExpr &expr) -{ - ResolveType::go (expr.get_type_to_cast_to ()); - ResolveExpr::go (expr.get_casted_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfExpr &expr) -{ - ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfExprConseqElse &expr) -{ - ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfLetExpr &expr) -{ - ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix); - - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &pattern : expr.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::IfLetExprConseqElse &expr) -{ - ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix); - - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &pattern : expr.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::BlockExpr &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (expr.has_label ()) - { - auto label = expr.get_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - for (auto &s : expr.get_statements ()) - { - if (s->is_item ()) - ResolveStmt::go (*s, prefix, canonical_prefix, - CanonicalPath::create_empty ()); - } - - for (auto &s : expr.get_statements ()) - { - if (!s->is_item ()) - ResolveStmt::go (*s, prefix, canonical_prefix, - CanonicalPath::create_empty ()); - } - - if (expr.has_tail_expr ()) - ResolveExpr::go (expr.get_tail_expr (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - const auto &operands = expr.get_operands (); - using RegisterType = AST::InlineAsmOperand::RegisterType; - for (auto &operand : operands) - { - switch (operand.get_register_type ()) - { - case RegisterType::In: { - auto in = operand.get_in (); - ResolveExpr::go (*in.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Out: { - auto out = operand.get_out (); - ResolveExpr::go (*out.expr, prefix, canonical_prefix); - break; - } - case RegisterType::InOut: { - auto in_out = operand.get_in_out (); - ResolveExpr::go (*in_out.expr, prefix, canonical_prefix); - break; - } - case RegisterType::SplitInOut: { - auto split_in_out = operand.get_split_in_out (); - ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix); - ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix); - break; - } - case RegisterType::Const: { - auto anon_const = operand.get_const ().anon_const; - ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Sym: { - auto sym = operand.get_sym (); - ResolveExpr::go (*sym.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Label: { - auto label = operand.get_label (); - ResolveExpr::go (*label.expr, prefix, canonical_prefix); - break; - } - } - } -} -void -ResolveExpr::visit (AST::InlineAsm &expr) -{ - translate_operand (expr, prefix, canonical_prefix); -} -void -ResolveExpr::visit (AST::UnsafeBlockExpr &expr) -{ - expr.get_block_expr ().accept_vis (*this); -} - -void -ResolveExpr::visit (AST::ArrayElemsValues &elems) -{ - for (auto &elem : elems.get_values ()) - ResolveExpr::go (*elem, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ArrayExpr &expr) -{ - expr.get_array_elems ()->accept_vis (*this); -} - -void -ResolveExpr::visit (AST::ArrayIndexExpr &expr) -{ - ResolveExpr::go (expr.get_array_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_index_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ArrayElemsCopied &expr) -{ - ResolveExpr::go (expr.get_num_copies (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_elem_to_copy (), prefix, canonical_prefix); -} - -// this this an empty struct constructor like 'S {}' -void -ResolveExpr::visit (AST::StructExprStruct &struct_expr) -{ - ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix); -} - -// this this a struct constructor with fields -void -ResolveExpr::visit (AST::StructExprStructFields &struct_expr) -{ - ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix); - - if (struct_expr.has_struct_base ()) - { - AST::StructBase &base = struct_expr.get_struct_base (); - ResolveExpr::go (base.get_base_struct (), prefix, canonical_prefix); - } - - auto const &struct_fields = struct_expr.get_fields (); - for (auto &struct_field : struct_fields) - { - ResolveStructExprField::go (*struct_field, prefix, canonical_prefix); - } -} - -void -ResolveExpr::visit (AST::GroupedExpr &expr) -{ - ResolveExpr::go (expr.get_expr_in_parens (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::FieldAccessExpr &expr) -{ - ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (expr.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::BreakExpr &expr) -{ - if (expr.has_label ()) - { - auto label = expr.get_label ().get_lifetime (); - if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup ( - CanonicalPath::new_seg (label.get_node_id (), - label.get_lifetime_name ()), - &resolved_node)) - { - rust_error_at (label.get_locus (), ErrorCode::E0426, - "use of undeclared label %qs in %<break%>", - label.get_lifetime_name ().c_str ()); - return; - } - resolver->insert_resolved_label (label.get_node_id (), resolved_node); - } - - if (expr.has_break_expr ()) - { - bool funny_error = false; - auto &break_expr = expr.get_break_expr (); - if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier) - { - /* This is a break with an expression, and the expression is - just a single identifier. See if the identifier is either - "rust" or "gcc", in which case we have "break rust" or "break - gcc", and so may need to emit our funny error. We cannot yet - emit the error here though, because the identifier may still - be in scope, and ICE'ing on valid programs would not be very - funny. */ - std::string ident - = static_cast<AST::IdentifierExpr &> (break_expr).as_string (); - if (ident == "rust" || ident == "gcc") - funny_error = true; - } - ResolveExpr::go (break_expr, prefix, canonical_prefix, funny_error); - } -} - -void -ResolveExpr::visit (AST::WhileLoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - ResolveExpr::go (expr.get_predicate_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ForLoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - // this needs a new rib to contain the pattern - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve the expression - PatternDeclaration::go (expr.get_pattern (), Rib::ItemType::Var); - ResolveExpr::go (expr.get_iterator_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::ContinueExpr &expr) -{ - if (expr.has_label ()) - { - auto label = expr.get_label (); - if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup ( - CanonicalPath::new_seg (label.get_node_id (), - label.get_lifetime_name ()), - &resolved_node)) - { - rust_error_at (expr.get_label ().get_locus (), ErrorCode::E0426, - "use of undeclared label %qs in %<continue%>", - label.get_lifetime_name ().c_str ()); - return; - } - resolver->insert_resolved_label (label.get_node_id (), resolved_node); - } -} - -void -ResolveExpr::visit (AST::BorrowExpr &expr) -{ - ResolveExpr::go (expr.get_borrowed_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::DereferenceExpr &expr) -{ - ResolveExpr::go (expr.get_dereferenced_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::MatchExpr &expr) -{ - ResolveExpr::go (expr.get_scrutinee_expr (), prefix, canonical_prefix); - for (auto &match_case : expr.get_match_cases ()) - { - // each arm is in its own scope - NodeId scope_node_id = match_case.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve - AST::MatchArm &arm = match_case.get_arm (); - if (arm.has_match_arm_guard ()) - ResolveExpr::go (arm.get_guard_expr (), prefix, canonical_prefix); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // insert any possible new patterns - for (auto &pattern : arm.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - // resolve the body - ResolveExpr::go (match_case.get_expr (), prefix, canonical_prefix); - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - } -} - -void -ResolveExpr::visit (AST::RangeFromToExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeFromExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeToExpr &expr) -{ - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeFullExpr &) -{ - // nothing to do -} - -void -ResolveExpr::visit (AST::RangeFromToInclExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ClosureExprInner &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &p : expr.get_params ()) - { - resolve_closure_param (p, bindings); - } - - resolver->push_closure_context (expr.get_node_id ()); - - ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); - - resolver->pop_closure_context (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::ClosureExprInnerTyped &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &p : expr.get_params ()) - { - resolve_closure_param (p, bindings); - } - - ResolveType::go (expr.get_return_type ()); - - resolver->push_closure_context (expr.get_node_id ()); - - ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix); - - resolver->pop_closure_context (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m, - std::vector<PatternBinding> &bindings) -{ - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, bindings); - - if (param.has_type_given ()) - ResolveType::go (param.get_type ()); -} - -ResolveExpr::ResolveExpr (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - bool funny_error) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix), - funny_error (funny_error) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h deleted file mode 100644 index 562a3bd..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ /dev/null @@ -1,102 +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_AST_RESOLVE_EXPR_H -#define RUST_AST_RESOLVE_EXPR_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-expr.h" - -namespace Rust { -namespace Resolver { - -class ResolveExpr : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Expr &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - bool funny_error = false); - - void visit (AST::TupleIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::PathInExpression &expr) override; - void visit (AST::QualifiedPathInExpression &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; - void visit (AST::AssignmentExpr &expr) override; - void visit (AST::IdentifierExpr &expr) override; - void visit (AST::ArithmeticOrLogicalExpr &expr) override; - void visit (AST::CompoundAssignmentExpr &expr) override; - void visit (AST::ComparisonExpr &expr) override; - void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::NegationExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; - void visit (AST::IfExpr &expr) override; - void visit (AST::IfExprConseqElse &expr) override; - void visit (AST::IfLetExpr &expr) override; - void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::BlockExpr &expr) override; - void visit (AST::InlineAsm &expr) override; - void visit (AST::UnsafeBlockExpr &expr) override; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::ArrayElemsCopied &elems) override; - void visit (AST::StructExprStruct &struct_expr) override; - void visit (AST::StructExprStructFields &struct_expr) override; - void visit (AST::GroupedExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::ContinueExpr &expr) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; - void visit (AST::MatchExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &expr) override; - void visit (AST::RangeFromToInclExpr &expr) override; - void visit (AST::ClosureExprInner &expr) override; - void visit (AST::ClosureExprInnerTyped &expr) override; - void visit (AST::ErrorPropagationExpr &expr) override; - -protected: - void resolve_closure_param (AST::ClosureParam ¶m, - std::vector<PatternBinding> &bindings); - -private: - ResolveExpr (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, bool funny_error); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; - bool funny_error; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_EXPR_H diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h deleted file mode 100644 index 971bf8f..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ /dev/null @@ -1,261 +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_AST_RESOLVE_IMPLITEM_H -#define RUST_AST_RESOLVE_IMPLITEM_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-full.h" - -namespace Rust { -namespace Resolver { - -class ResolveToplevelImplItem : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::AssociatedItem &item, const CanonicalPath &prefix) - { - if (item.is_marked_for_strip ()) - return; - - ResolveToplevelImplItem resolver (prefix); - item.accept_vis (resolver); - } - - void visit (AST::TypeAlias &type) override - { - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_new_type_name ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - } - - void visit (AST::ConstantItem &constant) override - { - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - } - -private: - ResolveToplevelImplItem (const CanonicalPath &prefix) - : ResolverBase (), prefix (prefix) - { - rust_assert (!prefix.is_empty ()); - } - - const CanonicalPath &prefix; -}; - -class ResolveTopLevelTraitItems : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveTopLevelTraitItems resolver (prefix, canonical_prefix); - item->accept_vis (resolver); - }; - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - } - - void visit (AST::TraitItemConst &constant) override - { - auto decl - = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - mappings.insert_canonical_path (constant.get_node_id (), cpath); - } - - void visit (AST::TraitItemType &type) override - { - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - mappings.insert_canonical_path (type.get_node_id (), cpath); - } - -private: - ResolveTopLevelTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveToplevelExternItem : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::ExternalItem &item, const CanonicalPath &prefix) - { - ResolveToplevelExternItem resolver (prefix); - item.accept_vis (resolver); - }; - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - } - - void visit (AST::ExternalStaticItem &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, - Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - } - - void visit (AST::ExternalTypeItem &type) override - { - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - } - -private: - ResolveToplevelExternItem (const CanonicalPath &prefix) - : ResolverBase (), prefix (prefix) - {} - - const CanonicalPath &prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_IMPLITEM_H diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc deleted file mode 100644 index d584961..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ /dev/null @@ -1,1250 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve-item.h" -#include "rust-ast-full-decls.h" -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" - -#include "rust-item.h" -#include "selftest.h" - -namespace Rust { -namespace Resolver { - -ResolveTraitItems::ResolveTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveTraitItems::go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - if (item->is_marked_for_strip ()) - return; - - ResolveTraitItems resolver (prefix, canonical_prefix); - item->accept_vis (resolver); -} - -void -ResolveTraitItems::visit (AST::Function &function) -{ - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - // self turns into (self: Self) as a function param - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto param = static_cast<AST::VariadicParam &> (*p); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - // FIXME: which location should be used for Rust::Identifier `self`? - AST::IdentifierPattern self_pattern ( - param.get_node_id (), {"self"}, param.get_locus (), - param.get_has_ref (), param.get_is_mut (), - std::unique_ptr<AST::Pattern> (nullptr)); - - PatternDeclaration::go (self_pattern, Rib::ItemType::Param); - - if (param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!param.get_has_ref ()); - ResolveType::go (param.get_type ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector<std::unique_ptr<AST::TypePathSegment>> segments; - segments.push_back (std::unique_ptr<AST::TypePathSegment> ( - new AST::TypePathSegment ("Self", false, param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - param.get_locus ()); - ResolveType::go (self_type_path); - } - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - if (function.has_where_clause ()) - ResolveWhereClause::Resolve (function.get_where_clause ()); - - // trait items have an optional body - if (function.has_body ()) - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} -void -ResolveTraitItems::visit (AST::TraitItemType &type) -{ - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (type.get_node_id (), cpath); - - for (auto &bound : type.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); -} - -void -ResolveTraitItems::visit (AST::TraitItemConst &constant) -{ - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - ResolveType::go (constant.get_type ()); - - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), path, cpath); -} - -ResolveItem::ResolveItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveItem::go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveItem resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveItem::visit (AST::TypeAlias &alias) -{ - auto talias - = CanonicalPath::new_seg (alias.get_node_id (), - alias.get_new_type_name ().as_string ()); - auto path = prefix.append (talias); - auto cpath = canonical_prefix.append (talias); - mappings.insert_canonical_path (alias.get_node_id (), cpath); - - NodeId scope_node_id = alias.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (alias.has_generics ()) - ResolveGenericParams::go (alias.get_generic_params (), prefix, - canonical_prefix); - - if (alias.has_where_clause ()) - ResolveWhereClause::Resolve (alias.get_where_clause ()); - - ResolveType::go (alias.get_type_aliased ()); - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Module &module) -{ - auto mod = CanonicalPath::new_seg (module.get_node_id (), - module.get_name ().as_string ()); - auto path = prefix.append (mod); - auto cpath = canonical_prefix.append (mod); - mappings.insert_canonical_path (module.get_node_id (), cpath); - - resolve_visibility (module.get_visibility ()); - - NodeId scope_node_id = module.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // FIXME: Should we reinsert a child here? Any reason we ResolveTopLevel::go - // in ResolveTopLevel::visit (AST::Module) as well as here? - for (auto &item : module.get_items ()) - ResolveTopLevel::go (*item, CanonicalPath::create_empty (), cpath); - - resolver->push_new_module_scope (module.get_node_id ()); - for (auto &item : module.get_items ()) - ResolveItem::go (*item, path, cpath); - - resolver->pop_module_scope (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::TupleStruct &struct_decl) -{ - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolve_visibility (struct_decl.get_visibility ()); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - if (struct_decl.has_where_clause ()) - ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); - - for (AST::TupleField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - resolve_visibility (field.get_visibility ()); - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Enum &enum_decl) -{ - auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - - resolve_visibility (enum_decl.get_visibility ()); - - NodeId scope_node_id = enum_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (enum_decl.has_generics ()) - ResolveGenericParams::go (enum_decl.get_generic_params (), prefix, - canonical_prefix); - - if (enum_decl.has_where_clause ()) - ResolveWhereClause::Resolve (enum_decl.get_where_clause ()); - - /* The actual fields are inside the variants. */ - for (auto &variant : enum_decl.get_variants ()) - ResolveItem::go (*variant, path, cpath); - - resolver->get_type_scope ().pop (); -} - -/* EnumItem doesn't need to be handled, no fields. */ -void -ResolveItem::visit (AST::EnumItem &item) -{ - // Since at this point we cannot have visibilities on enum items anymore, we - // can skip handling them - - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); -} - -void -ResolveItem::visit (AST::EnumItemTuple &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - for (auto &field : item.get_tuple_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } -} - -void -ResolveItem::visit (AST::EnumItemStruct &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - for (auto &field : item.get_struct_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } -} - -void -ResolveItem::visit (AST::EnumItemDiscriminant &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (item.get_node_id (), cpath); -} - -void -ResolveItem::visit (AST::StructStruct &struct_decl) -{ - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolve_visibility (struct_decl.get_visibility ()); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - if (struct_decl.has_where_clause ()) - ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); - - for (AST::StructField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - resolve_visibility (field.get_visibility ()); - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Union &union_decl) -{ - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - - resolve_visibility (union_decl.get_visibility ()); - - NodeId scope_node_id = union_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (union_decl.has_generics ()) - ResolveGenericParams::go (union_decl.get_generic_params (), prefix, - canonical_prefix); - - if (union_decl.has_where_clause ()) - ResolveWhereClause::Resolve (union_decl.get_where_clause ()); - - for (AST::StructField &field : union_decl.get_variants ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::StaticItem &var) -{ - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - - ResolveType::go (var.get_type ()); - ResolveExpr::go (var.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::ConstantItem &constant) -{ - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - resolve_visibility (constant.get_visibility ()); - - ResolveType::go (constant.get_type ()); - ResolveExpr::go (constant.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::Function &function) -{ - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolve_visibility (function.get_visibility ()); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (function.has_where_clause ()) - ResolveWhereClause::Resolve (function.get_where_clause ()); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - if (function.has_self_param ()) - { - // self turns into (self: Self) as a function param - AST::Param &s_param = function.get_self_param (); - auto &self_param = static_cast<AST::SelfParam &> (s_param); - - // FIXME: which location should be used for Rust::Identifier `self`? - AST::IdentifierPattern self_pattern ( - self_param.get_node_id (), {"self"}, self_param.get_locus (), - self_param.get_has_ref (), self_param.get_is_mut (), - std::unique_ptr<AST::Pattern> (nullptr)); - PatternDeclaration::go (self_pattern, Rib::ItemType::Param); - - if (self_param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!self_param.get_has_ref ()); - ResolveType::go (self_param.get_type ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector<std::unique_ptr<AST::TypePathSegment>> segments; - segments.push_back (std::unique_ptr<AST::TypePathSegment> ( - new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - self_param.get_locus ()); - ResolveType::go (self_type_path); - } - } - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto ¶m = static_cast<AST::VariadicParam &> (*p); - if (param.has_pattern ()) - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - if (param.has_type ()) - ResolveType::go (param.get_type ()); - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - // resolve the function body - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::InherentImpl &impl_block) -{ - NodeId scope_node_id = impl_block.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - - resolve_visibility (impl_block.get_visibility ()); - - if (impl_block.has_generics ()) - ResolveGenericParams::go (impl_block.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (impl_block.has_where_clause ()) - ResolveWhereClause::Resolve (impl_block.get_where_clause ()); - - // FIXME this needs to be protected behind nominal type-checks see: - // rustc --explain E0118 - // issue #2634 - ResolveType::go (impl_block.get_type ()); - - // Setup paths - CanonicalPath self_cpath = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), self_cpath); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::InherentImpl resolve Self: {%s}", - self_cpath.get ().c_str ()); - - CanonicalPath impl_type = self_cpath; - CanonicalPath impl_type_seg - = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), impl_type); - CanonicalPath impl_prefix = prefix.append (impl_type_seg); - - // see https://godbolt.org/z/a3vMbsT6W - CanonicalPath cpath = CanonicalPath::create_empty (); - if (canonical_prefix.size () <= 1) - { - cpath = impl_prefix; - } - else - { - std::string seg_buf = "<impl " + self_cpath.get () + ">"; - CanonicalPath seg - = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf); - cpath = canonical_prefix.append (seg); - } - - // done setup paths - - auto Self - = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().insert (Self, - impl_block.get_type ().get_node_id (), - impl_block.get_type ().get_locus ()); - - for (auto &impl_item : impl_block.get_impl_items ()) - { - rust_debug ( - "AST::InherentImpl resolve_impl_item: impl_prefix={%s} cpath={%s}", - impl_prefix.get ().c_str (), cpath.get ().c_str ()); - resolve_impl_item (*impl_item, impl_prefix, cpath); - } - - resolver->get_type_scope ().peek ()->clear_name ( - Self, impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().pop (); - resolver->get_name_scope ().pop (); -} - -void -ResolveItem::visit (AST::TraitImpl &impl_block) -{ - NodeId scope_node_id = impl_block.get_node_id (); - - resolve_visibility (impl_block.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (impl_block.has_generics ()) - ResolveGenericParams::go (impl_block.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (impl_block.has_where_clause ()) - ResolveWhereClause::Resolve (impl_block.get_where_clause ()); - - // CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - NodeId trait_resolved_node = ResolveType::go (impl_block.get_trait_path ()); - if (trait_resolved_node == UNKNOWN_NODEID) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - // CanonicalPath canonical_impl_type = CanonicalPath::create_empty (); - NodeId type_resolved_node = ResolveType::go (impl_block.get_type ()); - if (type_resolved_node == UNKNOWN_NODEID) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - bool ok = true; - - // setup paths - CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - - ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (), - canonical_trait_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::TraitImpl resolve trait type: {%s}", - canonical_trait_type.get ().c_str ()); - - CanonicalPath canonical_impl_type = CanonicalPath::create_empty (); - ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), - canonical_impl_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::TraitImpl resolve self: {%s}", - canonical_impl_type.get ().c_str ()); - - // raw paths - CanonicalPath impl_type_seg = canonical_impl_type; - CanonicalPath trait_type_seg = canonical_trait_type; - CanonicalPath projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - trait_type_seg, impl_type_seg); - CanonicalPath impl_prefix = prefix.append (projection); - - // setup canonical-path - CanonicalPath canonical_projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - canonical_trait_type, - canonical_impl_type); - CanonicalPath cpath = CanonicalPath::create_empty (); - if (canonical_prefix.size () <= 1) - { - cpath = canonical_projection; - } - else - { - std::string projection_str = canonical_projection.get (); - std::string seg_buf - = "<impl " + projection_str.substr (1, projection_str.size () - 2) - + ">"; - CanonicalPath seg - = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf); - cpath = canonical_prefix.append (seg); - } - - // DONE setup canonical-path - - auto Self - = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().insert (Self, - impl_block.get_type ().get_node_id (), - impl_block.get_type ().get_locus ()); - - for (auto &impl_item : impl_block.get_impl_items ()) - { - rust_debug ( - "AST::TraitImpl resolve_impl_item: impl_prefix={%s} cpath={%s}", - impl_prefix.get ().c_str (), cpath.get ().c_str ()); - resolve_impl_item (*impl_item, impl_prefix, cpath); - } - - Rib *r = resolver->get_type_scope ().peek (); - r->clear_name (Self, impl_block.get_type ().get_node_id ()); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::Trait &trait) -{ - NodeId scope_node_id = trait.get_node_id (); - - resolve_visibility (trait.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - - ResolveGenericParams::go_single (trait.get_implicit_self (), prefix, - canonical_prefix); - ResolveGenericParams::go (trait.get_generic_params (), prefix, - canonical_prefix); - - // Self is an implicit TypeParam so lets mark it as such - resolver->get_type_scope ().append_reference_for_def ( - trait.get_node_id (), trait.get_implicit_self ().get_node_id ()); - - if (trait.has_type_param_bounds ()) - { - for (auto &bound : trait.get_type_param_bounds ()) - { - ResolveTypeBound::go (*bound); - } - } - - // resolve any where clause items - if (trait.has_where_clause ()) - ResolveWhereClause::Resolve (trait.get_where_clause ()); - - // resolve the paths - CanonicalPath path = CanonicalPath::create_empty (); - CanonicalPath cpath = CanonicalPath::create_empty (); - // - - for (auto &item : trait.get_trait_items ()) - { - ResolveTraitItems::go (item.get (), path, cpath); - } - - resolver->get_type_scope ().pop (); - resolver->get_name_scope ().pop (); -} - -void -ResolveItem::visit (AST::ExternBlock &extern_block) -{ - resolve_visibility (extern_block.get_visibility ()); - - for (auto &item : extern_block.get_extern_items ()) - { - resolve_extern_item (*item); - } -} - -void -ResolveItem::resolve_impl_item (AST::AssociatedItem &item, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveImplItems::go (item, prefix, canonical_prefix); -} - -void -ResolveItem::resolve_extern_item (AST::ExternalItem &item) -{ - ResolveExternItem::go (item, prefix, canonical_prefix); -} - -static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports); -static void -flatten_rebind (const AST::UseTreeRebind &glob, std::vector<Import> &imports); -static void -flatten_list (const AST::UseTreeList &glob, std::vector<Import> &imports); - -static void -flatten (const AST::UseTree *tree, std::vector<Import> &imports) -{ - switch (tree->get_kind ()) - { - case AST::UseTree::Glob: { - auto glob = static_cast<const AST::UseTreeGlob *> (tree); - flatten_glob (*glob, imports); - break; - } - case AST::UseTree::Rebind: { - auto rebind = static_cast<const AST::UseTreeRebind *> (tree); - flatten_rebind (*rebind, imports); - break; - } - case AST::UseTree::List: { - auto list = static_cast<const AST::UseTreeList *> (tree); - flatten_list (*list, imports); - break; - } - break; - } -} - -static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports) -{ - if (glob.has_path ()) - imports.emplace_back (glob.get_path (), true, std::string ()); -} - -static void -flatten_rebind (const AST::UseTreeRebind &rebind, std::vector<Import> &imports) -{ - auto path = rebind.get_path (); - - std::string label; - if (rebind.has_identifier ()) - label = rebind.get_identifier ().as_string (); - else - label = path.get_final_segment ().as_string (); - - imports.emplace_back (path, false, label); -} - -static void -flatten_list (const AST::UseTreeList &list, std::vector<Import> &imports) -{ - auto prefix = AST::SimplePath::create_empty (); - if (list.has_path ()) - prefix = list.get_path (); - - for (const auto &tree : list.get_trees ()) - { - // append imports to the main list, then modify them in-place - auto start_idx = imports.size (); - flatten (tree.get (), imports); - - for (auto import = imports.begin () + start_idx; import != imports.end (); - import++) - { - // avoid duplicate node ids - auto prefix_copy - = AST::SimplePath ({}, prefix.has_opening_scope_resolution (), - prefix.get_locus ()); - for (auto &seg : prefix.get_segments ()) - prefix_copy.get_segments ().push_back ( - AST::SimplePathSegment (seg.get_segment_name (), - seg.get_locus ())); - - import->add_prefix (std::move (prefix_copy)); - } - } -} - -void -Import::add_prefix (AST::SimplePath prefix) -{ - AST::SimplePath old_path (std::move (path)); - path = std::move (prefix); - std::move (old_path.get_segments ().begin (), old_path.get_segments ().end (), - std::back_inserter (path.get_segments ())); -} - -/** - * Flatten a UseDeclaration's UseTree into multiple simple paths to resolve. - * - * Given the following use declarations: - * ``` - * use some::path::to_resolve; #1 - * use some::path::to_glob::*; #2 - * use some::path::{one, two}; #2 - * ``` - * - * In the first case, we simply want to return a vector with a single - * SimplePath: - * [some::path::to_resolve] - * - * In the second case, we want to resolve the glob's "origin path": - * [some::path::to_glob] - * - * Finally in the third case, we want to create two SimplePaths to resolve: - * [some::path::one, some::path::two] - */ -static std::vector<Import> -flatten_use_dec_to_imports (const AST::UseDeclaration &use_item) -{ - auto imports = std::vector<Import> (); - - const auto &tree = use_item.get_tree (); - flatten (tree.get (), imports); - - return imports; -} - -void -ResolveItem::visit (AST::UseDeclaration &use_item) -{ - std::vector<Import> to_resolve = flatten_use_dec_to_imports (use_item); - - // FIXME: I think this does not actually resolve glob use-decls and is going - // the wrong way about it. RFC #1560 specifies the following: - // - // > When we find a glob import, we have to record a 'back link', so that when - // a public name is added for the supplying module, we can add it for the - // importing module. - // - // Which is the opposite of what we're doing if I understand correctly? - - NodeId current_module = resolver->peek_current_module_scope (); - for (auto &import : to_resolve) - { - auto &path = import.get_path (); - - rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ()); - NodeId resolved_node_id = ResolvePath::go (path); - bool ok = resolved_node_id != UNKNOWN_NODEID; - if (!ok) - continue; - - if (import.is_glob ()) - continue; - - auto decl = CanonicalPath::new_seg (resolved_node_id, import.get_name ()); - mappings.insert_module_child_item (current_module, decl); - - resolver->get_type_scope ().insert (decl, resolved_node_id, - path.get_locus (), - Rib::ItemType::Type); - rust_debug ("use-decl rexporting: [%s]", decl.get ().c_str ()); - } -} - -ResolveImplItems::ResolveImplItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolveItem (prefix, canonical_prefix) -{} - -void -ResolveImplItems::go (AST::AssociatedItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - if (item.is_marked_for_strip ()) - return; - - ResolveImplItems resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveImplItems::visit (AST::TypeAlias &alias) -{ - ResolveItem::visit (alias); - - resolve_visibility (alias.get_visibility ()); - - // FIXME this stops the erronious unused decls which will be fixed later on - resolver->get_type_scope ().append_reference_for_def (alias.get_node_id (), - alias.get_node_id ()); -} - -void -ResolveExternItem::go (AST::ExternalItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveExternItem resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveExternItem::visit (AST::Function &function) -{ - NodeId scope_node_id = function.get_node_id (); - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolve_visibility (function.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve the generics - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto ¶m : function.get_function_params ()) - if (!param->is_variadic ()) - { - auto &p = static_cast<AST::FunctionParam &> (*param); - ResolveType::go (p.get_type ()); - } - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExternItem::visit (AST::ExternalStaticItem &item) -{ - resolve_visibility (item.get_visibility ()); - - ResolveType::go (item.get_type ()); -} - -} // namespace Resolver -} // namespace Rust - -#if CHECKING_P - -namespace selftest { - -static void -rust_flatten_nested_glob (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foobar = Rust::AST::SimplePath ({foo, bar}); - - auto glob - = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, - foobar, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_glob (glob, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); -} - -static void -rust_flatten_glob (void) -{ - auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION); - - auto glob - = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, - frob, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_glob (glob, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path (), "frobulator"); -} - -static void -rust_flatten_rebind_none (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foobar = Rust::AST::SimplePath ({foo, bar}); - - auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, - foobar, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); -} - -static void -rust_flatten_rebind (void) -{ - auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION); - - auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, - frob, UNDEF_LOCATION, {"saindoux"}); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path (), "frobulator"); - ASSERT_EQ (imports[0].get_name (), "saindoux"); -} - -static void -rust_flatten_rebind_nested (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto baz = Rust::AST::SimplePathSegment ("baz", UNDEF_LOCATION); - - auto foo_bar_baz = Rust::AST::SimplePath ({foo, bar, baz}); - - auto rebind - = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, - foo_bar_baz, UNDEF_LOCATION, {"saindoux"}); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (imports[0].get_name (), "saindoux"); -} - -static void -rust_flatten_list (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foo_bar = Rust::AST::SimplePath ({foo, bar}); - - auto baz = Rust::AST::SimplePath::from_str ("baz", UNDEF_LOCATION); - auto bul = Rust::AST::SimplePath::from_str ("bul", UNDEF_LOCATION); - - // use foo::bar::{baz, bul}; - - auto use0 = std::unique_ptr<Rust::AST::UseTree> ( - new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, baz, - UNDEF_LOCATION)); - auto use1 = std::unique_ptr<Rust::AST::UseTree> ( - new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, bul, - UNDEF_LOCATION)); - - auto uses = std::vector<std::unique_ptr<Rust::AST::UseTree>> (); - uses.emplace_back (std::move (use0)); - uses.emplace_back (std::move (use1)); - - auto list - = Rust::AST::UseTreeList (Rust::AST::UseTreeList::PATH_PREFIXED, foo_bar, - std::move (uses), UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_list (list, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 2); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[2].as_string (), "bul"); -} - -static void -rust_use_dec_flattening (void) -{ - rust_flatten_glob (); - rust_flatten_nested_glob (); - rust_flatten_rebind_none (); - rust_flatten_rebind (); - rust_flatten_rebind_nested (); - rust_flatten_list (); -} - -void -rust_simple_path_resolve_test (void) -{ - rust_use_dec_flattening (); -} - -} // namespace selftest - -#endif // CHECKING_P diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h deleted file mode 100644 index 776dd53..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ /dev/null @@ -1,162 +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_AST_RESOLVE_ITEM_H -#define RUST_AST_RESOLVE_ITEM_H - -#include "rust-ast-full-decls.h" -#include "rust-ast-resolve-base.h" - -#include "config.h" - -namespace Rust { -namespace Resolver { - -class ResolveTraitItems : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::Function &type) override; - void visit (AST::TraitItemType &type) override; - void visit (AST::TraitItemConst &constant) override; - -private: - ResolveTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveItem : public ResolverBase -{ -public: - using Rust::Resolver::ResolverBase::visit; - - static void go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::TypeAlias &alias) override; - void visit (AST::Module &module) override; - void visit (AST::TupleStruct &struct_decl) override; - void visit (AST::Enum &enum_decl) override; - /* EnumItem doesn't need to be handled, no fields. */ - void visit (AST::EnumItem &item) override; - void visit (AST::EnumItemTuple &item) override; - void visit (AST::EnumItemStruct &item) override; - void visit (AST::EnumItemDiscriminant &item) override; - void visit (AST::StructStruct &struct_decl) override; - void visit (AST::Union &union_decl) override; - void visit (AST::StaticItem &var) override; - void visit (AST::ConstantItem &constant) override; - void visit (AST::Function &function) override; - void visit (AST::InherentImpl &impl_block) override; - void visit (AST::TraitImpl &impl_block) override; - void visit (AST::Trait &trait) override; - void visit (AST::ExternBlock &extern_block) override; - void visit (AST::UseDeclaration &) override; - -protected: - void resolve_impl_item (AST::AssociatedItem &item, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - void resolve_extern_item (AST::ExternalItem &item); - - ResolveItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveImplItems : public ResolveItem -{ - using Rust::Resolver::ResolveItem::visit; - -public: - static void go (AST::AssociatedItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::TypeAlias &alias) override; - -private: - ResolveImplItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); -}; - -class ResolveExternItem : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::ExternalItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::Function &function) override; - void visit (AST::ExternalStaticItem &item) override; - -private: - ResolveExternItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class Import -{ -public: - Import (AST::SimplePath path, bool is_glob, std::string name) - : path (path), is_glob_f (is_glob), name (name) - {} - - AST::SimplePath &get_path () { return path; } - - const AST::SimplePath &get_path () const { return path; } - - bool is_glob () const { return is_glob_f; } - - const std::string &get_name () const { return name; } - - void add_prefix (AST::SimplePath prefix); - -private: - AST::SimplePath path; - bool is_glob_f; - std::string name; -}; - -} // namespace Resolver -} // namespace Rust - -#if CHECKING_P - -namespace selftest { -extern void -rust_simple_path_resolve_test (void); -} // namespace selftest - -#endif // CHECKING_P - -#endif // RUST_AST_RESOLVE_ITEM_H diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc deleted file mode 100644 index 530926d..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright (C) 2020-2024 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve-path.h" -#include "rust-ast-resolve-type.h" -#include "rust-hir-map.h" -#include "rust-path.h" - -namespace Rust { -namespace Resolver { - -ResolvePath::ResolvePath () : ResolverBase () {} - -NodeId -ResolvePath::go (AST::PathInExpression &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::go (AST::QualifiedPathInExpression &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::go (AST::SimplePath &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::resolve_path (AST::PathInExpression &expr) -{ - if (expr.is_lang_item ()) - return Analysis::Mappings::get ().get_lang_item_node ( - expr.get_lang_item ()); - - NodeId resolved_node_id = UNKNOWN_NODEID; - NodeId module_scope_id = resolver->peek_current_module_scope (); - NodeId previous_resolved_node_id = module_scope_id; - for (size_t i = 0; i < expr.get_segments ().size (); i++) - { - auto &segment = expr.get_segments ().at (i); - const AST::PathIdentSegment &ident_seg = segment.get_ident_segment (); - bool is_first_segment = i == 0; - resolved_node_id = UNKNOWN_NODEID; - - bool in_middle_of_path = i > 0; - if (in_middle_of_path && segment.is_lower_self_seg ()) - { - rust_error_at (segment.get_locus (), ErrorCode::E0433, - "leading path segment %qs can only be used at the " - "beginning of a path", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - if (segment.is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - else if (segment.is_super_path_seg ()) - { - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment.get_locus (), - "cannot use %<super%> at the crate scope"); - return UNKNOWN_NODEID; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - - // resolve any generic args - if (segment.has_generic_args ()) - ResolveGenericArgs::go (segment.get_generic_args ()); - - // logic is awkward here there are a few cases - // - // T::Default - // mod::foo::impl_item - // super::super::module::item - // self - // self::foo - // self::foo::baz - // - // T::Default we can only resolve the T and cant do anything about Default - // its dependant on associated types - // - // mod::foo::impl_item - // we can resolve mod::foo but nothing about impl_item but we need to - // _always resolve generic arguments - // - // self is a simple single lookup - // - // we have module_scope_id for the next module_scope to lookup - // resolved_node_id is the thing we have resolve this segment to - // - // new algo? - // we can only use module resolution when the previous segment is either - // unknown or equal to this module_scope_id - // - // can only use old resolution when previous segment is unkown - - if (is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment.get_node_id (), - ident_seg.as_string ()); - if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (segment.is_lower_self_seg ()) - { - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - else - { - // no error handling here since we might be able to resolve via - // the module hierarchy and handle errors at the end - } - } - - if (resolved_node_id == UNKNOWN_NODEID - && previous_resolved_node_id == module_scope_id) - { - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, - ident_seg.as_string ()); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment.get_locus (), - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - } - - bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID; - if (did_resolve_segment) - { - if (mappings.node_is_module (resolved_node_id) - || mappings.node_is_crate (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - previous_resolved_node_id = resolved_node_id; - } - else if (is_first_segment) - { - rust_error_at (segment.get_locus (), ErrorCode::E0433, - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - - resolved_node = resolved_node_id; - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (expr.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (expr.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - return resolved_node_id; -} - -NodeId -ResolvePath::resolve_path (AST::QualifiedPathInExpression &expr) -{ - auto &root_segment = expr.get_qualified_path_type (); - ResolveType::go (root_segment.get_type ()); - if (root_segment.has_as_clause ()) - ResolveType::go (root_segment.get_as_type_path ()); - - for (auto &segment : expr.get_segments ()) - { - // we cant actually do anything with the segment itself since this is all - // the job of the type system to figure it out but we can resolve any - // generic arguments used - if (segment.has_generic_args ()) - ResolveGenericArgs::go (segment.get_generic_args ()); - } - - // cannot fully resolve a qualified path as it is dependant on associated - // items - return UNKNOWN_NODEID; -} - -NodeId -ResolvePath::resolve_path (AST::SimplePath &expr) -{ - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - NodeId module_scope_id = resolver->peek_current_module_scope (); - - NodeId previous_resolved_node_id = UNKNOWN_NODEID; - NodeId resolved_node_id = UNKNOWN_NODEID; - for (size_t i = 0; i < expr.get_segments ().size (); i++) - { - AST::SimplePathSegment &segment = expr.get_segments ().at (i); - bool is_first_segment = i == 0; - bool is_final_segment = i >= (expr.get_segments ().size () - 1); - resolved_node_id = UNKNOWN_NODEID; - - if (segment.is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - resolved_node_id = module_scope_id; - - continue; - } - else if (segment.is_super_path_seg ()) - { - if (!is_first_segment) - { - rust_error_at (segment.get_locus (), - "%<super%> can only be used in start position"); - return UNKNOWN_NODEID; - } - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment.get_locus (), - "cannot use %<super%> at the crate scope"); - return UNKNOWN_NODEID; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - resolved_node_id = module_scope_id; - - continue; - } - - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, - segment.get_segment_name ()); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment.get_locus (), - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - - if (resolved_node_id == UNKNOWN_NODEID && is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment.get_node_id (), - segment.get_segment_name ()); - if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - } - - // if we still have not resolved and this is the final segment and the - // final segment is self its likely the case: pub use - // - // result::Result::{self, Err, Ok}; - // - // Then the resolved_node_id is just the previous one so long as it is a - // resolved node id - // rust_debug_loc (segment.get_locus (), - // "trying to resolve seg: [%s] first [%s] last [%s]", - // segment.get_segment_name ().c_str (), - // is_first_segment ? "true" : "false", - // is_final_segment ? "true" : "false"); - if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment - && is_final_segment && segment.is_lower_self_seg ()) - resolved_node_id = previous_resolved_node_id; - - // final check - if (resolved_node_id == UNKNOWN_NODEID) - { - rust_error_at (segment.get_locus (), - "cannot find simple path segment %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - - if (mappings.node_is_module (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - - previous_resolved_node_id = resolved_node_id; - } - - resolved_node = resolved_node_id; - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (expr.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (expr.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - return resolved_node_id; -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-path.h b/gcc/rust/resolve/rust-ast-resolve-path.h deleted file mode 100644 index cddb54a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-path.h +++ /dev/null @@ -1,52 +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_AST_RESOLVE_PATH_H -#define RUST_AST_RESOLVE_PATH_H - -#include "rust-ast-resolve-base.h" - -namespace Rust { -namespace Resolver { - -class ResolvePath : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::PathInExpression &expr); - static NodeId go (AST::QualifiedPathInExpression &expr); - static NodeId go (AST::SimplePath &expr); - -private: - ResolvePath (); - - NodeId resolve_path (AST::PathInExpression &expr); - NodeId resolve_path (AST::QualifiedPathInExpression &expr); - NodeId resolve_path (AST::SimplePath &expr); - - void - resolve_simple_path_segments (CanonicalPath prefix, size_t offs, - const std::vector<AST::SimplePathSegment> &segs, - NodeId expr_node_id, location_t expr_locus); -}; - -} // namespace Resolver -} // namespace Rust - -#endif // !RUST_AST_RESOLVE_PATH_H diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc deleted file mode 100644 index ee84be8..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" - -namespace Rust { -namespace Resolver { - -void -PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type) -{ - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - PatternDeclaration::go (pattern, type, bindings); -} - -void -PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type, - std::vector<PatternBinding> &bindings) -{ - PatternDeclaration resolver (bindings, type); - pattern.accept_vis (resolver); - - for (auto &map_entry : resolver.missing_bindings) - { - auto ident = map_entry.first; // key - auto info = map_entry.second; // value - - rust_error_at (info.get_locus (), ErrorCode::E0408, - "variable '%s' is not bound in all patterns", - ident.as_string ().c_str ()); - } - - for (auto &map_entry : resolver.inconsistent_bindings) - { - auto ident = map_entry.first; // key - auto info = map_entry.second; // value - - rust_error_at ( - info.get_locus (), ErrorCode::E0409, - "variable '%s' is bound inconsistently across pattern alternatives", - ident.as_string ().c_str ()); - } -} - -void -PatternDeclaration::visit (AST::IdentifierPattern &pattern) -{ - Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm; - add_new_binding (pattern.get_ident (), pattern.get_node_id (), - BindingTypeInfo (mut, pattern.get_is_ref (), - pattern.get_locus ())); -} - -void -PatternDeclaration::visit (AST::GroupedPattern &pattern) -{ - pattern.get_pattern_in_parens ().accept_vis (*this); -} - -void -PatternDeclaration::visit (AST::ReferencePattern &pattern) -{ - pattern.get_referenced_pattern ().accept_vis (*this); -} - -void -PatternDeclaration::visit (AST::PathInExpression &pattern) -{ - ResolvePath::go (pattern); -} - -void -PatternDeclaration::visit (AST::TupleStructPattern &pattern) -{ - ResolvePath::go (pattern.get_path ()); - - AST::TupleStructItems &items = pattern.get_items (); - switch (items.get_item_type ()) - { - case AST::TupleStructItems::RANGE: { - // TODO - rust_unreachable (); - } - break; - - case AST::TupleStructItems::NO_RANGE: { - auto &items_no_range - = static_cast<AST::TupleStructItemsNoRange &> (items); - - for (auto &inner_pattern : items_no_range.get_patterns ()) - { - inner_pattern->accept_vis (*this); - } - } - break; - } -} - -void -PatternDeclaration::visit (AST::StructPattern &pattern) -{ - ResolvePath::go (pattern.get_path ()); - - auto &struct_pattern_elems = pattern.get_struct_pattern_elems (); - for (auto &field : struct_pattern_elems.get_struct_pattern_fields ()) - { - switch (field->get_item_type ()) - { - case AST::StructPatternField::ItemType::TUPLE_PAT: { - AST::StructPatternFieldTuplePat &tuple - = static_cast<AST::StructPatternFieldTuplePat &> (*field); - - tuple.get_index_pattern ().accept_vis (*this); - } - break; - - case AST::StructPatternField::ItemType::IDENT_PAT: { - AST::StructPatternFieldIdentPat &ident - = static_cast<AST::StructPatternFieldIdentPat &> (*field); - - ident.get_ident_pattern ().accept_vis (*this); - } - break; - - case AST::StructPatternField::ItemType::IDENT: { - auto &ident = static_cast<AST::StructPatternFieldIdent &> (*field); - - Mutability mut - = ident.is_mut () ? Mutability::Mut : Mutability::Imm; - - add_new_binding (ident.get_identifier (), ident.get_node_id (), - BindingTypeInfo (mut, ident.is_ref (), - ident.get_locus ())); - } - break; - } - } -} - -void -PatternDeclaration::visit (AST::TuplePattern &pattern) -{ - auto &items = pattern.get_items (); - switch (items.get_pattern_type ()) - { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: { - auto &ref = static_cast<AST::TuplePatternItemsMultiple &> ( - pattern.get_items ()); - - for (auto &p : ref.get_patterns ()) - p->accept_vis (*this); - } - break; - - case AST::TuplePatternItems::TuplePatternItemType::RANGED: { - auto &ref - = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ()); - - for (auto &p : ref.get_lower_patterns ()) - p->accept_vis (*this); - for (auto &p : ref.get_upper_patterns ()) - p->accept_vis (*this); - } - break; - } -} - -void -PatternDeclaration::visit (AST::AltPattern &pattern) -{ - // push a new set of 'Or' bindings to the stack. Accounts for the - // alternatives. e.g. in `p_0 | p_1`, bindings to the same identifier between - // p_0 and p_1 shouldn't cause an error. - bindings_with_ctx.push_back ( - PatternBinding (PatternBoundCtx::Or, std::set<Identifier> ())); - - // This is a hack to avoid creating a separate visitor class for the - // consistency checks. We empty out the binding_info_map before each iteration - // to separate between the alts' binding_maps. And right after the alt - // visit... - auto tmp_binding_map = binding_info_map; - binding_info_map.clear (); - - std::vector<BindingMap> alts_binding_maps; - - for (auto &alt : pattern.get_alts ()) - { - // before this visit, the binding_info_map is guaranteed to be empty - rust_assert (binding_info_map.empty ()); - - // push a new `Product` context to correctly reject multiple bindings - // within this single alt. - bindings_with_ctx.push_back ( - PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())); - - alt->accept_vis (*this); - - // ...the binding_info_map is (potentially) populated. We copy it to the - // vector, and empty it out to be ready for the next iteration. And after - // all the iterations are finished... - alts_binding_maps.push_back (binding_info_map); - binding_info_map.clear (); - - // Remove the last (i.e. `Product`) context and add the bindings from the - // visited alt to the one before last (i.e. `Or`). Now (after checking - // with the alt internally), the bindings from this alt will reside in the - // `Or` context. - auto last_bound_idents = bindings_with_ctx.back ().idents; - bindings_with_ctx.pop_back (); - - for (auto &ident : last_bound_idents) - { - bindings_with_ctx.back ().idents.insert (ident); - } - } - - // Now we can finally check for consistency. - check_bindings_consistency (alts_binding_maps); - - // Now we remove the `Or` context we pushed earlier. - // e.g. in `(a, (p_0 | p_1), c)`: after finishing up inside the alt pattern, - // we return to the tuple (`Product`) context and push the new bindings. - auto idents = bindings_with_ctx.back ().idents; - bindings_with_ctx.pop_back (); - for (auto &ident : idents) - bindings_with_ctx.back ().idents.insert (ident.as_string ()); - - // ...we repopulate the binding_info_map correctly (the initial bindings - // stored in the tmp_binding_map + all the bindings from all the alts) - binding_info_map = tmp_binding_map; - for (auto &alt_map : alts_binding_maps) - for (auto &map_entry : alt_map) - binding_info_map.insert (map_entry); -} - -void -PatternDeclaration::add_new_binding (Identifier ident, NodeId node_id, - BindingTypeInfo info) -{ - bool has_binding_ctx = bindings_with_ctx.size () > 0; - rust_assert (has_binding_ctx); - - bool identifier_or_bound = false, identifier_product_bound = false; - - for (auto binding : bindings_with_ctx) - { - bool identifier_bound_here - = (binding.idents.find (ident) != binding.idents.end ()); - if (identifier_bound_here) - { - identifier_product_bound |= binding.ctx == PatternBoundCtx::Product; - identifier_or_bound |= binding.ctx == PatternBoundCtx::Or; - } - } - - if (identifier_product_bound) - { - if (type == Rib::ItemType::Param) - { - rust_error_at (info.get_locus (), ErrorCode::E0415, - "identifier '%s' is bound more than once in the " - "same parameter list", - ident.as_string ().c_str ()); - } - else - { - rust_error_at ( - info.get_locus (), ErrorCode::E0416, - "identifier '%s' is bound more than once in the same pattern", - ident.as_string ().c_str ()); - } - - return; - } - - if (!identifier_or_bound) - { - bindings_with_ctx.back ().idents.insert (ident); - resolver->get_name_scope ().insert ( - CanonicalPath::new_seg (node_id, ident.as_string ()), node_id, - info.get_locus (), type); - } - - binding_info_map.insert ({ident, info}); -} - -// Verifies that all the alts in an AltPattern have the same set of bindings -// with the same mutability and reference states. -void -PatternDeclaration::check_bindings_consistency ( - std::vector<BindingMap> &binding_maps) -{ - for (size_t i = 0; i < binding_maps.size (); i++) - { - auto &outer_bindings_map = binding_maps[i]; - - for (size_t j = 0; j < binding_maps.size (); j++) - { - // skip comparing the current outer map with itself. - if (j == i) - continue; - - auto &inner_bindings_map = binding_maps[j]; - - // iterate over the inner map entries and check if they exist in outer - // map - for (auto map_entry : inner_bindings_map) - { - auto ident = map_entry.first; // key - auto inner_info = map_entry.second; // value - bool ident_is_outer_bound = outer_bindings_map.count (ident); - - if (!ident_is_outer_bound && !missing_bindings.count (ident)) - missing_bindings.insert ({ident, inner_info}); - - else if (outer_bindings_map.count (ident) - && outer_bindings_map[ident] != inner_info - && !inconsistent_bindings.count (ident)) - inconsistent_bindings.insert ({ident, inner_info}); - } - } - } -} - -static void -resolve_range_pattern_bound (AST::RangePatternBound &bound) -{ - switch (bound.get_bound_type ()) - { - case AST::RangePatternBound::RangePatternBoundType::LITERAL: - // Nothing to resolve for a literal. - break; - - case AST::RangePatternBound::RangePatternBoundType::PATH: { - auto &ref = static_cast<AST::RangePatternBoundPath &> (bound); - - ResolvePath::go (ref.get_path ()); - } - break; - - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: { - auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound); - - ResolvePath::go (ref.get_qualified_path ()); - } - break; - } -} - -void -PatternDeclaration::visit (AST::RangePattern &pattern) -{ - resolve_range_pattern_bound (pattern.get_upper_bound ()); - resolve_range_pattern_bound (pattern.get_lower_bound ()); -} - -void -PatternDeclaration::visit (AST::SlicePattern &pattern) -{ - for (auto &p : pattern.get_items ()) - { - p->accept_vis (*this); - } -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h deleted file mode 100644 index 876de16..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ /dev/null @@ -1,146 +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_AST_RESOLVE_PATTERN_H -#define RUST_AST_RESOLVE_PATTERN_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-full.h" - -namespace Rust { -namespace Resolver { - -// Specifies whether the set of already bound patterns are related by 'Or' or -// 'Product'. Used to check for multiple bindings to the same identifier. -enum PatternBoundCtx -{ - // A product pattern context (e.g. struct and tuple patterns) - Product, - // An or-pattern context (e.g. p_0 | p_1 | ...) - Or, -}; - -struct PatternBinding -{ - PatternBoundCtx ctx; - std::set<Identifier> idents; - - PatternBinding (PatternBoundCtx ctx, std::set<Identifier> idents) - : ctx (ctx), idents (idents) - {} -}; - -// Info that gets stored in the map. Helps us detect if two bindings to the same -// identifier have different mutability or ref states. -class BindingTypeInfo -{ - Mutability mut; - bool is_ref; - location_t locus; - -public: - BindingTypeInfo (Mutability mut, bool is_ref, location_t locus) - : mut (mut), is_ref (is_ref), locus (locus) - {} - - BindingTypeInfo (BindingTypeInfo const &other) - : mut (other.mut), is_ref (other.is_ref), locus (other.get_locus ()) - {} - - BindingTypeInfo (){}; - - location_t get_locus () const { return locus; } - Mutability get_mut () const { return mut; } - bool get_is_ref () const { return is_ref; } - - BindingTypeInfo operator= (BindingTypeInfo const &other) - { - mut = other.mut; - is_ref = other.is_ref; - locus = other.get_locus (); - - return *this; - } - - bool operator== (BindingTypeInfo const &other) - { - return mut == other.mut && is_ref == other.is_ref; - } - - bool operator!= (BindingTypeInfo const &other) - { - return !BindingTypeInfo::operator== (other); - } -}; - -typedef std::map<Identifier, BindingTypeInfo> BindingMap; - -class PatternDeclaration : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Pattern &pattern, Rib::ItemType type); - static void go (AST::Pattern &pattern, Rib::ItemType type, - std::vector<PatternBinding> &bindings); - - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::GroupedPattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - void visit (AST::PathInExpression &pattern) override; - void visit (AST::StructPattern &pattern) override; - void visit (AST::TupleStructPattern &pattern) override; - void visit (AST::TuplePattern &pattern) override; - void visit (AST::RangePattern &pattern) override; - void visit (AST::AltPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - - void add_new_binding (Identifier ident, NodeId node_id, BindingTypeInfo info); - void check_bindings_consistency (std::vector<BindingMap> &binding_maps); - -private: - PatternDeclaration (std::vector<PatternBinding> &bindings_with_ctx, - Rib::ItemType type) - : ResolverBase (), bindings_with_ctx (bindings_with_ctx), type (type) - {} - - // To avoid having a separate visitor for consistency checks, we store - // bindings in two forms: - - // 1) Bindings as a vector of context-related sets. - // Used for checking multiple bindings to the same identifier (i.e. E0415, - // E0416). - std::vector<PatternBinding> &bindings_with_ctx; - - // 2) Bindings as a map between identifiers and binding info. - // Used for checking consistency between alt patterns (i.e. E0408, E0409). - BindingMap binding_info_map; - - // we need to insert the missing and inconsistent bindings (found in - // check_bindings_consistency) into maps to avoid duplication of error - // messages. - BindingMap inconsistent_bindings; - BindingMap missing_bindings; - - Rib::ItemType type; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_PATTERN_H diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.cc b/gcc/rust/resolve/rust-ast-resolve-stmt.cc deleted file mode 100644 index fefb522..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.cc +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-item.h" -#include "rust-ast-resolve-stmt.h" -#include "rust-ast-resolve-implitem.h" - -namespace Rust { -namespace Resolver { - -void -ResolveStmt::visit (AST::ExternBlock &extern_block) -{ - resolve_visibility (extern_block.get_visibility ()); - for (auto &item : extern_block.get_extern_items ()) - { - ResolveToplevelExternItem::go (*item, CanonicalPath::create_empty ()); - ResolveExternItem::go (*item, prefix, canonical_prefix); - } -} - -void -ResolveStmt::visit (AST::Trait &trait) -{ - ResolveTopLevel::go (trait, prefix, canonical_prefix); - ResolveItem::go (trait, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::InherentImpl &impl_block) -{ - ResolveTopLevel::go (impl_block, prefix, canonical_prefix); - ResolveItem::go (impl_block, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::TraitImpl &impl_block) -{ - ResolveTopLevel::go (impl_block, prefix, canonical_prefix); - ResolveItem::go (impl_block, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::StaticItem &var) -{ - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = decl; - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, var.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - ResolveType::go (var.get_type ()); - ResolveExpr::go (var.get_expr (), path, cpath); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h deleted file mode 100644 index 6c99d6a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ /dev/null @@ -1,407 +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_AST_RESOLVE_STMT_H -#define RUST_AST_RESOLVE_STMT_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-expr.h" -#include "rust-item.h" - -namespace Rust { -namespace Resolver { - -class ResolveStmt : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Stmt &stmt, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - const CanonicalPath &enum_prefix) - { - if (stmt.is_marked_for_strip ()) - return; - - ResolveStmt resolver (prefix, canonical_prefix, enum_prefix); - stmt.accept_vis (resolver); - } - - void visit (AST::ExprStmt &stmt) override - { - ResolveExpr::go (stmt.get_expr (), prefix, canonical_prefix); - } - - void visit (AST::ConstantItem &constant) override - { - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - ResolveType::go (constant.get_type ()); - ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix); - } - - void visit (AST::LetStmt &stmt) override - { - if (stmt.has_init_expr ()) - ResolveExpr::go (stmt.get_init_expr (), prefix, canonical_prefix); - - if (stmt.has_else_expr ()) - ResolveExpr::go (stmt.get_else_expr (), prefix, canonical_prefix); - - PatternDeclaration::go (stmt.get_pattern (), Rib::ItemType::Var); - if (stmt.has_type ()) - ResolveType::go (stmt.get_type ()); - } - - void visit (AST::TupleStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::TupleField &field : struct_decl.get_fields ()) - ResolveType::go (field.get_field_type ()); - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Enum &enum_decl) override - { - auto decl - = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, enum_decl.get_node_id (), enum_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, enum_decl.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId scope_node_id = enum_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (enum_decl.has_generics ()) - ResolveGenericParams::go (enum_decl.get_generic_params (), prefix, - canonical_prefix); - - for (auto &variant : enum_decl.get_variants ()) - ResolveStmt::go (*variant, path, canonical_prefix, path); - - resolver->get_type_scope ().pop (); - } - - void visit (AST::EnumItem &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - // Done, no fields. - } - - void visit (AST::EnumItemTuple &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - for (auto &field : item.get_tuple_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - } - - void visit (AST::EnumItemStruct &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - for (auto &field : item.get_struct_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - } - - void visit (AST::EnumItemDiscriminant &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - // Done, no fields. - } - - void visit (AST::StructStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::StructField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Union &union_decl) override - { - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, union_decl.get_node_id (), union_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, union_decl.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId scope_node_id = union_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (union_decl.has_generics ()) - ResolveGenericParams::go (union_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::StructField &field : union_decl.get_variants ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto ¶m = static_cast<AST::VariadicParam &> (*p); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - ResolveType::go (param.get_type ()); - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - // resolve the function body - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - } - - void visit (AST::ExternBlock &extern_block) override; - void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl_block) override; - void visit (AST::TraitImpl &impl_block) override; - void visit (AST::StaticItem &var) override; - -private: - ResolveStmt (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - const CanonicalPath &enum_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix), - enum_prefix (enum_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; - - /* item declaration statements are not given a canonical path, but enum items - * (variants) do inherit the enum path/identifier name. */ - const CanonicalPath &enum_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_STMT_H diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc deleted file mode 100644 index 9b38e6a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve-struct-expr-field.h" -#include "rust-ast-resolve-expr.h" - -namespace Rust { -namespace Resolver { - -void -ResolveStructExprField::go (AST::StructExprField &field, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveStructExprField resolver (prefix, canonical_prefix); - field.accept_vis (resolver); -} - -ResolveStructExprField::ResolveStructExprField ( - const CanonicalPath &prefix, const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field) -{ - ResolveExpr::go (field.get_value (), prefix, canonical_prefix); -} - -void -ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field) -{ - ResolveExpr::go (field.get_value (), prefix, canonical_prefix); -} - -void -ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field) -{ - AST::IdentifierExpr expr (field.get_field_name (), {}, field.get_locus ()); - expr.set_node_id (field.get_node_id ()); - - ResolveExpr::go (expr, prefix, canonical_prefix); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h deleted file mode 100644 index 87fa60d..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h +++ /dev/null @@ -1,54 +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_AST_RESOLVE_STRUCT_EXPR_FIELD -#define RUST_AST_RESOLVE_STRUCT_EXPR_FIELD - -#include "rust-ast-resolve-base.h" - -namespace Rust { -namespace Resolver { - -// this resolves values being assigned not that the field actually exists yet. - -class ResolveStructExprField : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::StructExprField &field, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::StructExprFieldIdentifierValue &field) override; - - void visit (AST::StructExprFieldIndexValue &field) override; - - void visit (AST::StructExprFieldIdentifier &field) override; - -private: - ResolveStructExprField (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_STRUCT_EXPR_FIELD diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h deleted file mode 100644 index 379ccab..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ /dev/null @@ -1,500 +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_AST_RESOLVE_TOPLEVEL_H -#define RUST_AST_RESOLVE_TOPLEVEL_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-implitem.h" -#include "rust-name-resolver.h" - -namespace Rust { -namespace Resolver { - -class ResolveTopLevel : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - if (item.is_marked_for_strip ()) - return; - - ResolveTopLevel resolver (prefix, canonical_prefix); - item.accept_vis (resolver); - - NodeId current_module = resolver.resolver->peek_current_module_scope (); - resolver.mappings.insert_child_item_to_parent_module_mapping ( - item.get_node_id (), current_module); - } - - void visit (AST::Module &module) override - { - auto mod = CanonicalPath::new_seg (module.get_node_id (), - module.get_name ().as_string ()); - auto path = prefix.append (mod); - auto cpath = canonical_prefix.append (mod); - - resolver->get_name_scope ().insert ( - path, module.get_node_id (), module.get_locus (), false, - Rib::ItemType::Module, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, module.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, mod); - mappings.insert_module_child (current_module, module.get_node_id ()); - - resolver->push_new_module_scope (module.get_node_id ()); - for (auto &item : module.get_items ()) - ResolveTopLevel::go (*item, path, cpath); - - resolver->pop_module_scope (); - - mappings.insert_canonical_path (module.get_node_id (), cpath); - } - - void visit (AST::TypeAlias &alias) override - { - auto talias - = CanonicalPath::new_seg (alias.get_node_id (), - alias.get_new_type_name ().as_string ()); - auto path = prefix.append (talias); - auto cpath = canonical_prefix.append (talias); - - resolver->get_type_scope ().insert ( - path, alias.get_node_id (), alias.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, alias.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, talias); - mappings.insert_canonical_path (alias.get_node_id (), cpath); - } - - void visit (AST::TupleStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - } - - void visit (AST::Enum &enum_decl) override - { - auto decl - = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, enum_decl.get_node_id (), enum_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, enum_decl.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - resolver->push_new_module_scope (enum_decl.get_node_id ()); - for (auto &variant : enum_decl.get_variants ()) - ResolveTopLevel::go (*variant, path, cpath); - - resolver->pop_module_scope (); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - } - - void visit (AST::EnumItem &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemTuple &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemStruct &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemDiscriminant &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::StructStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - auto duplicate_item - = [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }; - - resolver->get_type_scope ().insert (path, struct_decl.get_node_id (), - struct_decl.get_locus (), false, - Rib::ItemType::Type, duplicate_item); - - if (struct_decl.is_unit_struct ()) - resolver->get_name_scope ().insert (path, struct_decl.get_node_id (), - struct_decl.get_locus (), false, - Rib::ItemType::Type, duplicate_item); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - } - - void visit (AST::Union &union_decl) override - { - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, union_decl.get_node_id (), union_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, union_decl.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - } - - void visit (AST::StaticItem &var) override - { - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, var.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - } - - void visit (AST::ConstantItem &constant) override - { - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - } - - void visit (AST::InherentImpl &impl_block) override - { - std::string raw_impl_type_path = impl_block.get_type ().as_string (); - CanonicalPath impl_type_seg - = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (), - raw_impl_type_path); - - CanonicalPath impl_type - = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), - impl_type_seg); - CanonicalPath impl_prefix = prefix.append (impl_type_seg); - - for (auto &impl_item : impl_block.get_impl_items ()) - ResolveToplevelImplItem::go (*impl_item, impl_prefix); - } - - void visit (AST::TraitImpl &impl_block) override - { - std::string raw_impl_type_path = impl_block.get_type ().as_string (); - CanonicalPath impl_type_seg - = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (), - raw_impl_type_path); - - std::string raw_trait_type_path = impl_block.get_trait_path ().as_string (); - CanonicalPath trait_type_seg - = CanonicalPath::new_seg (impl_block.get_trait_path ().get_node_id (), - raw_trait_type_path); - - CanonicalPath projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - trait_type_seg, - impl_type_seg); - CanonicalPath impl_prefix = prefix.append (projection); - - resolver->get_name_scope ().insert ( - impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false, - Rib::ItemType::TraitImpl, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, impl_block.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - for (auto &impl_item : impl_block.get_impl_items ()) - ResolveToplevelImplItem::go (*impl_item, impl_prefix); - } - - void visit (AST::Trait &trait) override - { - auto decl = CanonicalPath::new_seg (trait.get_node_id (), - trait.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, trait.get_node_id (), trait.get_locus (), false, - Rib::ItemType::Trait, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, trait.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - - for (auto &item : trait.get_trait_items ()) - ResolveTopLevelTraitItems::go (item.get (), path, cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (trait.get_node_id (), cpath); - } - - void visit (AST::ExternBlock &extern_block) override - { - for (auto &item : extern_block.get_extern_items ()) - { - ResolveToplevelExternItem::go (*item, prefix); - } - } - - void visit (AST::ExternCrate &extern_crate) override - { - if (extern_crate.is_marked_for_strip ()) - return; - - NodeId resolved_crate = UNKNOWN_NODEID; - if (extern_crate.references_self ()) - { - CrateNum crate_num = mappings.get_current_crate (); - resolved_crate = mappings.crate_num_to_nodeid (crate_num).value (); - } - else - { - auto cnum - = mappings.lookup_crate_name (extern_crate.get_referenced_crate ()); - if (!cnum) - { - rust_error_at (extern_crate.get_locus (), "unknown crate %qs", - extern_crate.get_referenced_crate ().c_str ()); - return; - } - if (auto resolved = mappings.crate_num_to_nodeid (*cnum)) - resolved_crate = resolved.value (); - else - { - rust_internal_error_at (extern_crate.get_locus (), - "failed to resolve crate to nodeid"); - return; - } - } - - if (resolved_crate == UNKNOWN_NODEID) - { - rust_error_at (extern_crate.get_locus (), "failed to resolve crate"); - return; - } - - // mark the node as resolved - resolver->insert_resolved_name (extern_crate.get_node_id (), - resolved_crate); - CanonicalPath decl - = extern_crate.has_as_clause () - ? CanonicalPath::new_seg (extern_crate.get_node_id (), - extern_crate.get_as_clause ()) - : CanonicalPath::new_seg (extern_crate.get_node_id (), - extern_crate.get_referenced_crate ()); - - resolver->get_type_scope ().insert ( - decl, resolved_crate, extern_crate.get_locus (), false, - Rib::ItemType::ExternCrate, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, extern_crate.get_locus ()); - r.add_range (locus); - rust_error_at (r, "defined multiple times"); - }); - } - -private: - ResolveTopLevel (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_TOPLEVEL_H diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc deleted file mode 100644 index 5ab0c44..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ /dev/null @@ -1,783 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-expr.h" -#include "rust-canonical-path.h" -#include "rust-type.h" -#include "rust-hir-map.h" - -namespace Rust { -namespace Resolver { - -// rust-ast-resolve-type.h - -NodeId -ResolveType::go (AST::Type &type) -{ - ResolveType resolver; - type.accept_vis (resolver); - return resolver.resolved_node; -} - -void -ResolveType::visit (AST::BareFunctionType &fntype) -{ - for (auto ¶m : fntype.get_function_params ()) - ResolveType::go (param.get_type ()); - - if (fntype.has_return_type ()) - ResolveType::go (fntype.get_return_type ()); -} - -void -ResolveType::visit (AST::TupleType &tuple) -{ - if (tuple.is_unit_type ()) - { - resolved_node = resolver->get_unit_type_node_id (); - return; - } - - for (auto &elem : tuple.get_elems ()) - ResolveType::go (*elem); -} - -void -ResolveType::visit (AST::TypePath &path) -{ - ResolveRelativeTypePath::go (path, resolved_node); -} - -void -ResolveType::visit (AST::QualifiedPathInType &path) -{ - ResolveRelativeQualTypePath::go (path); -} - -void -ResolveType::visit (AST::ArrayType &type) -{ - type.get_elem_type ().accept_vis (*this); - ResolveExpr::go (type.get_size_expr (), CanonicalPath::create_empty (), - CanonicalPath::create_empty ()); -} - -void -ResolveType::visit (AST::TraitObjectTypeOneBound &type) -{ - ResolveTypeBound::go (type.get_trait_bound ()); -} - -void -ResolveType::visit (AST::TraitObjectType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - { - /* NodeId bound_resolved_id = */ - ResolveTypeBound::go (*bound); - } -} - -void -ResolveType::visit (AST::ParenthesisedType &type) -{ - resolved_node = ResolveType::go (*type.get_type_in_parens ()); -} - -void -ResolveType::visit (AST::ReferenceType &type) -{ - resolved_node = ResolveType::go (type.get_type_referenced ()); -} - -void -ResolveType::visit (AST::RawPointerType &type) -{ - resolved_node = ResolveType::go (type.get_type_pointed_to ()); -} - -void -ResolveType::visit (AST::InferredType &) -{ - // nothing to do -} - -void -ResolveType::visit (AST::NeverType &) -{ - resolved_node = resolver->get_never_type_node_id (); -} - -void -ResolveType::visit (AST::SliceType &type) -{ - resolved_node = ResolveType::go (type.get_elem_type ()); -} - -void -ResolveType::visit (AST::ImplTraitType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); -} - -void -ResolveType::visit (AST::ImplTraitTypeOneBound &type) -{ - ResolveTypeBound::go (type.get_trait_bound ()); -} - -// resolve relative type-paths - -bool -ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) -{ - auto resolver = Resolver::get (); - auto &mappings = Analysis::Mappings::get (); - - NodeId module_scope_id = resolver->peek_current_module_scope (); - NodeId previous_resolved_node_id = module_scope_id; - for (size_t i = 0; i < path.get_segments ().size (); i++) - { - auto &segment = path.get_segments ().at (i); - bool is_first_segment = i == 0; - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - auto ident_string = segment->is_lang_item () - ? LangItem::PrettyString (segment->get_lang_item ()) - : segment->get_ident_segment ().as_string (); - - resolved_node_id = UNKNOWN_NODEID; - - if (segment->is_lang_item ()) - { - resolved_node_id = Analysis::Mappings::get ().get_lang_item_node ( - segment->get_lang_item ()); - previous_resolved_node_id = resolved_node_id; - } - else - { - bool in_middle_of_path = i > 0; - if (in_middle_of_path && segment->is_lower_self_seg ()) - { - rust_error_at (segment->get_locus (), ErrorCode::E0433, - "leading path segment %qs can only be used at the " - "beginning of a path", - segment->as_string ().c_str ()); - return false; - } - - if (segment->is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - - continue; - } - else if (segment->is_super_path_seg ()) - { - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment->get_locus (), - "cannot use super at the crate scope"); - return false; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - continue; - } - } - - switch (segment->get_type ()) - { - case AST::TypePathSegment::SegmentType::GENERIC: { - AST::TypePathSegmentGeneric *s - = static_cast<AST::TypePathSegmentGeneric *> (segment.get ()); - if (s->has_generic_args ()) - ResolveGenericArgs::go (s->get_generic_args ()); - } - break; - - case AST::TypePathSegment::SegmentType::REG: - // nothing to do - break; - - case AST::TypePathSegment::SegmentType::FUNCTION: - AST::TypePathSegmentFunction *fnseg - = static_cast<AST::TypePathSegmentFunction *> (segment.get ()); - - AST::TypePathFunction &fn = fnseg->get_type_path_function (); - for (auto ¶m : fn.get_params ()) - { - ResolveType::go (*param); - } - - if (fn.has_return_type ()) - { - ResolveType::go (fn.get_return_type ()); - } - - break; - } - - if (is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment->get_node_id (), ident_string); - if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment->get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment->get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (!segment->is_lang_item () && segment->is_lower_self_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - - continue; - } - } - - if (resolved_node_id == UNKNOWN_NODEID - && previous_resolved_node_id == module_scope_id) - { - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, ident_string); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment->get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment->get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment->get_locus (), - "Cannot find path %qs in this scope", - segment->as_string ().c_str ()); - return false; - } - } - } - - bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID; - if (did_resolve_segment) - { - if (mappings.node_is_module (resolved_node_id) - || mappings.node_is_crate (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - previous_resolved_node_id = resolved_node_id; - } - else if (is_first_segment) - { - rust_error_at (segment->get_locus (), ErrorCode::E0412, - "could not resolve type path %qs", - segment->as_string ().c_str ()); - return false; - } - } - - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (path.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (path.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (path.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (path.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - - return true; -} - -// qualified type paths - -ResolveRelativeQualTypePath::ResolveRelativeQualTypePath () - : failure_flag (false) -{} - -bool -ResolveRelativeQualTypePath::go (AST::QualifiedPathInType &path) -{ - ResolveRelativeQualTypePath o; - - // resolve the type and trait path - auto &qualified_path = path.get_qualified_path_type (); - if (!o.resolve_qual_seg (qualified_path)) - return false; - - // qualified types are similar to other paths in that we cannot guarantee - // that we can resolve the path at name resolution. We must look up - // associated types and type information to figure this out properly - - std::unique_ptr<AST::TypePathSegment> &associated - = path.get_associated_segment (); - - associated->accept_vis (o); - if (o.failure_flag) - return false; - - for (auto &seg : path.get_segments ()) - { - seg->accept_vis (o); - if (o.failure_flag) - return false; - } - - return true; -} - -bool -ResolveRelativeQualTypePath::resolve_qual_seg (AST::QualifiedPathType &seg) -{ - if (seg.is_error ()) - { - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return false; - } - - auto &type = seg.get_type (); - ResolveType::go (type); - - if (seg.has_as_clause ()) - ResolveType::go (seg.get_as_type_path ()); - - return true; -} - -void -ResolveRelativeQualTypePath::visit (AST::TypePathSegmentGeneric &seg) -{ - if (seg.is_error ()) - { - failure_flag = true; - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return; - } - - ResolveGenericArgs::go (seg.get_generic_args ()); -} - -void -ResolveRelativeQualTypePath::visit (AST::TypePathSegment &seg) -{ - if (seg.is_error ()) - { - failure_flag = true; - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return; - } -} - -// resolve to canonical path - -bool -ResolveTypeToCanonicalPath::go (AST::Type &type, CanonicalPath &result) -{ - ResolveTypeToCanonicalPath resolver; - type.accept_vis (resolver); - result = resolver.result; - return !resolver.result.is_empty (); -} - -void -ResolveTypeToCanonicalPath::visit (AST::TypePath &path) -{ - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->lookup_resolved_name (path.get_node_id (), &resolved_node)) - { - resolver->lookup_resolved_type (path.get_node_id (), &resolved_node); - } - - if (resolved_node == UNKNOWN_NODEID) - return; - - if (auto type_path = mappings.lookup_canonical_path (resolved_node)) - { - auto &final_seg = path.get_segments ().back (); - switch (final_seg->get_type ()) - { - case AST::TypePathSegment::SegmentType::GENERIC: { - AST::TypePathSegmentGeneric *s - = static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ()); - - std::vector<CanonicalPath> args; - if (s->has_generic_args ()) - { - ResolveGenericArgs::go (s->get_generic_args ()); - for (auto &generic : s->get_generic_args ().get_generic_args ()) - { - // FIXME: What do we want to do here in case there is a - // constant or an ambiguous const generic? - // TODO: At that point, will all generics have been - // disambiguated? Can we thus canonical resolve types and - // const and `rust_unreachable` on ambiguous types? - // This is probably fine as we just want to canonicalize - // types, right? - if (generic.get_kind () == AST::GenericArg::Kind::Type) - { - CanonicalPath arg = CanonicalPath::create_empty (); - bool ok - = ResolveTypeToCanonicalPath::go (generic.get_type (), - arg); - if (ok) - args.push_back (std::move (arg)); - } - } - } - - result = *type_path; - if (!args.empty ()) - { - // append this onto the path - std::string buf; - for (size_t i = 0; i < args.size (); i++) - { - bool has_next = (i + 1) < args.size (); - const auto &arg = args.at (i); - - buf += arg.get (); - if (has_next) - buf += ", "; - } - - std::string arg_seg = "<" + buf + ">"; - CanonicalPath argument_seg - = CanonicalPath::new_seg (s->get_node_id (), arg_seg); - result = result.append (argument_seg); - } - } - break; - - default: - result = *type_path; - break; - } - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::ReferenceType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_type_referenced (), path); - if (ok) - { - std::string ref_type_str = type.is_mut () ? "mut" : ""; - std::string ref_path = "&" + ref_type_str + " " + path.get (); - result = CanonicalPath::new_seg (type.get_node_id (), ref_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::RawPointerType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_type_pointed_to (), path); - if (ok) - { - std::string ptr_type_str - = type.get_pointer_type () == AST::RawPointerType::CONST ? "const" - : "mut"; - std::string ptr_path = "*" + ptr_type_str + " " + path.get (); - result = CanonicalPath::new_seg (type.get_node_id (), ptr_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::SliceType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_elem_type (), path); - if (ok) - { - std::string slice_path = "[" + path.get () + "]"; - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::TraitObjectTypeOneBound &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok - = ResolveTypeToCanonicalPath::go (type.get_trait_bound ().get_type_path (), - path); - if (ok) - { - std::string slice_path = "<dyn " + path.get () + ">"; - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type) -{ - rust_assert (!type.get_type_param_bounds ().empty ()); - - auto &first_bound = type.get_type_param_bounds ().front (); - - // Is it allowed or even possible to have a lifetime bound as a first bound? - if (first_bound->get_bound_type () == AST::TraitBound::LIFETIME) - rust_unreachable (); - - auto &trait = static_cast<AST::TraitBound &> (*first_bound); - - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (trait.get_type_path (), path); - - // right? - rust_assert (ok); - - auto slice_path = "<dyn " + path.get (); - - for (size_t idx = 1; idx < type.get_type_param_bounds ().size (); idx++) - { - auto &additional_bound = type.get_type_param_bounds ()[idx]; - - std::string str; - - switch (additional_bound->get_bound_type ()) - { - case AST::TypeParamBound::TRAIT: { - auto bound_path = CanonicalPath::create_empty (); - - auto &bound_type_path - = static_cast<AST::TraitBound &> (*additional_bound) - .get_type_path (); - bool ok - = ResolveTypeToCanonicalPath::go (bound_type_path, bound_path); - - if (!ok) - continue; - - str = bound_path.get (); - break; - } - case AST::TypeParamBound::LIFETIME: - rust_unreachable (); - break; - } - slice_path += " + " + str; - } - - slice_path += ">"; - - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); -} - -void -ResolveTypeToCanonicalPath::visit (AST::NeverType &type) -{ - result = CanonicalPath::new_seg (type.get_node_id (), "!"); -} - -void -ResolveTypeToCanonicalPath::visit (AST::TupleType &type) -{ - if (!type.is_unit_type ()) - rust_unreachable (); - - result = CanonicalPath::new_seg (type.get_node_id (), "()"); -} - -ResolveTypeToCanonicalPath::ResolveTypeToCanonicalPath () - : ResolverBase (), result (CanonicalPath::create_empty ()) -{} - -bool -ResolveGenericArgs::is_const_value_name (const CanonicalPath &path) -{ - NodeId resolved; - auto found = resolver->get_name_scope ().lookup (path, &resolved); - - return found; -} - -bool -ResolveGenericArgs::is_type_name (const CanonicalPath &path) -{ - NodeId resolved; - auto found = resolver->get_type_scope ().lookup (path, &resolved); - - return found; -} - -void -ResolveGenericArgs::disambiguate (AST::GenericArg &arg) -{ - auto path = canonical_prefix.append ( - CanonicalPath::new_seg (UNKNOWN_NODEID, arg.get_path ())); - - auto is_type = is_type_name (path); - auto is_value = is_const_value_name (path); - - // In case we cannot find anything, we resolve the ambiguity to a type. - // This causes the typechecker to error out properly and when necessary. - // But types also take priority over const values in the case of - // ambiguities, hence the weird control flow - if (is_type || (!is_type && !is_value)) - arg = arg.disambiguate_to_type (); - else if (is_value) - arg = arg.disambiguate_to_const (); -} - -void -ResolveGenericArgs::resolve_disambiguated_generic (AST::GenericArg &arg) -{ - switch (arg.get_kind ()) - { - case AST::GenericArg::Kind::Const: - ResolveExpr::go (arg.get_expression (), prefix, canonical_prefix); - break; - case AST::GenericArg::Kind::Type: - ResolveType::go (arg.get_type ()); - break; - default: - rust_unreachable (); - } -} -void -ResolveGenericArgs::go (AST::GenericArgs &generic_args) -{ - auto empty = CanonicalPath::create_empty (); - - go (generic_args, empty, empty); -} - -void -ResolveGenericArgs::go (AST::GenericArgs &generic_args, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - auto resolver = ResolveGenericArgs (prefix, canonical_prefix); - - for (auto &arg : generic_args.get_generic_args ()) - { - if (arg.get_kind () == AST::GenericArg::Kind::Either) - resolver.disambiguate (arg); - - resolver.resolve_disambiguated_generic (arg); - } - - for (auto &binding : generic_args.get_binding_args ()) - { - ResolveType::go (binding.get_type ()); - } -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h deleted file mode 100644 index 8379d0e..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ /dev/null @@ -1,280 +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_AST_RESOLVE_TYPE_H -#define RUST_AST_RESOLVE_TYPE_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-expr.h" -#include "rust-diagnostics.h" -#include "rust-hir-map.h" -#include "rust-path.h" -#include "rust-type.h" -#include "util/rust-hir-map.h" - -namespace Rust { -namespace Resolver { - -class ResolveRelativeTypePath -{ -public: - static bool go (AST::TypePath &path, NodeId &resolved_node_id); -}; - -class ResolveRelativeQualTypePath : public ResolverBase -{ - using ResolverBase::visit; - -public: - static bool go (AST::QualifiedPathInType &path); - - void visit (AST::TypePathSegmentGeneric &seg) override; - - void visit (AST::TypePathSegment &seg) override; - -protected: - bool resolve_qual_seg (AST::QualifiedPathType &seg); - -private: - ResolveRelativeQualTypePath (); - - bool failure_flag; -}; - -class ResolveType : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::Type &type); - - void visit (AST::BareFunctionType &fntype) override; - void visit (AST::TupleType &tuple) override; - void visit (AST::TypePath &path) override; - void visit (AST::QualifiedPathInType &path) override; - void visit (AST::ArrayType &type) override; - void visit (AST::ReferenceType &type) override; - void visit (AST::InferredType &type) override; - void visit (AST::NeverType &type) override; - void visit (AST::RawPointerType &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; - void visit (AST::TraitObjectType &type) override; - void visit (AST::ParenthesisedType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - -private: - ResolveType () : ResolverBase () {} -}; - -class ResolveTypeBound : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::TypeParamBound &type) - { - ResolveTypeBound resolver; - type.accept_vis (resolver); - return resolver.resolved_node; - }; - - void visit (AST::TraitBound &bound) override - { - resolved_node = ResolveType::go (bound.get_type_path ()); - } - -private: - ResolveTypeBound () : ResolverBase () {} -}; - -class ResolveGenericParams : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (std::vector<std::unique_ptr<AST::GenericParam>> ¶ms, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveGenericParams resolver (prefix, canonical_prefix); - - // this needs to be done in two phases as they can be used and defined later - // in bounds - for (auto ¶m : params) - param->accept_vis (resolver); - - resolver.first_pass = false; - - for (auto ¶m : params) - param->accept_vis (resolver); - } - - static void go_single (AST::GenericParam ¶m, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveGenericParams resolver (prefix, canonical_prefix); - - param.accept_vis (resolver); - resolver.first_pass = false; - param.accept_vis (resolver); - } - - void visit (AST::ConstGenericParam ¶m) override - { - if (first_pass) - ResolveType::go (param.get_type ()); - else if (param.has_default_value ()) - ResolveExpr::go (param.get_default_value ().get_expression (), prefix, - canonical_prefix); - } - - void visit (AST::TypeParam ¶m) override - { - if (first_pass) - { - // if it has a type lets resolve it - if (param.has_type ()) - ResolveType::go (param.get_type ()); - - auto seg = CanonicalPath::new_seg ( - param.get_node_id (), param.get_type_representation ().as_string ()); - resolver->get_type_scope ().insert ( - seg, param.get_node_id (), param.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (param.get_locus (), - "generic param defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - - mappings.insert_canonical_path (param.get_node_id (), seg); - } - else if (param.has_type_param_bounds ()) - { - for (auto &bound : param.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); - } - } - -private: - ResolveGenericParams (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), first_pass (true), prefix (prefix), - canonical_prefix (canonical_prefix) - {} - - bool first_pass; - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveWhereClause : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void Resolve (AST::WhereClause &where_clause) - { - ResolveWhereClause r; - for (auto &clause : where_clause.get_items ()) - clause->accept_vis (r); - } - - void visit (AST::TypeBoundWhereClauseItem &item) override - { - ResolveType::go (item.get_type ()); - if (item.has_type_param_bounds ()) - { - for (auto &bound : item.get_type_param_bounds ()) - { - ResolveTypeBound::go (*bound); - } - } - } - -private: - ResolveWhereClause () : ResolverBase () {} -}; - -class ResolveTypeToCanonicalPath : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static bool go (AST::Type &type, CanonicalPath &result); - - void visit (AST::TypePath &path) override; - - void visit (AST::ReferenceType &type) override; - - void visit (AST::RawPointerType &type) override; - - void visit (AST::SliceType &type) override; - - void visit (AST::TraitObjectTypeOneBound &type) override; - - void visit (AST::TraitObjectType &type) override; - - void visit (AST::NeverType &type) override; - - void visit (AST::TupleType &type) override; - -private: - ResolveTypeToCanonicalPath (); - - CanonicalPath result; -}; - -class ResolveGenericArgs : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::GenericArgs &generic_args); - static void go (AST::GenericArgs &generic_args, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - -private: - ResolveGenericArgs (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - bool is_type_name (const CanonicalPath &path); - bool is_const_value_name (const CanonicalPath &path); - - /** - * Resolve a disambiguated generic arg - */ - void disambiguate (AST::GenericArg &arg); - - /** - * Resolve a disambiguated generic arg - */ - void resolve_disambiguated_generic (AST::GenericArg &arg); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_TYPE_H diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc deleted file mode 100644 index 3e3c992..0000000 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-resolve.h" -#include "rust-ast-full.h" -#include "rust-tyty.h" -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-item.h" -#include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-struct-expr-field.h" - -extern bool -saw_errors (void); - -namespace Rust { -namespace Resolver { - -// NameResolution - -NameResolution * -NameResolution::get () -{ - static NameResolution *instance; - if (instance == nullptr) - instance = new NameResolution (); - - return instance; -} - -NameResolution::NameResolution () - : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()) -{ - // these are global - resolver->get_type_scope ().push (mappings.get_next_node_id ()); - resolver->insert_builtin_types (resolver->get_type_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); -} - -void -NameResolution::Resolve (AST::Crate &crate) -{ - auto resolver = get (); - resolver->go (crate); -} - -void -NameResolution::go (AST::Crate &crate) -{ - // lookup current crate name - CrateNum cnum = mappings.get_current_crate (); - - // Clones the crate name instead of references due to gcc's possibly - // dangling references warnings - const auto crate_name = mappings.get_crate_name (cnum).value (); - - // setup the ribs - NodeId scope_node_id = crate.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // get the root segment - CanonicalPath crate_prefix - = CanonicalPath::new_seg (scope_node_id, crate_name); - crate_prefix.set_crate_num (cnum); - - // setup a dummy crate node - resolver->get_name_scope ().insert ( - CanonicalPath::new_seg (crate.get_node_id (), "__$$crate__"), - crate.get_node_id (), UNDEF_LOCATION); - - // setup the root scope - resolver->push_new_module_scope (scope_node_id); - - // first gather the top-level namespace names then we drill down so this - // allows for resolving forward declarations since an impl block might have - // a Self type Foo which is defined after the impl block for example. - for (auto &item : crate.items) - ResolveTopLevel::go (*item, CanonicalPath::create_empty (), crate_prefix); - - // FIXME remove this - if (saw_errors ()) - { - resolver->pop_module_scope (); - return; - } - - // next we can drill down into the items and their scopes - for (auto &item : crate.items) - ResolveItem::go (*item, CanonicalPath::create_empty (), crate_prefix); - - // done - resolver->pop_module_scope (); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 7528e79..f1c0e5c 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -25,6 +25,21 @@ namespace Rust { namespace Resolver2_0 { void +DefaultResolver::visit (AST::Crate &crate) +{ + auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); }; + + auto &mappings = Analysis::Mappings::get (); + + auto crate_num = mappings.lookup_crate_num (crate.get_node_id ()); + rust_assert (crate_num.has_value ()); + auto crate_name = mappings.get_crate_name (*crate_num); + rust_assert (crate_name.has_value ()); + + ctx.canonical_ctx.scope_crate (crate.get_node_id (), *crate_name, inner_fn); +} + +void DefaultResolver::visit (AST::BlockExpr &expr) { // extracting the lambda from the `scoped` call otherwise the code looks like @@ -38,19 +53,32 @@ DefaultResolver::visit (AST::BlockExpr &expr) void DefaultResolver::visit (AST::Module &module) { - auto item_fn = [this, &module] () { AST::DefaultASTVisitor::visit (module); }; + auto item_fn_1 + = [this, &module] () { AST::DefaultASTVisitor::visit (module); }; + + auto item_fn_2 = [this, &module, &item_fn_1] () { + ctx.canonical_ctx.scope (module.get_node_id (), module.get_name (), + std::move (item_fn_1)); + }; - ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn, + ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn_2, module.get_name ()); } void DefaultResolver::visit (AST::Function &function) { - auto def_fn + auto def_fn_1 = [this, &function] () { AST::DefaultASTVisitor::visit (function); }; - ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn); + auto def_fn_2 = [this, &function, &def_fn_1] () { + ctx.canonical_ctx.scope (function.get_node_id (), + function.get_function_name (), + std::move (def_fn_1)); + }; + + ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn_2, + function.get_function_name ()); } void @@ -61,73 +89,252 @@ DefaultResolver::visit (AST::ForLoopExpr &expr) } void -DefaultResolver::visit (AST::Trait &trait) +DefaultResolver::visit_if_let_patterns (AST::IfLetExpr &expr) { - auto inner_fn = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); }; + for (auto &pattern : expr.get_patterns ()) + visit (pattern); +} - ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn, +void +DefaultResolver::visit (AST::IfLetExpr &expr) +{ + auto inner_vis = [this, &expr] () { + visit_if_let_patterns (expr); + visit (expr.get_if_block ()); + }; + + visit_outer_attrs (expr); + + visit (expr.get_value_expr ()); + + ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis); +} + +void +DefaultResolver::visit (AST::IfLetExprConseqElse &expr) +{ + DefaultResolver::visit (static_cast<AST::IfLetExpr &> (expr)); + visit (expr.get_else_block ()); +} + +void +DefaultResolver::visit (AST::Trait &trait) +{ + visit_outer_attrs (trait); + visit (trait.get_visibility ()); + visit_inner_attrs (trait); + + auto inner_fn_1 = [this, &trait] () { + for (auto &item : trait.get_trait_items ()) + visit (item); + }; + + auto inner_fn_2 = [this, &trait, &inner_fn_1] () { + visit (trait.get_implicit_self ()); + for (auto &generic : trait.get_generic_params ()) + visit (generic); + if (trait.has_where_clause ()) + visit (trait.get_where_clause ()); + for (auto &bound : trait.get_type_param_bounds ()) + visit (bound); + + ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_1); + }; + + auto inner_fn_3 = [this, &trait, &inner_fn_2] () { + ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (), + std::move (inner_fn_2)); + }; + + ctx.scoped (Rib::Kind::Generics, trait.get_node_id (), inner_fn_3, trait.get_identifier () /* FIXME: Is that valid?*/); } void DefaultResolver::visit (AST::InherentImpl &impl) { - auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + visit_inner_attrs (impl); + + auto inner_fn_1 = [this, &impl] () { + for (auto &item : impl.get_impl_items ()) + visit (item); + }; + + auto inner_fn_2 = [this, &impl, &inner_fn_1] () { + maybe_insert_big_self (impl); + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + visit_impl_type (impl.get_type ()); + + ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1); + }; + + auto inner_fn_3 = [this, &impl, &inner_fn_2] () { + ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2)); + }; + + ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3); } void DefaultResolver::visit (AST::TraitImpl &impl) { - auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + visit_inner_attrs (impl); + + auto inner_fn_1 = [this, &impl] () { + for (auto &item : impl.get_impl_items ()) + visit (item); + }; + + auto inner_fn_2 = [this, &impl, &inner_fn_1] () { + maybe_insert_big_self (impl); + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + visit_impl_type (impl.get_type ()); + visit (impl.get_trait_path ()); + + ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1); + }; + + auto inner_fn_3 = [this, &impl, &inner_fn_2] () { + ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2)); + }; + + ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3); } void DefaultResolver::visit (AST::StructStruct &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_struct_name ()); + inner_fn_2, type.get_struct_name ()); } void DefaultResolver::visit (AST::TupleStruct &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_struct_name ()); + inner_fn_2, type.get_struct_name ()); +} + +void +DefaultResolver::visit (AST::EnumItem &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemTuple &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemStruct &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemDiscriminant &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); } void DefaultResolver::visit (AST::Enum &type) { - auto variant_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - variant_fn, type.get_identifier ()); + inner_fn_2, type.get_identifier ()); } void DefaultResolver::visit (AST::Union &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_identifier ()); + inner_fn_2, type.get_identifier ()); } void DefaultResolver::visit (AST::TypeAlias &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_new_type_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_new_type_name ()); + inner_fn_2, type.get_new_type_name ()); +} + +void +DefaultResolver::visit_closure_params (AST::ClosureExpr &expr) +{ + for (auto ¶m : expr.get_params ()) + visit (param); +} + +void +DefaultResolver::visit (AST::ClosureExpr &expr) +{ + auto expr_fn = [this, &expr] () { + visit_closure_params (expr); + visit (expr.get_definition_expr ()); + }; + + visit_outer_attrs (expr); + + ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), expr_fn); } void @@ -136,7 +343,7 @@ DefaultResolver::visit (AST::ClosureExprInner &expr) if (expr.is_marked_for_strip ()) return; - AST::DefaultASTVisitor::visit (expr); + visit (static_cast<AST::ClosureExpr &> (expr)); } void @@ -145,7 +352,8 @@ DefaultResolver::visit (AST::ClosureExprInnerTyped &expr) if (expr.is_marked_for_strip ()) return; - AST::DefaultASTVisitor::visit (expr); + visit (static_cast<AST::ClosureExpr &> (expr)); + visit (expr.get_return_type ()); } void @@ -160,23 +368,78 @@ DefaultResolver::visit (AST::MatchExpr &expr) void DefaultResolver::visit (AST::ConstantItem &item) { - if (item.has_expr ()) - { - auto expr_vis - = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; - // FIXME: Why do we need a Rib here? - ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis); - } + auto expr_vis_2 = [this, &item, &expr_vis_1] () { + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + std::move (expr_vis_1)); + }; + + // FIXME: Why do we need a Rib here? + ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } void DefaultResolver::visit (AST::StaticItem &item) { - auto expr_vis = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + auto expr_vis_2 = [this, &item, &expr_vis_1] () { + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + std::move (expr_vis_1)); + }; // FIXME: Why do we need a Rib here? - ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis); + ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); +} + +void +DefaultResolver::visit (AST::TypeParam ¶m) +{ + auto expr_vis = [this, ¶m] () { AST::DefaultASTVisitor::visit (param); }; + + ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis); +} + +void +DefaultResolver::visit_extern_crate (AST::ExternCrate &extern_crate, + AST::Crate &crate, CrateNum num) +{ + visit (crate); +} + +void +DefaultResolver::visit (AST::ExternCrate &crate) +{ + auto &mappings = Analysis::Mappings::get (); + auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); + + if (!num_opt) + { + rust_error_at (crate.get_locus (), "unknown crate %qs", + crate.get_referenced_crate ().c_str ()); + return; + } + + CrateNum num = *num_opt; + + AST::Crate &referenced_crate = mappings.get_ast_crate (num); + + auto sub_visitor_1 + = [&, this] () { visit_extern_crate (crate, referenced_crate, num); }; + + auto sub_visitor_2 = [&] () { + ctx.canonical_ctx.scope_crate (referenced_crate.get_node_id (), + crate.get_referenced_crate (), + std::move (sub_visitor_1)); + }; + + if (crate.has_as_clause ()) + ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (), + sub_visitor_2, crate.get_as_clause ()); + else + ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (), + sub_visitor_2, crate.get_referenced_crate ()); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 587d7d4..cf0df68 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -39,6 +39,7 @@ public: virtual ~DefaultResolver () {} + void visit (AST::Crate &) override; // First, our lexical scope expressions - these visit their sub nodes, always // these nodes create new scopes and ribs - they are often used to declare new // variables, such as a for loop's iterator, or a function's arguments @@ -46,18 +47,35 @@ public: void visit (AST::Module &) override; void visit (AST::Function &) override; void visit (AST::ForLoopExpr &expr) override; + virtual void visit_if_let_patterns (AST::IfLetExpr &expr); + void visit (AST::IfLetExpr &expr) override; + void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::Trait &) override; + // used to handle Self insertion in TopLevel + virtual void maybe_insert_big_self (AST::Impl &) {} + virtual void visit_impl_type (AST::Type &type) { visit (type); } void visit (AST::InherentImpl &) override; void visit (AST::TraitImpl &) override; + void visit (AST::TypeParam &) override; + + virtual void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum); + void visit (AST::ExternCrate &) override; + // type dec nodes, which visit their fields or variants by default void visit (AST::StructStruct &) override; void visit (AST::TupleStruct &) override; + void visit (AST::EnumItem &) override; + void visit (AST::EnumItemTuple &) override; + void visit (AST::EnumItemStruct &) override; + void visit (AST::EnumItemDiscriminant &) override; void visit (AST::Enum &) override; void visit (AST::Union &) override; void visit (AST::TypeAlias &) override; // Visitors that visit their expression node(s) + virtual void visit_closure_params (AST::ClosureExpr &); + virtual void visit (AST::ClosureExpr &); void visit (AST::ClosureExprInner &) override; void visit (AST::ClosureExprInnerTyped &) override; void visit (AST::MatchExpr &) override; diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index afaca1f..0dff831 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -17,8 +17,11 @@ // <http://www.gnu.org/licenses/>. #include "rust-early-name-resolver-2.0.h" -#include "rust-ast-full.h" +#include "optional.h" +#include "options.h" #include "rust-diagnostics.h" +#include "rust-hir-map.h" +#include "rust-item.h" #include "rust-toplevel-name-resolver-2.0.h" #include "rust-attributes.h" #include "rust-finalize-imports-2.0.h" @@ -62,21 +65,22 @@ Early::go (AST::Crate &crate) // We now proceed with resolving macros, which can be nested in almost any // items textual_scope.push (); - for (auto &item : crate.items) - item->accept_vis (*this); + + visit (crate); + textual_scope.pop (); } bool Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob) { - auto resolved - = ctx.resolve_path (glob.to_resolve.get_segments (), Namespace::Types); + auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types); if (!resolved.has_value ()) return false; - auto result - = Analysis::Mappings::get ().lookup_ast_module (resolved->get_node_id ()); + auto result = Analysis::Mappings::get ().lookup_glob_container ( + resolved->get_node_id ()); + if (!result) return false; @@ -141,6 +145,10 @@ Early::build_import_mapping ( // be moved into the newly created import mappings auto path = import.to_resolve; + // used to skip the "unresolved import" error + // if we output other errors during resolution + size_t old_error_count = macro_resolve_errors.size (); + switch (import.kind) { case TopLevel::ImportKind::Kind::Glob: @@ -154,7 +162,7 @@ Early::build_import_mapping ( break; } - if (!found) + if (!found && old_error_count == macro_resolve_errors.size ()) collect_error (Error (path.get_final_segment ().get_locus (), ErrorCode::E0433, "unresolved import %qs", path.as_string ().c_str ())); @@ -246,7 +254,12 @@ Early::visit (AST::Module &module) void Early::visit (AST::MacroInvocation &invoc) { - auto path = invoc.get_invoc_data ().get_path (); + auto &path = invoc.get_invoc_data ().get_path (); + + // We special case the `offset_of!()` macro if the flag is here, otherwise + // we accept whatever `offset_of!()` definition we resolved to. + auto resolve_offset_of + = flag_assume_builtin_offset_of && (path.as_string () == "offset_of"); if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) @@ -269,14 +282,16 @@ Early::visit (AST::MacroInvocation &invoc) // we won't have changed `definition` from `nullopt` if there are more // than one segments in our path if (!definition.has_value ()) - definition = ctx.resolve_path (path.get_segments (), Namespace::Macros); + definition = ctx.resolve_path (path, Namespace::Macros); - // if the definition still does not have a value, then it's an error + // if the definition still does not have a value, then it's an error - unless + // we should automatically resolve offset_of!() calls if (!definition.has_value ()) { - collect_error (Error (invoc.get_locus (), ErrorCode::E0433, - "could not resolve macro invocation %qs", - path.as_string ().c_str ())); + if (!resolve_offset_of) + collect_error (Error (invoc.get_locus (), ErrorCode::E0433, + "could not resolve macro invocation %qs", + path.as_string ().c_str ())); return; } @@ -311,8 +326,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) auto traits = attr.get_traits_to_derive (); for (auto &trait : traits) { - auto definition = ctx.resolve_path (trait.get ().get_segments (), - Namespace::Macros); + auto definition + = ctx.resolve_path (trait.get (), Namespace::Macros); if (!definition.has_value ()) { // FIXME: Change to proper error message @@ -325,18 +340,17 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) auto pm_def = mappings.lookup_derive_proc_macro_def ( definition->get_node_id ()); - rust_assert (pm_def.has_value ()); - - mappings.insert_derive_proc_macro_invocation (trait, - pm_def.value ()); + if (pm_def.has_value ()) + mappings.insert_derive_proc_macro_invocation (trait, + pm_def.value ()); } } else if (Analysis::BuiltinAttributeMappings::get () ->lookup_builtin (name) .is_error ()) // Do not resolve builtins { - auto definition = ctx.resolve_path (attr.get_path ().get_segments (), - Namespace::Macros); + auto definition + = ctx.resolve_path (attr.get_path (), Namespace::Macros); if (!definition.has_value ()) { // FIXME: Change to proper error message @@ -348,7 +362,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) auto pm_def = mappings.lookup_attribute_proc_macro_def ( definition->get_node_id ()); - rust_assert (pm_def.has_value ()); + if (!pm_def.has_value ()) + return; mappings.insert_attribute_proc_macro_invocation (attr.get_path (), pm_def.value ()); @@ -390,12 +405,12 @@ void Early::finalize_glob_import (NameResolutionContext &ctx, const Early::ImportPair &mapping) { - auto module = Analysis::Mappings::get ().lookup_ast_module ( - mapping.data.module ().get_node_id ()); - rust_assert (module); + auto container = Analysis::Mappings::get ().lookup_glob_container ( + mapping.data.container ().get_node_id ()); - GlobbingVisitor glob_visitor (ctx); - glob_visitor.go (module.value ()); + rust_assert (container); + + GlobbingVisitor (ctx).go (container.value ()); } void @@ -417,12 +432,15 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) declared_name = rebind.get_identifier ().as_string (); locus = rebind.get_identifier ().get_locus (); break; - case AST::UseTreeRebind::NewBindType::NONE: { + case AST::UseTreeRebind::NewBindType::NONE: + { const auto &segments = path.get_segments (); // We don't want to insert `self` with `use module::self` if (path.get_final_segment ().is_lower_self_seg ()) { - rust_assert (segments.size () > 1); + // Erroneous `self` or `{self}` use declaration + if (segments.size () == 1) + break; declared_name = segments[segments.size () - 2].as_string (); } else @@ -431,8 +449,8 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) break; } case AST::UseTreeRebind::NewBindType::WILDCARD: - rust_unreachable (); - break; + // We don't want to insert it into the trie + return; } for (auto &&definition : data.definitions ()) @@ -443,6 +461,19 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) void Early::visit (AST::UseDeclaration &decl) { + // We do not want to visit the use trees, we're only looking for top level + // rebind. eg. `use something;` or `use something::other;` + if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind) + { + auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ()); + if (rebind.get_path ().get_final_segment ().is_lower_self_seg ()) + { + collect_error ( + Error (decl.get_locus (), ErrorCode::E0429, + "%<self%> imports are only allowed within a { } list")); + } + } + auto &imports = toplevel.get_imports_to_resolve (); auto current_import = imports.find (decl.get_node_id ()); if (current_import != imports.end ()) @@ -468,5 +499,31 @@ Early::visit (AST::UseDeclaration &decl) DefaultResolver::visit (decl); } +void +Early::visit (AST::UseTreeList &use_list) +{ + if (!use_list.has_path ()) + { + for (auto &&tree : use_list.get_trees ()) + { + if (tree->get_kind () == AST::UseTree::Kind::Rebind) + { + auto &rebind = static_cast<AST::UseTreeRebind &> (*tree); + auto path_size = rebind.get_path ().get_segments ().size (); + if (path_size == 1 + && rebind.get_path () + .get_final_segment () + .is_lower_self_seg ()) + { + collect_error (Error (rebind.get_locus (), ErrorCode::E0431, + "%<self%> import can only appear in an " + "import list with a non-empty prefix")); + } + } + } + } + DefaultResolver::visit (use_list); +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index c4226fe..3940386 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -61,6 +61,7 @@ public: void visit (AST::Function &) override; void visit (AST::StructStruct &) override; void visit (AST::UseDeclaration &) override; + void visit (AST::UseTreeList &) override; struct ImportData { @@ -83,15 +84,15 @@ public: return ImportData (Kind::Rebind, std::move (definitions)); } - static ImportData Glob (Rib::Definition module) + static ImportData Glob (Rib::Definition container) { - return ImportData (Kind::Glob, module); + return ImportData (Kind::Glob, container); } - Rib::Definition module () const + Rib::Definition container () const { rust_assert (kind == Kind::Glob); - return glob_module; + return glob_container; } std::vector<std::pair<Rib::Definition, Namespace>> definitions () const @@ -107,8 +108,8 @@ public: : kind (kind), resolved_definitions (std::move (definitions)) {} - ImportData (Kind kind, Rib::Definition module) - : kind (kind), glob_module (module) + ImportData (Kind kind, Rib::Definition container) + : kind (kind), glob_container (container) {} // TODO: Should this be a union? @@ -117,7 +118,7 @@ public: std::vector<std::pair<Rib::Definition, Namespace>> resolved_definitions; // For Glob - Rib::Definition glob_module; + Rib::Definition glob_container; }; struct ImportPair @@ -218,7 +219,6 @@ private: std::vector<std::pair<Rib::Definition, Namespace>> resolve_path_in_all_ns (const P &path) { - const auto &segments = path.get_segments (); std::vector<std::pair<Rib::Definition, Namespace>> resolved; // Pair a definition with the namespace it was found in @@ -229,13 +229,22 @@ private: }; }; - ctx.resolve_path (segments, Namespace::Values) + std::vector<Error> value_errors; + std::vector<Error> type_errors; + std::vector<Error> macro_errors; + + ctx.resolve_path (path, value_errors, Namespace::Values) .map (pair_with_ns (Namespace::Values)); - ctx.resolve_path (segments, Namespace::Types) + ctx.resolve_path (path, type_errors, Namespace::Types) .map (pair_with_ns (Namespace::Types)); - ctx.resolve_path (segments, Namespace::Macros) + ctx.resolve_path (path, macro_errors, Namespace::Macros) .map (pair_with_ns (Namespace::Macros)); + if (!value_errors.empty () && !type_errors.empty () + && !macro_errors.empty ()) + for (auto &ent : value_errors) + collect_error (std::move (ent)); + return resolved; } diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc deleted file mode 100644 index fc9a26c..0000000 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ /dev/null @@ -1,589 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-early-name-resolver.h" -#include "rust-pattern.h" -#include "rust-name-resolver.h" -#include "rust-macro-builtins.h" -#include "rust-attribute-values.h" - -namespace Rust { -namespace Resolver { - -// Check if a module contains the `#[macro_use]` attribute -static bool -is_macro_use_module (const AST::Module &mod) -{ - for (const auto &attr : mod.get_outer_attrs ()) - if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE) - return true; - - return false; -} - -std::vector<std::unique_ptr<AST::Item>> -EarlyNameResolver::accumulate_escaped_macros (AST::Module &module) -{ - if (!is_macro_use_module (module)) - return {}; - - // Parse the module's items if they haven't been expanded and the file - // should be parsed (i.e isn't hidden behind an untrue or impossible cfg - // directive) - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - - std::vector<std::unique_ptr<AST::Item>> escaped_macros; - - scoped (module.get_node_id (), [&module, &escaped_macros, this] { - for (auto &item : module.get_items ()) - { - if (item->get_item_kind () == AST::Item::Kind::Module) - { - auto &module = *static_cast<AST::Module *> (item.get ()); - auto new_macros = accumulate_escaped_macros (module); - - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (escaped_macros)); - - continue; - } - - if (item->get_item_kind () == AST::Item::Kind::MacroRulesDefinition) - escaped_macros.emplace_back (item->clone_item ()); - } - }); - - return escaped_macros; -} - -EarlyNameResolver::EarlyNameResolver () - : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()), - mappings (Analysis::Mappings::get ()) -{} - -void -EarlyNameResolver::go (AST::Crate &crate) -{ - visit (crate); -} - -void -EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args) -{ - for (auto &arg : generic_args.get_generic_args ()) - arg.accept_vis (*this); - - for (auto &arg : generic_args.get_binding_args ()) - arg.get_type ().accept_vis (*this); -} - -void -EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path) -{ - path.get_type ().accept_vis (*this); - - if (path.has_as_clause ()) - path.get_as_type_path ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::Crate &crate) -{ - std::vector<std::unique_ptr<AST::Item>> new_items; - auto items = crate.take_items (); - - scoped (crate.get_node_id (), [&items, &new_items, this] { - for (auto &&item : items) - { - auto new_macros = std::vector<std::unique_ptr<AST::Item>> (); - - if (item->get_item_kind () == AST::Item::Kind::Module) - new_macros = accumulate_escaped_macros ( - *static_cast<AST::Module *> (item.get ())); - - new_items.emplace_back (std::move (item)); - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (new_items)); - } - }); - - crate.set_items (std::move (new_items)); - - scoped (crate.get_node_id (), [&crate, this] () { - for (auto &item : crate.items) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::DelimTokenTree &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputMetaItemContainer &) -{} - -void -EarlyNameResolver::visit (AST::IdentifierExpr &) -{} - -void -EarlyNameResolver::visit (AST::LifetimeParam &) -{} - -void -EarlyNameResolver::visit (AST::ConstGenericParam &) -{} - -// FIXME: ARTHUR: Do we need to perform macro resolution for paths as well? -// std::arch::asm!()? -void -EarlyNameResolver::visit (AST::PathInExpression &path) -{ - if (!path.is_lang_item ()) - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment) -{ - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::QualifiedPathInExpression &path) -{ - resolve_qualified_path_type (path.get_qualified_path_type ()); - - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::QualifiedPathInType &path) -{ - resolve_qualified_path_type (path.get_qualified_path_type ()); - - for (auto &segment : path.get_segments ()) - segment->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::LiteralExpr &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputLiteral &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputMacro &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemLitExpr &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemPathLit &) -{} - -void -EarlyNameResolver::visit (AST::StructExprStruct &) -{} - -void -EarlyNameResolver::visit (AST::StructExprFieldIdentifier &) -{} - -void -EarlyNameResolver::visit (AST::StructExprStructBase &) -{} - -void -EarlyNameResolver::visit (AST::BlockExpr &expr) -{ - scoped (expr.get_node_id (), [&expr, this] () { - for (auto &stmt : expr.get_statements ()) - stmt->accept_vis (*this); - - if (expr.has_tail_expr ()) - expr.get_tail_expr ().accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ContinueExpr &) -{} - -void -EarlyNameResolver::visit (AST::RangeFullExpr &) -{} - -void -EarlyNameResolver::visit (AST::ForLoopExpr &expr) -{ - scoped (expr.get_node_id (), [&expr, this] () { - expr.get_pattern ().accept_vis (*this); - expr.get_iterator_expr ().accept_vis (*this); - expr.get_loop_block ().accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::IfLetExpr &expr) -{ - expr.get_value_expr ().accept_vis (*this); - - scoped (expr.get_node_id (), - [&expr, this] () { expr.get_if_block ().accept_vis (*this); }); -} - -void -EarlyNameResolver::visit (AST::MatchExpr &expr) -{ - expr.get_scrutinee_expr ().accept_vis (*this); - - scoped (expr.get_node_id (), [&expr, this] () { - for (auto &arm : expr.get_match_cases ()) - { - scoped (arm.get_node_id (), [&arm, this] () { - if (arm.get_arm ().has_match_arm_guard ()) - arm.get_arm ().get_guard_expr ().accept_vis (*this); - - for (auto &pattern : arm.get_arm ().get_patterns ()) - pattern->accept_vis (*this); - - arm.get_expr ().accept_vis (*this); - }); - } - }); -} - -void -EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &) -{} - -void -EarlyNameResolver::visit (AST::Module &module) -{ - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - - // so we need to only go "one scope down" for fetching macros. Macros within - // functions are still scoped only within that function. But we have to be - // careful because nested modules with #[macro_use] actually works! - std::vector<std::unique_ptr<AST::Item>> new_items; - auto items = module.take_items (); - - scoped (module.get_node_id (), [&items, &new_items, this] { - for (auto &&item : items) - { - auto new_macros = std::vector<std::unique_ptr<AST::Item>> (); - - if (item->get_item_kind () == AST::Item::Kind::Module) - new_macros = accumulate_escaped_macros ( - *static_cast<AST::Module *> (item.get ())); - - new_items.emplace_back (std::move (item)); - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (new_items)); - } - }); - - module.set_items (std::move (new_items)); - - scoped (module.get_node_id (), [&module, this] () { - for (auto &item : module.get_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ExternCrate &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeGlob &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeList &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeRebind &) -{} - -void -EarlyNameResolver::visit (AST::UseDeclaration &) -{} - -void -EarlyNameResolver::visit (AST::EnumItem &) -{} - -void -EarlyNameResolver::visit (AST::Union &) -{} - -void -EarlyNameResolver::visit (AST::TraitItemType &) -{} - -void -EarlyNameResolver::visit (AST::Trait &trait) -{ - // shouldn't need to visit trait.get_implicit_self () - - for (auto &generic : trait.get_generic_params ()) - generic->accept_vis (*this); - - scoped (trait.get_node_id (), [&trait, this] () { - for (auto &item : trait.get_trait_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::InherentImpl &impl) -{ - impl.get_type ().accept_vis (*this); - - for (auto &generic : impl.get_generic_params ()) - generic->accept_vis (*this); - - scoped (impl.get_node_id (), [&impl, this] () { - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::TraitImpl &impl) -{ - impl.get_type ().accept_vis (*this); - - for (auto &generic : impl.get_generic_params ()) - generic->accept_vis (*this); - - scoped (impl.get_node_id (), [&impl, this] () { - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ExternalTypeItem &item) -{ - // nothing to do? -} - -void -EarlyNameResolver::visit (AST::ExternBlock &block) -{ - scoped (block.get_node_id (), [&block, this] () { - for (auto &item : block.get_extern_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::MacroMatchRepetition &) -{} - -void -EarlyNameResolver::visit (AST::MacroMatcher &) -{} - -void -EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def) -{ - auto path = CanonicalPath::new_seg (rules_def.get_node_id (), - rules_def.get_rule_name ().as_string ()); - resolver.get_macro_scope ().insert (path, rules_def.get_node_id (), - rules_def.get_locus ()); - - /* Since the EarlyNameResolver runs multiple time (fixed point algorithm) - * we could be inserting the same macro def over and over again until we - * implement some optimizations */ - // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead - if (mappings.lookup_macro_def (rules_def.get_node_id ())) - return; - - mappings.insert_macro_def (&rules_def); - rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]", - path.get ().c_str ()); -} - -void -EarlyNameResolver::visit (AST::MacroInvocation &invoc) -{ - auto &invoc_data = invoc.get_invoc_data (); - auto has_semicolon = invoc.has_semicolon (); - - if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) - for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) - pending_invoc->accept_vis (*this); - - // ?? - // switch on type of macro: - // - '!' syntax macro (inner switch) - // - procedural macro - "A token-based function-like macro" - // - 'macro_rules' (by example/pattern-match) macro? or not? "an - // AST-based function-like macro" - // - else is unreachable - // - attribute syntax macro (inner switch) - // - procedural macro attribute syntax - "A token-based attribute - // macro" - // - legacy macro attribute syntax? - "an AST-based attribute macro" - // - non-macro attribute: mark known - // - else is unreachable - // - derive macro (inner switch) - // - derive or legacy derive - "token-based" vs "AST-based" - // - else is unreachable - // - derive container macro - unreachable - - // lookup the rules for this macro - NodeId resolved_node = UNKNOWN_NODEID; - NodeId source_node = UNKNOWN_NODEID; - if (has_semicolon) - source_node = invoc.get_macro_node_id (); - else - source_node = invoc.get_node_id (); - auto seg - = CanonicalPath::new_seg (source_node, invoc_data.get_path ().as_string ()); - - bool found = resolver.get_macro_scope ().lookup (seg, &resolved_node); - if (!found) - { - rust_error_at (invoc.get_locus (), ErrorCode::E0433, - "could not resolve macro invocation %qs", - seg.get ().c_str ()); - return; - } - - // lookup the rules - auto rules_def = mappings.lookup_macro_def (resolved_node); - - auto &outer_attrs = rules_def.value ()->get_outer_attrs (); - bool is_builtin - = std::any_of (outer_attrs.begin (), outer_attrs.end (), - [] (AST::Attribute attr) { - return attr.get_path () - == Values::Attributes::RUSTC_BUILTIN_MACRO; - }); - - if (is_builtin) - { - auto builtin_kind = builtin_macro_from_string ( - rules_def.value ()->get_rule_name ().as_string ()); - invoc.map_to_builtin (builtin_kind.value ()); - } - - auto attributes = rules_def.value ()->get_outer_attrs (); - - /* Since the EarlyNameResolver runs multiple time (fixed point algorithm) - * we could be inserting the same macro def over and over again until we - * implement some optimizations */ - // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead - if (mappings.lookup_macro_invocation (invoc)) - return; - - mappings.insert_macro_invocation (invoc, *rules_def); -} - -// FIXME: ARTHUR: Do we need to resolve these as well here? - -void -EarlyNameResolver::visit (AST::MetaItemPath &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemSeq &) -{} - -void -EarlyNameResolver::visit (AST::MetaNameValueStr &) -{} - -void -EarlyNameResolver::visit (AST::MetaListPaths &) -{} - -void -EarlyNameResolver::visit (AST::MetaListNameValueStr &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundLiteral &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundPath &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundQualPath &) -{} - -void -EarlyNameResolver::visit (AST::StructPatternFieldIdent &) -{} - -void -EarlyNameResolver::visit (AST::StructPattern &) -{} - -void -EarlyNameResolver::visit (AST::TupleStructPattern &pattern) -{ - pattern.get_items ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TupleType &) -{} - -void -EarlyNameResolver::visit (AST::RawPointerType &) -{} - -void -EarlyNameResolver::visit (AST::ReferenceType &) -{} - -void -EarlyNameResolver::visit (AST::ArrayType &) -{} - -void -EarlyNameResolver::visit (AST::SliceType &) -{} - -void -EarlyNameResolver::visit (AST::InferredType &) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h deleted file mode 100644 index 26fc84d..0000000 --- a/gcc/rust/resolve/rust-early-name-resolver.h +++ /dev/null @@ -1,196 +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_EARLY_NAME_RESOLVER_H -#define RUST_EARLY_NAME_RESOLVER_H - -#include "rust-name-resolver.h" -#include "rust-system.h" -#include "rust-ast.h" -#include "rust-ast-visitor.h" - -namespace Rust { -namespace Resolver { - -class EarlyNameResolver : public AST::DefaultASTVisitor -{ -public: - EarlyNameResolver (); - - void go (AST::Crate &crate); - -private: - using AST::DefaultASTVisitor::visit; - - /** - * Execute a lambda within a scope. This is equivalent to calling - * `enter_scope` before your code and `exit_scope` after. This ensures - * no errors can be committed - */ - void scoped (NodeId scope_id, std::function<void ()> fn) - { - auto old_scope = current_scope; - current_scope = scope_id; - resolver.get_macro_scope ().push (scope_id); - resolver.push_new_macro_rib (resolver.get_macro_scope ().peek ()); - - fn (); - - resolver.get_macro_scope ().pop (); - current_scope = old_scope; - } - - /** - * Accumulate all of the nested macros which escape their module through the - * use of the #[macro_use] attribute. - * - * This function recursively accumulates macros in all of the nested modules - * of an item container (an AST::Crate or an AST::Module) and returns this new - * list of items. You can then use the `take_items` and `set_items` functions - * on these containers to replace their list of items. - */ - std::vector<std::unique_ptr<AST::Item>> - accumulate_escaped_macros (AST::Module &module); - - /** - * The "scope" we are currently in. - * - * This involves lexical scopes: - * - * ```rust - * // current_scope = crate_id; - * macro_rules! foo { () => {} ) - * - * { - * // current_scope = current_block_id; - * macro_rules! foo { () => { something!(); } } - * } - * // current_scope = crate_id; - * ``` - * - * as well as any sort of scope-like structure that might impact import name - * resolution or macro name resolution: - * - * ```rust - * macro_rules! foo { - * () => { fn empty() {} } - * } - * - * - * trait Foo { - * fn foo() { - * fn inner_foo() { - * macro_rules! foo { () => {} ) - * - * foo!(); - * } - * - * foo!(); - * } - * - * foo!(); - * } - * - * foo!(); - * ``` - */ - NodeId current_scope; - - /* The crate's scope */ - NodeId crate_scope; - - Resolver &resolver; - Analysis::Mappings &mappings; - - /** - * Early name-resolve generic args, which can be macro invocations - */ - void resolve_generic_args (AST::GenericArgs &generic_args); - - /** - * Early name-resolve a qualified path type, which can contain macro - * invocations - */ - void resolve_qualified_path_type (AST::QualifiedPathType &path); - - virtual void visit (AST::Crate &crate); - virtual void visit (AST::DelimTokenTree &delim_tok_tree); - virtual void visit (AST::AttrInputMetaItemContainer &input); - virtual void visit (AST::IdentifierExpr &ident_expr); - virtual void visit (AST::LifetimeParam &lifetime_param); - virtual void visit (AST::ConstGenericParam &const_param); - virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::QualifiedPathInExpression &path); - virtual void visit (AST::QualifiedPathInType &path); - virtual void visit (AST::LiteralExpr &expr); - virtual void visit (AST::AttrInputLiteral &attr_input); - virtual void visit (AST::AttrInputMacro &attr_input); - virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathLit &meta_item); - virtual void visit (AST::StructExprStruct &expr); - virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::Module &module); - virtual void visit (AST::ExternCrate &crate); - virtual void visit (AST::UseTreeGlob &use_tree); - virtual void visit (AST::UseTreeList &use_tree); - virtual void visit (AST::UseTreeRebind &use_tree); - virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::EnumItem &item); - virtual void visit (AST::Union &union_item); - virtual void visit (AST::TraitItemType &item); - virtual void visit (AST::Trait &trait); - virtual void visit (AST::InherentImpl &impl); - virtual void visit (AST::TraitImpl &impl); - virtual void visit (AST::ExternalTypeItem &item); - virtual void visit (AST::ExternBlock &block); - virtual void visit (AST::MacroMatchRepetition &match); - virtual void visit (AST::MacroMatcher &matcher); - virtual void visit (AST::MacroRulesDefinition &rules_def); - virtual void visit (AST::MacroInvocation ¯o_invoc); - virtual void visit (AST::MetaItemPath &meta_item); - virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaNameValueStr &meta_item); - virtual void visit (AST::MetaListPaths &meta_item); - virtual void visit (AST::MetaListNameValueStr &meta_item); - virtual void visit (AST::RangePatternBoundLiteral &bound); - virtual void visit (AST::RangePatternBoundPath &bound); - virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::StructPatternFieldIdent &field); - virtual void visit (AST::StructPattern &pattern); - virtual void visit (AST::TupleStructPattern &pattern); - virtual void visit (AST::TupleType &type); - virtual void visit (AST::RawPointerType &type); - virtual void visit (AST::ReferenceType &type); - virtual void visit (AST::ArrayType &type); - virtual void visit (AST::SliceType &type); - virtual void visit (AST::InferredType &type); -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_EARLY_NAME_RESOLVER_H diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc index b0e8651..317acb0 100644 --- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc @@ -21,19 +21,44 @@ #include "rust-hir-map.h" #include "rust-name-resolution-context.h" #include "rust-rib.h" +#include "rust-system.h" #include "rust-toplevel-name-resolver-2.0.h" namespace Rust { namespace Resolver2_0 { void -GlobbingVisitor::go (AST::Module *module) +GlobbingVisitor::go (AST::Item *container) { - for (auto &i : module->get_items ()) + switch (container->get_item_kind ()) + { + case AST::Item::Kind::Module: + visit_module_container (static_cast<AST::Module &> (*container)); + break; + case AST::Item::Kind::Enum: + visit_enum_container (static_cast<AST::Enum &> (*container)); + break; + default: + rust_unreachable (); + } +} + +void +GlobbingVisitor::visit_module_container (AST::Module &module) +{ + for (auto &i : module.get_items ()) visit (i); } void +GlobbingVisitor::visit_enum_container (AST::Enum &item) +{ + for (auto &variant : item.get_variants ()) + ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (), + Namespace::Types); +} + +void GlobbingVisitor::visit (AST::Module &module) { if (module.get_visibility ().is_public ()) diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.h b/gcc/rust/resolve/rust-finalize-imports-2.0.h index d587a5e..4ae1d6d 100644 --- a/gcc/rust/resolve/rust-finalize-imports-2.0.h +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.h @@ -18,6 +18,7 @@ #include "rust-ast.h" #include "rust-expr.h" +#include "rust-item.h" #include "rust-name-resolution-context.h" #include "rust-toplevel-name-resolver-2.0.h" #include "rust-early-name-resolver-2.0.h" @@ -32,7 +33,11 @@ class GlobbingVisitor : public AST::DefaultASTVisitor public: GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {} - void go (AST::Module *module); + void go (AST::Item *container); + + void visit_module_container (AST::Module &module); + void visit_enum_container (AST::Enum &item); + void visit (AST::Module &module) override; void visit (AST::MacroRulesDefinition ¯o) override; void visit (AST::Function &function) override; diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index f390e38..75dd873 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -543,12 +543,20 @@ private: Node root; }; +enum class ResolutionMode +{ + Normal, + FromRoot, + FromExtern, // extern prelude +}; + template <Namespace N> class ForeverStack { public: ForeverStack () : root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)), lang_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID, root)), + extern_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID)), cursor_reference (root) { rust_assert (root.is_root ()); @@ -671,11 +679,9 @@ public: */ template <typename S> tl::optional<Rib::Definition> resolve_path ( - const std::vector<S> &segments, - std::function<void (const S &, NodeId)> insert_segment_resolution); - - // FIXME: Documentation - tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const; + const std::vector<S> &segments, ResolutionMode mode, + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors); // FIXME: Documentation tl::optional<Rib &> to_rib (NodeId rib_id); @@ -737,6 +743,9 @@ private: tl::optional<Node &> parent; // `None` only if the node is a root }; + // private overload which allows specifying a starting point + tl::optional<Rib::Definition> get (Node &start, const Identifier &name); + /* Should we keep going upon seeing a Rib? */ enum class KeepGoing { @@ -768,6 +777,10 @@ private: * resolution */ Node lang_prelude; + /* + * The extern prelude, used for resolving external crates + */ + Node extern_prelude; std::reference_wrapper<Node> cursor_reference; @@ -787,13 +800,15 @@ private: tl::optional<SegIterator<S>> find_starting_point ( const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point, - std::function<void (const S &, NodeId)> insert_segment_resolution); + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors); template <typename S> tl::optional<Node &> resolve_segments ( Node &starting_point, const std::vector<S> &segments, SegIterator<S> iterator, - std::function<void (const S &, NodeId)> insert_segment_resolution); + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors); tl::optional<Rib::Definition> resolve_final_segment (Node &final_node, std::string &seg_name, @@ -823,6 +838,21 @@ private: tl::optional<Node &> dfs_node (Node &starting_point, NodeId to_find); tl::optional<const Node &> dfs_node (const Node &starting_point, NodeId to_find) const; + +public: + bool forward_declared (NodeId definition, NodeId usage) + { + if (peek ().kind != Rib::Kind::ForwardTypeParamBan) + return false; + + const auto &definition_rib = dfs_rib (cursor (), definition); + + if (!definition_rib) + return false; + + return (definition_rib + && definition_rib.value ().kind == Rib::Kind::ForwardTypeParamBan); + } }; } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 885f282..848f5e6 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -20,6 +20,7 @@ #include "rust-ast.h" #include "rust-diagnostics.h" #include "rust-forever-stack.h" +#include "rust-edition.h" #include "rust-rib.h" #include "rust-unwrap-segment.h" #include "optional.h" @@ -290,12 +291,16 @@ ForeverStack<N>::update_cursor (Node &new_cursor) template <Namespace N> tl::optional<Rib::Definition> -ForeverStack<N>::get (const Identifier &name) +ForeverStack<N>::get (Node &start, const Identifier &name) { tl::optional<Rib::Definition> resolved_definition = tl::nullopt; // TODO: Can we improve the API? have `reverse_iter` return an optional? - reverse_iter ([&resolved_definition, &name] (Node ¤t) { + reverse_iter (start, [&resolved_definition, &name] (Node ¤t) { + // we can't reference associated types/functions like this + if (current.rib.kind == Rib::Kind::TraitOrImpl) + return KeepGoing::Yes; + auto candidate = current.rib.get (name.as_string ()); return candidate.map_or ( @@ -319,6 +324,13 @@ ForeverStack<N>::get (const Identifier &name) template <Namespace N> tl::optional<Rib::Definition> +ForeverStack<N>::get (const Identifier &name) +{ + return get (cursor (), name); +} + +template <Namespace N> +tl::optional<Rib::Definition> ForeverStack<N>::get_lang_prelude (const Identifier &name) { return lang_prelude.rib.get (name.as_string ()); @@ -397,12 +409,13 @@ ForeverStack<N>::find_closest_module (Node &starting_point) * segments */ template <typename S> static inline bool -check_leading_kw_at_start (const S &segment, bool condition) +check_leading_kw_at_start (std::vector<Error> &collect_errors, const S &segment, + bool condition) { if (condition) - rust_error_at ( + collect_errors.emplace_back ( segment.get_locus (), ErrorCode::E0433, - "leading path segment %qs can only be used at the beginning of a path", + "%qs in paths can only be used in start position", segment.as_string ().c_str ()); return condition; @@ -418,7 +431,8 @@ template <typename S> tl::optional<typename std::vector<S>::const_iterator> ForeverStack<N>::find_starting_point ( const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point, - std::function<void (const S &, NodeId)> insert_segment_resolution) + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors) { auto iterator = segments.begin (); @@ -435,8 +449,9 @@ ForeverStack<N>::find_starting_point ( // if we're after the first path segment and meet `self` or `crate`, it's // an error - we should only be seeing `super` keywords at this point - if (check_leading_kw_at_start (seg, !is_start (iterator, segments) - && is_self_or_crate)) + if (check_leading_kw_at_start (collect_errors, seg, + !is_start (iterator, segments) + && is_self_or_crate)) return tl::nullopt; if (seg.is_crate_path_seg ()) @@ -459,8 +474,9 @@ ForeverStack<N>::find_starting_point ( starting_point = find_closest_module (starting_point); if (starting_point.get ().is_root ()) { - rust_error_at (seg.get_locus (), ErrorCode::E0433, - "too many leading %<super%> keywords"); + collect_errors.emplace_back ( + seg.get_locus (), ErrorCode::E0433, + "too many leading %<super%> keywords"); return tl::nullopt; } @@ -486,7 +502,8 @@ tl::optional<typename ForeverStack<N>::Node &> ForeverStack<N>::resolve_segments ( Node &starting_point, const std::vector<S> &segments, typename std::vector<S>::const_iterator iterator, - std::function<void (const S &, NodeId)> insert_segment_resolution) + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors) { Node *current_node = &starting_point; for (; !is_last (iterator, segments); iterator++) @@ -508,12 +525,13 @@ ForeverStack<N>::resolve_segments ( rust_debug ("[ARTHUR]: resolving segment part: %s", str.c_str ()); // check that we don't encounter *any* leading keywords afterwards - if (check_leading_kw_at_start (seg, seg.is_crate_path_seg () - || seg.is_super_path_seg () - || seg.is_lower_self_seg ())) + if (check_leading_kw_at_start (collect_errors, seg, + seg.is_crate_path_seg () + || seg.is_super_path_seg () + || seg.is_lower_self_seg ())) return tl::nullopt; - tl::optional<typename ForeverStack<N>::Node &> child = tl::nullopt; + tl::optional<std::reference_wrapper<Node>> child = tl::nullopt; /* * On every iteration this loop either @@ -535,6 +553,14 @@ ForeverStack<N>::resolve_segments ( bool searched_prelude = false; while (true) { + if (is_start (iterator, segments) + && current_node->rib.kind == Rib::Kind::TraitOrImpl) + { + // we can't reference associated types/functions like this + current_node = ¤t_node->parent.value (); + continue; + } + // may set the value of child for (auto &kv : current_node->children) { @@ -557,10 +583,17 @@ ForeverStack<N>::resolve_segments ( break; } - if (N == Namespace::Types) + auto rib_lookup = current_node->rib.get (seg.as_string ()); + if (rib_lookup && !rib_lookup->is_ambiguous ()) { - auto rib_lookup = current_node->rib.get (seg.as_string ()); - if (rib_lookup && !rib_lookup->is_ambiguous ()) + if (Analysis::Mappings::get () + .lookup_glob_container (rib_lookup->get_node_id ()) + .has_value ()) + { + child = dfs_node (root, rib_lookup->get_node_id ()).value (); + break; + } + else { insert_segment_resolution (outer_seg, rib_lookup->get_node_id ()); @@ -585,9 +618,9 @@ ForeverStack<N>::resolve_segments ( current_node = ¤t_node->parent.value (); } - // if child didn't contain a value - // the while loop above should have return'd or kept looping - current_node = &child.value (); + // if child didn't point to a value + // the while loop above would have returned or kept looping + current_node = &child->get (); insert_segment_resolution (outer_seg, current_node->id); } @@ -618,48 +651,118 @@ template <Namespace N> template <typename S> tl::optional<Rib::Definition> ForeverStack<N>::resolve_path ( - const std::vector<S> &segments, - std::function<void (const S &, NodeId)> insert_segment_resolution) + const std::vector<S> &segments, ResolutionMode mode, + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors) { - // TODO: What to do if segments.empty() ? + rust_assert (!segments.empty ()); + + std::reference_wrapper<Node> starting_point = cursor (); + switch (mode) + { + case ResolutionMode::Normal: + break; // default + case ResolutionMode::FromRoot: + starting_point = root; + break; + case ResolutionMode::FromExtern: + starting_point = extern_prelude; + break; + default: + rust_unreachable (); + } // if there's only one segment, we just use `get` if (segments.size () == 1) { - auto &seg = segments.front (); - if (auto lang_item = unwrap_segment_get_lang_item (seg)) + auto &outer_seg = segments.front (); + if (auto lang_item = unwrap_segment_get_lang_item (outer_seg)) { NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node ( lang_item.value ()); - insert_segment_resolution (seg, seg_id); + insert_segment_resolution (outer_seg, seg_id); // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (seg_id); } + auto &seg = unwrap_type_segment (outer_seg); + tl::optional<Rib::Definition> res - = get (unwrap_type_segment (segments.back ()).as_string ()); + = get (starting_point.get (), seg.as_string ()); if (!res) - res = get_lang_prelude ( - unwrap_type_segment (segments.back ()).as_string ()); + res = get_lang_prelude (seg.as_string ()); + + if (N == Namespace::Types && !res) + { + if (seg.is_crate_path_seg ()) + { + insert_segment_resolution (outer_seg, root.id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (root.id); + } + else if (seg.is_lower_self_seg ()) + { + NodeId id = find_closest_module (starting_point.get ()).id; + insert_segment_resolution (outer_seg, id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (id); + } + else if (seg.is_super_path_seg ()) + { + Node &closest_module + = find_closest_module (starting_point.get ()); + if (closest_module.is_root ()) + { + rust_error_at (seg.get_locus (), ErrorCode::E0433, + "too many leading %<super%> keywords"); + return tl::nullopt; + } + + NodeId id + = find_closest_module (closest_module.parent.value ()).id; + insert_segment_resolution (outer_seg, id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (id); + } + else + { + // HACK: check for a module after we check the language prelude + for (auto &kv : + find_closest_module (starting_point.get ()).children) + { + auto &link = kv.first; + + if (link.path.map_or ( + [&seg] (Identifier path) { + auto &path_str = path.as_string (); + return path_str == seg.as_string (); + }, + false)) + { + insert_segment_resolution (outer_seg, kv.second.id); + return Rib::Definition::NonShadowable (kv.second.id); + } + } + } + } if (res && !res->is_ambiguous ()) - insert_segment_resolution (segments.back (), res->get_node_id ()); + insert_segment_resolution (outer_seg, res->get_node_id ()); return res; } - std::reference_wrapper<Node> starting_point = cursor (); - return find_starting_point (segments, starting_point, - insert_segment_resolution) - .and_then ([this, &segments, &starting_point, &insert_segment_resolution] ( - typename std::vector<S>::const_iterator iterator) { - return resolve_segments (starting_point.get (), segments, iterator, - insert_segment_resolution); - }) + insert_segment_resolution, collect_errors) + .and_then ( + [this, &segments, &starting_point, &insert_segment_resolution, + &collect_errors] (typename std::vector<S>::const_iterator iterator) { + return resolve_segments (starting_point.get (), segments, iterator, + insert_segment_resolution, collect_errors); + }) .and_then ([this, &segments, &insert_segment_resolution] ( - Node final_node) -> tl::optional<Rib::Definition> { + Node &final_node) -> tl::optional<Rib::Definition> { // leave resolution within impl blocks to type checker if (final_node.rib.kind == Rib::Kind::TraitOrImpl) return tl::nullopt; @@ -675,6 +778,26 @@ ForeverStack<N>::resolve_path ( if (!res) res = get_lang_prelude (seg_name); + if (N == Namespace::Types && !res) + { + // HACK: check for a module after we check the language prelude + for (auto &kv : final_node.children) + { + auto &link = kv.first; + + if (link.path.map_or ( + [&seg_name] (Identifier path) { + auto &path_str = path.as_string (); + return path_str == seg_name; + }, + false)) + { + insert_segment_resolution (segments.back (), kv.second.id); + return Rib::Definition::NonShadowable (kv.second.id); + } + } + } + if (res && !res->is_ambiguous ()) insert_segment_resolution (segments.back (), res->get_node_id ()); @@ -744,67 +867,6 @@ ForeverStack<N>::dfs (const ForeverStack<N>::Node &starting_point, } template <Namespace N> -tl::optional<Resolver::CanonicalPath> -ForeverStack<N>::to_canonical_path (NodeId id) const -{ - // find the id in the current forever stack, starting from the root, - // performing either a BFS or DFS once the Node containing the ID is found, go - // back up to the root (parent().parent().parent()...) accumulate link - // segments reverse them that's your canonical path - - return dfs (root, id).map ([this, id] (ConstDfsResult tuple) { - auto containing_node = tuple.first; - auto name = tuple.second; - - auto segments = std::vector<Resolver::CanonicalPath> (); - - reverse_iter (containing_node, [&segments] (const Node ¤t) { - if (current.is_root ()) - return KeepGoing::No; - - auto children = current.parent.value ().children; - const Link *outer_link = nullptr; - - for (auto &kv : children) - { - auto &link = kv.first; - auto &child = kv.second; - - if (current.id == child.id) - { - outer_link = &link; - break; - } - } - - rust_assert (outer_link); - - outer_link->path.map ([&segments, outer_link] (Identifier path) { - segments.emplace (segments.begin (), - Resolver::CanonicalPath::new_seg (outer_link->id, - path.as_string ())); - }); - - return KeepGoing::Yes; - }); - - auto &mappings = Analysis::Mappings::get (); - CrateNum crate_num = mappings.lookup_crate_num (root.id).value (); - auto path = Resolver::CanonicalPath::new_seg ( - root.id, mappings.get_crate_name (crate_num).value ()); - path.set_crate_num (crate_num); - - for (const auto &segment : segments) - path = path.append (segment); - - // Finally, append the name - path = path.append (Resolver::CanonicalPath::new_seg (id, name)); - - return path; - }); -} - -template <Namespace N> tl::optional<Rib &> ForeverStack<N>::dfs_rib (ForeverStack<N>::Node &starting_point, NodeId to_find) { diff --git a/gcc/rust/resolve/rust-ice-finalizer.cc b/gcc/rust/resolve/rust-ice-finalizer.cc index bd4763f..79a06c3 100644 --- a/gcc/rust/resolve/rust-ice-finalizer.cc +++ b/gcc/rust/resolve/rust-ice-finalizer.cc @@ -22,12 +22,12 @@ namespace Rust { namespace Resolver { void ATTRIBUTE_NORETURN -funny_ice_text_finalizer (diagnostic_text_output_format &text_output, - const diagnostic_info *diagnostic, - diagnostic_t diag_kind) +funny_ice_text_finalizer (diagnostics::text_sink &text_output, + const diagnostics::diagnostic_info *diagnostic, + enum diagnostics::kind diag_kind) { - gcc_assert (diag_kind == DK_ICE_NOBT); - default_diagnostic_text_finalizer (text_output, diagnostic, diag_kind); + gcc_assert (diag_kind == diagnostics::kind::ice_nobt); + diagnostics::default_text_finalizer (text_output, diagnostic, diag_kind); fnotice (stderr, "You have broken GCC Rust. This is a feature.\n"); exit (ICE_EXIT_CODE); } diff --git a/gcc/rust/resolve/rust-ice-finalizer.h b/gcc/rust/resolve/rust-ice-finalizer.h index 85ab88f..5120176 100644 --- a/gcc/rust/resolve/rust-ice-finalizer.h +++ b/gcc/rust/resolve/rust-ice-finalizer.h @@ -55,9 +55,9 @@ namespace Resolver { the default bug reporting instructions, as there is no bug to report. */ void ATTRIBUTE_NORETURN -funny_ice_text_finalizer (diagnostic_text_output_format &text_output, - const diagnostic_info *diagnostic, - diagnostic_t diag_kind); +funny_ice_text_finalizer (diagnostics::text_sink &text_output, + const diagnostics::diagnostic_info *diagnostic, + enum diagnostics::kind diag_kind); } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 7d32374..96b38f4 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -19,10 +19,12 @@ #include "optional.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" +#include "rust-expr.h" #include "rust-hir-map.h" #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" #include "rust-name-resolution-context.h" +#include "rust-resolve-builtins.h" #include "rust-path.h" #include "rust-system.h" #include "rust-tyty.h" @@ -33,99 +35,71 @@ namespace Rust { namespace Resolver2_0 { -Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {} +Late::Late (NameResolutionContext &ctx) + : DefaultResolver (ctx), funny_error (false), block_big_self (false) +{} -static NodeId -next_node_id () +void +Late::go (AST::Crate &crate) { - return Analysis::Mappings::get ().get_next_node_id (); -}; + Builtins::setup_type_ctx (); + + visit (crate); +} -static HirId -next_hir_id () +void +Late::new_label (Identifier name, NodeId id) { - return Analysis::Mappings::get ().get_next_hir_id (); -}; + // labels can always shadow, so `insert` should never fail. if it does, we're + // in big trouble! + auto ok = ctx.labels.insert (name, id); + + rust_assert (ok); +} void -Late::setup_builtin_types () -{ - // access the global type context to setup the TyTys - auto &ty_ctx = *Resolver::TypeCheckContext::get (); - - // Late builtin type struct helper - struct LType - { - std::string name; - NodeId node_id; - NodeId hir_id; - TyTy::BaseType *type; - - explicit LType (std::string name, TyTy::BaseType *type) - : name (name), node_id (next_node_id ()), hir_id (type->get_ref ()), - type (type) - {} - }; - - static const LType builtins[] = { - {LType ("bool", new TyTy::BoolType (next_hir_id ()))}, - {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))}, - {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))}, - {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))}, - {LType ("u64", new TyTy::UintType (next_hir_id (), TyTy::UintType::U64))}, - {LType ("u128", new TyTy::UintType (next_hir_id (), TyTy::UintType::U128))}, - {LType ("i8", new TyTy::IntType (next_hir_id (), TyTy::IntType::I8))}, - {LType ("i16", new TyTy::IntType (next_hir_id (), TyTy::IntType::I16))}, - {LType ("i32", new TyTy::IntType (next_hir_id (), TyTy::IntType::I32))}, - {LType ("i64", new TyTy::IntType (next_hir_id (), TyTy::IntType::I64))}, - {LType ("i128", new TyTy::IntType (next_hir_id (), TyTy::IntType::I128))}, - {LType ("f32", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F32))}, - {LType ("f64", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F64))}, - {LType ("usize", new TyTy::USizeType (next_hir_id ()))}, - {LType ("isize", new TyTy::ISizeType (next_hir_id ()))}, - {LType ("char", new TyTy::CharType (next_hir_id ()))}, - {LType ("str", new TyTy::StrType (next_hir_id ()))}, - {LType ("!", new TyTy::NeverType (next_hir_id ()))}, - - // the unit type `()` does not play a part in name-resolution - so we only - // insert it in the type context... - }; - - // There's a special Rib for putting prelude items, since prelude items need - // to satisfy certain special rules. - ctx.scoped (Rib::Kind::Prelude, 0, [this, &ty_ctx] (void) -> void { - for (const auto &builtin : builtins) - { - auto ok = ctx.types.insert (builtin.name, builtin.node_id); - rust_assert (ok); - - ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id); - ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type); - } - }); - - // ...here! - auto *unit_type = TyTy::TupleType::get_unit_type (); - ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type); +Late::visit (AST::ForLoopExpr &expr) +{ + visit_outer_attrs (expr); + + ctx.bindings.enter (BindingSource::For); + + visit (expr.get_pattern ()); + + ctx.bindings.exit (); + + visit (expr.get_iterator_expr ()); + + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + + visit (expr.get_loop_block ()); } void -Late::go (AST::Crate &crate) +Late::visit_if_let_patterns (AST::IfLetExpr &expr) { - setup_builtin_types (); + ctx.bindings.enter (BindingSource::IfLet); - for (auto &item : crate.items) - item->accept_vis (*this); + DefaultResolver::visit_if_let_patterns (expr); + + ctx.bindings.exit (); } void -Late::new_label (Identifier name, NodeId id) +Late::visit (AST::MatchArm &arm) { - // labels can always shadow, so `insert` should never fail. if it does, we're - // in big trouble! - auto ok = ctx.labels.insert (name, id); + visit_outer_attrs (arm); - rust_assert (ok); + ctx.bindings.enter (BindingSource::Match); + + for (auto &pattern : arm.get_patterns ()) + visit (pattern); + + ctx.bindings.exit (); + + if (arm.has_match_arm_guard ()) + visit (arm.get_guard_expr ()); } void @@ -138,8 +112,13 @@ Late::visit (AST::LetStmt &let) // this makes variable shadowing work properly if (let.has_init_expr ()) visit (let.get_init_expr ()); + + ctx.bindings.enter (BindingSource::Let); + visit (let.get_pattern ()); + ctx.bindings.exit (); + if (let.has_else_expr ()) visit (let.get_init_expr ()); @@ -161,15 +140,109 @@ Late::visit (AST::LetStmt &let) } void -Late::visit (AST::IdentifierPattern &identifier) +Late::visit (AST::WhileLetLoopExpr &while_let) +{ + DefaultASTVisitor::visit_outer_attrs (while_let); + + if (while_let.has_loop_label ()) + visit (while_let.get_loop_label ()); + + // visit expression before pattern + // this makes variable shadowing work properly + visit (while_let.get_scrutinee_expr ()); + + ctx.bindings.enter (BindingSource::WhileLet); + + for (auto &pattern : while_let.get_patterns ()) + visit (pattern); + + ctx.bindings.exit (); + + visit (while_let.get_loop_block ()); +} + +static void +visit_identifier_as_pattern (NameResolutionContext &ctx, + const Identifier &ident, location_t locus, + NodeId node_id, bool is_ref, bool is_mut) { // do we insert in labels or in values // but values does not allow shadowing... since functions cannot shadow // do we insert functions in labels as well? - // We do want to ignore duplicated data because some situations rely on it. - std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), - identifier.get_node_id ()); + if (ctx.bindings.peek ().is_and_bound (ident)) + { + if (ctx.bindings.peek ().get_source () == BindingSource::Param) + rust_error_at ( + locus, ErrorCode::E0415, + "identifier %qs is bound more than once in the same parameter list", + ident.as_string ().c_str ()); + else + rust_error_at ( + locus, ErrorCode::E0416, + "identifier %qs is bound more than once in the same pattern", + ident.as_string ().c_str ()); + return; + } + + ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut); + + if (ctx.bindings.peek ().is_or_bound (ident)) + { + auto res = ctx.values.get (ident); + rust_assert (res.has_value () && !res->is_ambiguous ()); + ctx.map_usage (Usage (node_id), Definition (res->get_node_id ())); + } + else + { + // We do want to ignore duplicated data because some situations rely on + // it. + std::ignore = ctx.values.insert_shadowable (ident, node_id); + } +} + +void +Late::visit (AST::IdentifierPattern &identifier) +{ + DefaultResolver::visit (identifier); + + visit_identifier_as_pattern (ctx, identifier.get_ident (), + identifier.get_locus (), + identifier.get_node_id (), + identifier.get_is_ref (), + identifier.get_is_mut ()); +} + +void +Late::visit (AST::AltPattern &pattern) +{ + ctx.bindings.peek ().push (Binding::Kind::Or); + for (auto &alt : pattern.get_alts ()) + { + ctx.bindings.peek ().push (Binding::Kind::Product); + visit (alt); + ctx.bindings.peek ().merge (); + } + ctx.bindings.peek ().merge (); +} + +void +Late::visit_function_params (AST::Function &function) +{ + ctx.bindings.enter (BindingSource::Param); + + for (auto ¶m : function.get_function_params ()) + visit (param); + + ctx.bindings.exit (); +} + +void +Late::visit (AST::StructPatternFieldIdent &field) +{ + visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (), + field.get_node_id (), field.is_ref (), + field.is_mut ()); } void @@ -187,6 +260,9 @@ Late::visit (AST::SelfParam ¶m) void Late::visit (AST::BreakExpr &expr) { + if (expr.has_label ()) + resolve_label (expr.get_label_unchecked ().get_lifetime ()); + if (expr.has_break_expr ()) { auto &break_expr = expr.get_break_expr (); @@ -213,6 +289,38 @@ Late::visit (AST::BreakExpr &expr) } void +Late::visit (AST::LoopLabel &label) +{ + auto &lifetime = label.get_lifetime (); + ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()), + lifetime.get_node_id ()); +} + +void +Late::resolve_label (AST::Lifetime &lifetime) +{ + if (auto resolved = ctx.labels.get (lifetime.as_string ())) + { + if (resolved->get_node_id () != lifetime.get_node_id ()) + ctx.map_usage (Usage (lifetime.get_node_id ()), + Definition (resolved->get_node_id ())); + } + else + rust_error_at (lifetime.get_locus (), ErrorCode::E0426, + "use of undeclared label %qs", + lifetime.as_string ().c_str ()); +} + +void +Late::visit (AST::ContinueExpr &expr) +{ + if (expr.has_label ()) + resolve_label (expr.get_label_unchecked ()); + + DefaultResolver::visit (expr); +} + +void Late::visit (AST::IdentifierExpr &expr) { // TODO: same thing as visit(PathInExpression) here? @@ -228,8 +336,9 @@ Late::visit (AST::IdentifierExpr &expr) } else if (funny_error) { - diagnostic_text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer; - emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1, + diagnostics::text_finalizer (global_dc) + = Resolver::funny_ice_text_finalizer; + emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1, "are you trying to break %s? how dare you?", expr.as_string ().c_str ()); } @@ -307,14 +416,13 @@ Late::visit (AST::PathInExpression &expr) return; } - auto resolved = ctx.resolve_path (expr.get_segments (), Namespace::Values, - Namespace::Types); + auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types); if (!resolved) { if (!ctx.lookup (expr.get_segments ().front ().get_node_id ())) - rust_error_at (expr.get_locus (), - "could not resolve path expression: %qs", + rust_error_at (expr.get_locus (), ErrorCode::E0433, + "Cannot find path %qs in this scope", expr.as_simple_path ().as_string ().c_str ()); return; } @@ -331,43 +439,134 @@ Late::visit (AST::PathInExpression &expr) } void -Late::visit (AST::TypePath &type) +Late::visit_impl_type (AST::Type &type) +{ + // TODO: does this have to handle reentrancy? + rust_assert (!block_big_self); + block_big_self = true; + visit (type); + block_big_self = false; +} + +template <typename P> +static void +resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self, + P &type) { // should we add type path resolution in `ForeverStack` directly? Since it's // quite more complicated. // maybe we can overload `resolve_path<Namespace::Types>` to only do // typepath-like path resolution? that sounds good - DefaultResolver::visit (type); - - // take care of only simple cases - // TODO: remove this? - rust_assert (!type.has_opening_scope_resolution_op ()); + // prevent "impl Self {}" and similar + if (type.get_segments ().size () == 1 + && !unwrap_segment_get_lang_item (type.get_segments ().front ()) + .has_value () + && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg () + && block_big_self) + { + rust_error_at (type.get_locus (), + "%<Self%> is not valid in the self type of an impl block"); + return; + } // this *should* mostly work // TODO: make sure typepath-like path resolution (?) is working - auto resolved = ctx.resolve_path (type.get_segments (), Namespace::Types); + auto resolved = ctx.resolve_path (type, Namespace::Types); if (!resolved.has_value ()) { - if (!ctx.lookup (type.get_segments ().front ()->get_node_id ())) - rust_error_at (type.get_locus (), "could not resolve type path %qs", - type.as_string ().c_str ()); + if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ()))) + rust_error_at (type.get_locus (), ErrorCode::E0412, + "could not resolve type path %qs", + unwrap_segment_error_string (type).c_str ()); return; } if (resolved->is_ambiguous ()) { rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous", - type.as_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } + if (ctx.types.forward_declared (resolved->get_node_id (), + type.get_node_id ())) + { + rust_error_at (type.get_locus (), ErrorCode::E0128, + "type parameters with a default cannot use forward " + "declared identifiers"); + } + ctx.map_usage (Usage (type.get_node_id ()), Definition (resolved->get_node_id ())); } void +Late::visit (AST::TypePath &type) +{ + DefaultResolver::visit (type); + + resolve_type_path_like (ctx, block_big_self, type); +} + +void +Late::visit (AST::Visibility &vis) +{ + if (!vis.has_path ()) + return; + + AST::SimplePath &path = vis.get_path (); + + rust_assert (path.get_segments ().size ()); + auto &first_seg = path.get_segments ()[0]; + + auto mode = ResolutionMode::Normal; + + if (path.has_opening_scope_resolution ()) + { + if (get_rust_edition () == Edition::E2015) + mode = ResolutionMode::FromRoot; + else + mode = ResolutionMode::FromExtern; + } + else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg () + && !first_seg.is_lower_self_seg ()) + { + if (get_rust_edition () == Edition::E2015) + { + mode = ResolutionMode::FromRoot; + } + else + { + rust_error_at (path.get_locus (), + "relative paths are not supported in visibilities in " + "2018 edition or later"); + return; + } + } + + auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types); + + if (!res.has_value ()) + { + rust_error_at (path.get_locus (), ErrorCode::E0433, + "could not resolve path %qs", path.as_string ().c_str ()); + return; + } + + // TODO: is this possible? + if (res->is_ambiguous ()) + { + rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous", + path.as_string ().c_str ()); + return; + } + + ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ())); +} + +void Late::visit (AST::Trait &trait) { // kind of weird how this is done @@ -381,24 +580,13 @@ Late::visit (AST::Trait &trait) } void -Late::visit (AST::StructStruct &s) -{ - auto s_vis = [this, &s] () { AST::DefaultASTVisitor::visit (s); }; - ctx.scoped (Rib::Kind::Item, s.get_node_id (), s_vis); -} - -void Late::visit (AST::StructExprStruct &s) { visit_outer_attrs (s); visit_inner_attrs (s); DefaultResolver::visit (s.get_struct_name ()); - auto resolved - = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } void @@ -409,11 +597,7 @@ Late::visit (AST::StructExprStructBase &s) DefaultResolver::visit (s.get_struct_name ()); visit (s.get_struct_base ()); - auto resolved - = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } void @@ -427,11 +611,7 @@ Late::visit (AST::StructExprStructFields &s) for (auto &field : s.get_fields ()) visit (field); - auto resolved - = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } // needed because Late::visit (AST::GenericArg &) is non-virtual @@ -466,30 +646,27 @@ Late::visit (AST::GenericArg &arg) DefaultResolver::visit (arg); } -template <class Closure> -static void -add_captures (Closure &closure, NameResolutionContext &ctx) -{ - auto vals = ctx.values.peek ().get_values (); - for (auto &val : vals) - { - ctx.mappings.add_capture (closure.get_node_id (), - val.second.get_node_id ()); - } -} - void -Late::visit (AST::ClosureExprInner &closure) +Late::visit_closure_params (AST::ClosureExpr &closure) { - add_captures (closure, ctx); - DefaultResolver::visit (closure); + ctx.bindings.enter (BindingSource::Param); + + DefaultResolver::visit_closure_params (closure); + + ctx.bindings.exit (); } void -Late::visit (AST::ClosureExprInnerTyped &closure) +Late::visit (AST::ClosureExpr &expr) { - add_captures (closure, ctx); - DefaultResolver::visit (closure); + // add captures + auto vals = ctx.values.peek ().get_values (); + for (auto &val : vals) + { + ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ()); + } + + DefaultResolver::visit (expr); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index ac376b5..608ae38 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -37,34 +37,48 @@ public: void new_label (Identifier name, NodeId id); + // Specialized visit bits + void visit_function_params (AST::Function &function) override; + // some more label declarations void visit (AST::LetStmt &) override; + void visit (AST::WhileLetLoopExpr &) override; // TODO: Do we need this? // void visit (AST::Method &) override; void visit (AST::IdentifierPattern &) override; + void visit (AST::StructPatternFieldIdent &) override; + void visit (AST::AltPattern &) override; void visit (AST::SelfParam &) override; + void visit (AST::MatchArm &) override; + void visit (AST::ForLoopExpr &) override; + void visit_if_let_patterns (AST::IfLetExpr &) override; // resolutions void visit (AST::IdentifierExpr &) override; void visit (AST::StructExprFieldIdentifier &) override; void visit (AST::BreakExpr &) override; + void visit (AST::ContinueExpr &) override; + void visit (AST::LoopLabel &) override; void visit (AST::PathInExpression &) override; + void visit_impl_type (AST::Type &) override; void visit (AST::TypePath &) override; + void visit (AST::Visibility &) override; void visit (AST::Trait &) override; void visit (AST::StructExprStruct &) override; void visit (AST::StructExprStructBase &) override; void visit (AST::StructExprStructFields &) override; - void visit (AST::StructStruct &) override; void visit (AST::GenericArgs &) override; void visit (AST::GenericArg &); - void visit (AST::ClosureExprInner &) override; - void visit (AST::ClosureExprInnerTyped &) override; + void visit_closure_params (AST::ClosureExpr &) override; + void visit (AST::ClosureExpr &) override; private: - /* Setup Rust's builtin types (u8, i32, !...) in the resolver */ - void setup_builtin_types (); + void resolve_label (AST::Lifetime &lifetime); bool funny_error; + + /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */ + bool block_big_self; }; // TODO: Add missing mappings and data structures diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index 92c4863..1b84f1d 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -23,8 +23,169 @@ namespace Rust { namespace Resolver2_0 { +BindingLayer::BindingLayer (BindingSource source) : source (source) +{ + push (Binding::Kind::Product); +} + +bool +BindingLayer::bind_test (Identifier ident, Binding::Kind kind) +{ + for (auto &bind : bindings) + { + if (bind.idents.find (ident.as_string ()) != bind.idents.cend () + && bind.kind == kind) + { + return true; + } + } + return false; +} + +void +BindingLayer::push (Binding::Kind kind) +{ + bindings.push_back (Binding (kind)); +} + +bool +BindingLayer::is_and_bound (Identifier ident) +{ + return bind_test (ident, Binding::Kind::Product); +} + +bool +BindingLayer::is_or_bound (Identifier ident) +{ + return bind_test (ident, Binding::Kind::Or); +} + +void +BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref, + bool is_mut) +{ + bindings.back ().idents.emplace ( + std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut))); +} + +void +BindingLayer::merge () +{ + auto last_binding = std::move (bindings.back ()); + bindings.pop_back (); + + if (bindings.back ().has_expected_bindings) + { + for (auto &value : bindings.back ().idents) + { + auto ident = value.first; + if (last_binding.idents.find (ident) == last_binding.idents.end ()) + { + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0408, + "variable %qs is not bound in all patterns", + ident.c_str ()); + } + } + } + + for (auto &value : last_binding.idents) + { + auto res = bindings.back ().idents.emplace (value); + if (res.second) + { + if (bindings.back ().has_expected_bindings) + { + auto &ident = value.first; + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0408, + "variable %qs is not bound in all patterns", + ident.c_str ()); + } + } + else + { + auto this_mode = value.second.second; + auto other_mode = res.first->second.second; + if (this_mode != other_mode) + { + auto &ident = value.first; + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0409, + "variable %qs is bound inconsistently across " + "pattern alternatives", + ident.c_str ()); + } + } + } + + if (bindings.back ().kind == Binding::Kind::Or) + bindings.back ().has_expected_bindings = true; +} + +BindingSource +BindingLayer::get_source () const +{ + return source; +} + +Resolver::CanonicalPath +CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &) +{ + auto ret = Resolver::CanonicalPath::new_seg (node_id, seg); + ret.set_crate_num (crate_num); + return ret; +} + +Resolver::CanonicalPath +CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg)); +} + +Resolver::CanonicalPath +CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx) +{ + if (!cache) + { + auto res = ctx.lookup (lookup_id).and_then ( + [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); }); + + if (!res) + { + // HACK: use a dummy value + // this should bring us roughly to parity with nr1.0 + // since nr1.0 doesn't seem to handle canonical paths for generics + // quite right anyways + return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX"); + } + + cache = res.value (); + } + return cache->as_path (ctx); +} + +Resolver::CanonicalPath +CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append ( + Resolver::CanonicalPath::inherent_impl_seg (impl_id, + type_record.as_path (ctx))); +} + +Resolver::CanonicalPath +CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append ( + Resolver::CanonicalPath::trait_impl_projection_seg ( + impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx))); +} + NameResolutionContext::NameResolutionContext () - : mappings (Analysis::Mappings::get ()) + : mappings (Analysis::Mappings::get ()), canonical_ctx (*this) {} tl::expected<NodeId, DuplicateNameError> diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index ea81bde..558b3ca 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -23,6 +23,8 @@ #include "rust-forever-stack.h" #include "rust-hir-map.h" #include "rust-rib.h" +#include "rust-stacked-contexts.h" +#include "rust-item.h" namespace Rust { namespace Resolver2_0 { @@ -156,6 +158,326 @@ public: NodeId id; }; +struct IdentifierMode +{ + bool is_ref; + bool is_mut; + + IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut) + {} + + bool operator== (const IdentifierMode &other) + { + return other.is_ref == is_ref && other.is_mut == is_mut; + } + + bool operator!= (const IdentifierMode &other) { return !(*this == other); } +}; + +struct Binding +{ + enum class Kind + { + Product, + Or, + } kind; + + // used to check the correctness of or-bindings + bool has_expected_bindings; + + std::unordered_map<std::string, std::pair<location_t, IdentifierMode>> idents; + + Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {} +}; + +/** + * Used to identify the source of a binding, and emit the correct error message. + */ +enum class BindingSource +{ + Match, + Let, + IfLet, + WhileLet, + For, + /* Closure param or function param */ + Param +}; + +class BindingLayer +{ + BindingSource source; + std::vector<Binding> bindings; + + bool bind_test (Identifier ident, Binding::Kind kind); + +public: + void push (Binding::Kind kind); + + BindingLayer (BindingSource source); + + /** + * Identifies if the identifier has been used in a product binding context. + * eg. `let (a, a) = test();` + */ + bool is_and_bound (Identifier ident); + + /** + * Identifies if the identifier has been used in a or context. + * eg. `let (a, 1) | (a, 2) = test()` + */ + bool is_or_bound (Identifier ident); + + void insert_ident (std::string ident, location_t locus, bool is_ref, + bool is_mut); + + void merge (); + + BindingSource get_source () const; +}; + +class NameResolutionContext; +/* + * Used to handle canonical paths + * Similar to ForeverStack, but namespace independent and more specialized + */ +class CanonicalPathRecord +{ +public: + virtual Resolver::CanonicalPath as_path (const NameResolutionContext &) = 0; + + virtual bool is_root () const = 0; + + virtual ~CanonicalPathRecord () = default; +}; + +class CanonicalPathRecordWithParent : public CanonicalPathRecord +{ +public: + CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent (&parent) + {} + + CanonicalPathRecord &get_parent () { return *parent; } + + bool is_root () const override final { return false; } + +private: + CanonicalPathRecord *parent; +}; + +class CanonicalPathRecordCrateRoot : public CanonicalPathRecord +{ +public: + CanonicalPathRecordCrateRoot (NodeId node_id, std::string seg) + : node_id (node_id), seg (std::move (seg)) + { + rust_assert (Analysis::Mappings::get ().node_is_crate (node_id)); + crate_num = Analysis::Mappings::get ().lookup_crate_num (node_id).value (); + } + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + + bool is_root () const override final { return true; } + +private: + NodeId node_id; + CrateNum crate_num; + std::string seg; +}; + +class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id, + std::string seg) + : CanonicalPathRecordWithParent (parent), node_id (node_id), + seg (std::move (seg)) + { + rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id)); + } + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId node_id; + std::string seg; +}; + +class CanonicalPathRecordLookup : public CanonicalPathRecord +{ +public: + CanonicalPathRecordLookup (NodeId lookup_id) + : lookup_id (lookup_id), cache (nullptr) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + + bool is_root () const override final { return true; } + +private: + NodeId lookup_id; + CanonicalPathRecord *cache; +}; + +class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id, + NodeId type_id) + : CanonicalPathRecordWithParent (parent), impl_id (impl_id), + type_record (type_id) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId impl_id; + CanonicalPathRecordLookup type_record; +}; + +class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id, + NodeId type_id, NodeId trait_path_id) + : CanonicalPathRecordWithParent (parent), impl_id (impl_id), + type_record (type_id), trait_path_record (trait_path_id) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId impl_id; + CanonicalPathRecordLookup type_record; + CanonicalPathRecordLookup trait_path_record; +}; + +class CanonicalPathCtx +{ +public: + CanonicalPathCtx (const NameResolutionContext &ctx) + : current_record (nullptr), nr_ctx (&ctx) + {} + + Resolver::CanonicalPath get_path (NodeId id) const + { + return get_record (id).as_path (*nr_ctx); + } + + CanonicalPathRecord &get_record (NodeId id) const + { + auto it = records.find (id); + rust_assert (it != records.end ()); + return *it->second; + } + + tl::optional<CanonicalPathRecord *> get_record_opt (NodeId id) const + { + auto it = records.find (id); + if (it == records.end ()) + return tl::nullopt; + else + return it->second.get (); + } + + void insert_record (NodeId id, const Identifier &ident) + { + insert_record (id, ident.as_string ()); + } + + void insert_record (NodeId id, std::string seg) + { + rust_assert (current_record != nullptr); + + auto it = records.find (id); + if (it == records.end ()) + { + auto record = new CanonicalPathRecordNormal (*current_record, id, + std::move (seg)); + bool ok + = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record)) + .second; + rust_assert (ok); + } + } + + template <typename F> void scope (NodeId id, const Identifier &ident, F &&f) + { + scope (id, ident.as_string (), std::forward<F> (f)); + } + + template <typename F> void scope (NodeId id, std::string seg, F &&f) + { + rust_assert (current_record != nullptr); + + scope_inner (id, std::forward<F> (f), [this, id, &seg] () { + return new CanonicalPathRecordNormal (*current_record, id, + std::move (seg)); + }); + } + + template <typename F> void scope_impl (AST::InherentImpl &impl, F &&f) + { + rust_assert (current_record != nullptr); + + NodeId id = impl.get_node_id (); + scope_inner (id, std::forward<F> (f), [this, id, &impl] () { + return new CanonicalPathRecordImpl (*current_record, id, + impl.get_type ().get_node_id ()); + }); + } + + template <typename F> void scope_impl (AST::TraitImpl &impl, F &&f) + { + rust_assert (current_record != nullptr); + + NodeId id = impl.get_node_id (); + scope_inner (id, std::forward<F> (f), [this, id, &impl] () { + return new CanonicalPathRecordTraitImpl ( + *current_record, id, impl.get_type ().get_node_id (), + impl.get_trait_path ().get_node_id ()); + }); + } + + template <typename F> + void scope_crate (NodeId node_id, std::string crate_name, F &&f) + { + scope_inner (node_id, std::forward<F> (f), [node_id, &crate_name] () { + return new CanonicalPathRecordCrateRoot (node_id, std::move (crate_name)); + }); + } + +private: + template <typename FCreate, typename FCallback> + void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create) + { + auto it = records.find (id); + if (it == records.end ()) + { + CanonicalPathRecord *record = std::forward<FCreate> (f_create) (); + it = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record)) + .first; + } + + rust_assert (it->second->is_root () + || &static_cast<CanonicalPathRecordWithParent &> (*it->second) + .get_parent () + == current_record); + + CanonicalPathRecord *stash = it->second.get (); + std::swap (stash, current_record); + + std::forward<FCallback> (f_callback) (); + + std::swap (stash, current_record); + } + + std::unordered_map<NodeId, std::unique_ptr<CanonicalPathRecord>> records; + CanonicalPathRecord *current_record; + + const NameResolutionContext *nr_ctx; +}; + // Now our resolver, which keeps track of all the `ForeverStack`s we could want class NameResolutionContext { @@ -212,6 +534,9 @@ public: ForeverStack<Namespace::Labels> labels; Analysis::Mappings &mappings; + StackedContexts<BindingLayer> bindings; + + CanonicalPathCtx canonical_ctx; // TODO: Rename // TODO: Use newtype pattern for Usage and Definition @@ -219,9 +544,15 @@ public: tl::optional<NodeId> lookup (NodeId usage) const; + Resolver::CanonicalPath to_canonical_path (NodeId id) const + { + return canonical_ctx.get_path (id); + } + template <typename S> - tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments, - Namespace ns) + tl::optional<Rib::Definition> + resolve_path (const std::vector<S> &segments, ResolutionMode mode, + std::vector<Error> &collect_errors, Namespace ns) { std::function<void (const S &, NodeId)> insert_segment_resolution = [this] (const S &seg, NodeId id) { @@ -232,33 +563,119 @@ public: switch (ns) { case Namespace::Values: - return values.resolve_path (segments, insert_segment_resolution); + return values.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Types: - return types.resolve_path (segments, insert_segment_resolution); + return types.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Macros: - return macros.resolve_path (segments, insert_segment_resolution); + return macros.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Labels: - return labels.resolve_path (segments, insert_segment_resolution); + return labels.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); default: rust_unreachable (); } } template <typename S, typename... Args> - tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments, - Args... ns_args) + tl::optional<Rib::Definition> + resolve_path (const std::vector<S> &segments, ResolutionMode mode, + tl::optional<std::vector<Error> &> collect_errors, + Namespace ns_first, Args... ns_args) { - std::initializer_list<Namespace> namespaces = {ns_args...}; + std::initializer_list<Namespace> namespaces = {ns_first, ns_args...}; for (auto ns : namespaces) { - if (auto ret = resolve_path (segments, ns)) + std::vector<Error> collect_errors_inner; + if (auto ret = resolve_path (segments, mode, collect_errors_inner, ns)) return ret; + if (!collect_errors_inner.empty ()) + { + if (collect_errors.has_value ()) + { + std::move (collect_errors_inner.begin (), + collect_errors_inner.end (), + std::back_inserter (collect_errors.value ())); + } + else + { + for (auto &e : collect_errors_inner) + e.emit (); + } + return tl::nullopt; + } } return tl::nullopt; } + template <typename S, typename... Args> + tl::optional<Rib::Definition> + resolve_path (const std::vector<S> &path_segments, + bool has_opening_scope_resolution, + tl::optional<std::vector<Error> &> collect_errors, + Namespace ns_first, Args... ns_args) + { + auto mode = ResolutionMode::Normal; + if (has_opening_scope_resolution) + { + if (get_rust_edition () == Edition::E2015) + mode = ResolutionMode::FromRoot; + else + mode = ResolutionMode::FromExtern; + } + return resolve_path (path_segments, mode, collect_errors, ns_first, + ns_args...); + } + + template <typename S, typename... Args> + tl::optional<Rib::Definition> + resolve_path (const std::vector<S> &path_segments, + bool has_opening_scope_resolution, Namespace ns_first, + Args... ns_args) + { + return resolve_path (path_segments, has_opening_scope_resolution, + tl::nullopt, ns_first, ns_args...); + } + + template <typename S, typename... Args> + tl::optional<Rib::Definition> + resolve_path (const std::vector<S> &path_segments, ResolutionMode mode, + Namespace ns_first, Args... ns_args) + { + return resolve_path (path_segments, mode, tl::nullopt, ns_first, + ns_args...); + } + + template <typename... Args> + tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path, + Args &&...args) + { + return resolve_path (path.get_segments (), + path.has_opening_scope_resolution (), + std::forward<Args> (args)...); + } + + template <typename... Args> + tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression &path, + Args &&...args) + { + return resolve_path (path.get_segments (), path.opening_scope_resolution (), + std::forward<Args> (args)...); + } + + template <typename... Args> + tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path, + Args &&...args) + { + return resolve_path (path.get_segments (), + path.has_opening_scope_resolution_op (), + std::forward<Args> (args)...); + } + private: /* Map of "usage" nodes which have been resolved to a "definition" node */ std::map<Usage, Definition> resolved_nodes; diff --git a/gcc/rust/resolve/rust-resolve-builtins.cc b/gcc/rust/resolve/rust-resolve-builtins.cc new file mode 100644 index 0000000..b16db9a --- /dev/null +++ b/gcc/rust/resolve/rust-resolve-builtins.cc @@ -0,0 +1,125 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-resolve-builtins.h" +#include "rust-name-resolution-context.h" +#include "rust-tyty.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver2_0 { +namespace Builtins { + +// Use X-macros + +#define TYPE_UINT(n, enum_ident) TYPE1 (n, UintType, UintType::enum_ident) +#define TYPE_INT(n, enum_ident) TYPE1 (n, IntType, IntType::enum_ident) + +#define BUILTIN_TYPES \ + TYPE0 ("bool", BoolType) \ + TYPE_UINT ("u8", U8) \ + TYPE_UINT ("u16", U16) \ + TYPE_UINT ("u32", U32) \ + TYPE_UINT ("u64", U64) \ + TYPE_UINT ("u128", U128) \ + TYPE_INT ("i8", I8) \ + TYPE_INT ("i16", I16) \ + TYPE_INT ("i32", I32) \ + TYPE_INT ("i64", I64) \ + TYPE_INT ("i128", I128) \ + TYPE1 ("f32", FloatType, FloatType::F32) \ + TYPE1 ("f64", FloatType, FloatType::F64) \ + TYPE0 ("usize", USizeType) \ + TYPE0 ("isize", ISizeType) \ + TYPE0 ("char", CharType) \ + TYPE0 ("str", StrType) \ + TYPE0 ("!", NeverType) + +// Define constants using X macros + +#define TYPE0(...) 1 + +#define TYPE1(...) 1 + +static constexpr size_t builtin_count = BUILTIN_TYPES 0; +#undef TYPE0 +#undef TYPE1 + +#define TYPE0(n, ...) n, +#define TYPE1(n, ...) n, +static constexpr const char *builtin_names[] = {BUILTIN_TYPES}; +#undef TYPE0 +#undef TYPE1 + +static NodeId builtin_node_ids[builtin_count]; + +void +setup_lang_prelude (NameResolutionContext &ctx) +{ + auto &mappings = Analysis::Mappings::get (); + + // insert into prelude rib + ctx.scoped (Rib::Kind::Prelude, 0, [&mappings, &ctx] (void) -> void { + for (size_t i = 0; i < builtin_count; i++) + { + NodeId node_id = mappings.get_next_node_id (); + rust_assert (ctx.types.insert (Identifier (builtin_names[i]), node_id)); + builtin_node_ids[i] = node_id; + } + }); +} + +void +setup_type_ctx () +{ + auto &mappings = Analysis::Mappings::get (); + auto &ty_ctx = *Resolver::TypeCheckContext::get (); + + HirId hir_ids[builtin_count]; + for (size_t i = 0; i < builtin_count; i++) + hir_ids[i] = mappings.get_next_hir_id (); + + TyTy::BaseType *types[builtin_count]; + { + size_t i = 0; +#define TYPE_BASE(stub) \ + types[i] = new TyTy::stub; \ + i++; +#define TYPE0(n, ty) TYPE_BASE (ty (hir_ids[i])) +#define TYPE1(n, ty, p1) TYPE_BASE (ty (hir_ids[i], TyTy::p1)) + BUILTIN_TYPES +#undef TYPE_BASE +#undef TYPE0 +#undef TYPE1 + } + + for (size_t i = 0; i < builtin_count; i++) + { + NodeId node_id = builtin_node_ids[i]; + HirId hir_id = hir_ids[i]; + mappings.insert_node_to_hir (node_id, hir_id); + ty_ctx.insert_builtin (hir_id, node_id, types[i]); + } + + // handle unit type separately + auto *unit_type = TyTy::TupleType::get_unit_type (); + ty_ctx.insert_builtin (unit_type->get_ref (), mappings.get_next_node_id (), + unit_type); +} + +} // namespace Builtins +} // namespace Resolver2_0 +} // namespace Rust diff --git a/gcc/rust/resolve/rust-resolve-builtins.h b/gcc/rust/resolve/rust-resolve-builtins.h new file mode 100644 index 0000000..e7e1bd2 --- /dev/null +++ b/gcc/rust/resolve/rust-resolve-builtins.h @@ -0,0 +1,37 @@ +// 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/>. + +#ifndef RUST_RESOLVE_BUILTINS_H +#define RUST_RESOLVE_BUILTINS_H + +namespace Rust { +namespace Resolver2_0 { + +// forward declare +class NameResolutionContext; + +namespace Builtins { + +void setup_lang_prelude (NameResolutionContext &ctx); +void setup_type_ctx (); + +} // namespace Builtins +} // namespace Resolver2_0 +} // namespace Rust + +#endif // RUST_RESOLVE_BUILTINS_H diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h index c498328..140c991 100644 --- a/gcc/rust/resolve/rust-rib.h +++ b/gcc/rust/resolve/rust-rib.h @@ -188,6 +188,8 @@ public: * restriction that you cannot `use` items from the Prelude */ Prelude, + /* Generic rib, used to store generics */ + Generics, } kind; static std::string kind_to_string (Rib::Kind kind) @@ -214,9 +216,13 @@ public: return "Forward type param ban"; case Rib::Kind::ConstParamType: return "Const Param Type"; - default: - rust_unreachable (); + case Kind::Prelude: + return "Prelude"; + case Kind::Generics: + return "Generics"; } + + rust_unreachable (); } Rib (Kind kind); diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 8863be7..0930f96 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -95,70 +95,32 @@ TopLevel::go (AST::Crate &crate) // times in a row in a fixed-point fashion, so it would make the code // responsible for this ugly and perfom a lot of error checking. - for (auto &item : crate.items) - item->accept_vis (*this); + visit (crate); } void TopLevel::visit (AST::Module &module) { - insert_or_error_out (module.get_name (), module, Namespace::Types); - - // Parse the module's items if they haven't been expanded and the file - // should be parsed (i.e isn't hidden behind an untrue or impossible cfg - // directive - // TODO: make sure this is right - // TODO: avoid loading items if cfg attributes are present? - // might not be needed if this runs after early resolution? - // This was copied from the old early resolver method - // 'accumulate_escaped_macros' - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - DefaultResolver::visit (module); - if (Analysis::Mappings::get ().lookup_ast_module (module.get_node_id ()) + if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ()) == tl::nullopt) - Analysis::Mappings::get ().insert_ast_module (&module); + Analysis::Mappings::get ().insert_glob_container (&module); } void TopLevel::visit (AST::Trait &trait) { - insert_or_error_out (trait.get_identifier ().as_string (), trait, - Namespace::Types); + insert_or_error_out (trait.get_identifier (), trait, Namespace::Types); DefaultResolver::visit (trait); } void -TopLevel::visit (AST::InherentImpl &impl) -{ - auto inner_fn = [this, &impl] () { - insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), - impl.get_type (), Namespace::Types); - - // We do want to visit with the default visitor instead of default resolver - // because we don't want to insert the scope twice. - AST::DefaultASTVisitor::visit (impl); - }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); -} - -void -TopLevel::visit (AST::TraitImpl &impl) +TopLevel::maybe_insert_big_self (AST::Impl &impl) { - auto inner_fn = [this, &impl] () { - insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), - impl.get_type (), Namespace::Types); - - // We do want to visit using the default visitor instead of default resolver - // because we don't want to insert the scope twice. - AST::DefaultASTVisitor::visit (impl); - }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), + impl.get_type (), Namespace::Types); } void @@ -188,19 +150,10 @@ insert_macros (std::vector<PROC_MACRO> ¯os, NameResolutionContext &ctx) } void -TopLevel::visit (AST::ExternCrate &crate) +TopLevel::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate, + CrateNum num) { auto &mappings = Analysis::Mappings::get (); - auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); - - if (!num_opt) - { - rust_error_at (crate.get_locus (), "unknown crate %qs", - crate.get_referenced_crate ().c_str ()); - return; - } - - CrateNum num = *num_opt; auto attribute_macros = mappings.lookup_attribute_proc_macros (num); @@ -208,34 +161,27 @@ TopLevel::visit (AST::ExternCrate &crate) auto derive_macros = mappings.lookup_derive_proc_macros (num); - auto sub_visitor = [&] () { - // TODO: Find a way to keep this part clean without the double dispatch. - if (derive_macros.has_value ()) - { - insert_macros (derive_macros.value (), ctx); - for (auto ¯o : derive_macros.value ()) - mappings.insert_derive_proc_macro_def (macro); - } - if (attribute_macros.has_value ()) - { - insert_macros (attribute_macros.value (), ctx); - for (auto ¯o : attribute_macros.value ()) - mappings.insert_attribute_proc_macro_def (macro); - } - if (bang_macros.has_value ()) - { - insert_macros (bang_macros.value (), ctx); - for (auto ¯o : bang_macros.value ()) - mappings.insert_bang_proc_macro_def (macro); - } - }; + // TODO: Find a way to keep this part clean without the double dispatch. + if (derive_macros.has_value ()) + { + insert_macros (derive_macros.value (), ctx); + for (auto ¯o : derive_macros.value ()) + mappings.insert_derive_proc_macro_def (macro); + } + if (attribute_macros.has_value ()) + { + insert_macros (attribute_macros.value (), ctx); + for (auto ¯o : attribute_macros.value ()) + mappings.insert_attribute_proc_macro_def (macro); + } + if (bang_macros.has_value ()) + { + insert_macros (bang_macros.value (), ctx); + for (auto ¯o : bang_macros.value ()) + mappings.insert_bang_proc_macro_def (macro); + } - if (crate.has_as_clause ()) - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor, - crate.get_as_clause ()); - else - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor, - crate.get_referenced_crate ()); + visit (crate); } static bool @@ -312,14 +258,7 @@ TopLevel::visit (AST::ExternalStaticItem &static_item) void TopLevel::visit (AST::StructStruct &struct_item) { - auto generic_vis = [this, &struct_item] () { - for (auto &g : struct_item.get_generic_params ()) - { - g->accept_vis (*this); - } - }; - - ctx.scoped (Rib::Kind::Item, struct_item.get_node_id (), generic_vis); + DefaultResolver::visit (struct_item); insert_or_error_out (struct_item.get_struct_name (), struct_item, Namespace::Types); @@ -365,24 +304,32 @@ void TopLevel::visit (AST::EnumItem &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemTuple &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemStruct &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemDiscriminant &variant) { insert_or_error_out (variant.get_identifier (), variant, Namespace::Types); + + DefaultResolver::visit (variant); } void @@ -392,6 +339,13 @@ TopLevel::visit (AST::Enum &enum_item) Namespace::Types); DefaultResolver::visit (enum_item); + + // Since enums can be containers for imports, we need to insert them like we + // do for modules + if (Analysis::Mappings::get ().lookup_glob_container ( + enum_item.get_node_id ()) + == tl::nullopt) + Analysis::Mappings::get ().insert_glob_container (&enum_item); } void @@ -421,21 +375,18 @@ TopLevel::visit (AST::TypeAlias &type_item) DefaultResolver::visit (type_item); } -static void -flatten_rebind ( +static void flatten_rebind ( const AST::UseTreeRebind &glob, std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths); -static void -flatten_list ( +static void flatten_list ( const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths, std::vector<AST::SimplePath> &glob_paths, std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths, NameResolutionContext &ctx); -static void -flatten_glob (const AST::UseTreeGlob &glob, - std::vector<AST::SimplePath> &glob_paths, - NameResolutionContext &ctx); +static void flatten_glob (const AST::UseTreeGlob &glob, + std::vector<AST::SimplePath> &glob_paths, + NameResolutionContext &ctx); static void flatten ( @@ -446,17 +397,20 @@ flatten ( { switch (tree->get_kind ()) { - case AST::UseTree::Rebind: { + case AST::UseTree::Rebind: + { auto rebind = static_cast<const AST::UseTreeRebind *> (tree); flatten_rebind (*rebind, rebind_paths); break; } - case AST::UseTree::List: { + case AST::UseTree::List: + { auto list = static_cast<const AST::UseTreeList *> (tree); flatten_list (*list, paths, glob_paths, rebind_paths, ctx); break; } - case AST::UseTree::Glob: { + case AST::UseTree::Glob: + { auto glob = static_cast<const AST::UseTreeGlob *> (tree); flatten_glob (*glob, glob_paths, ctx); break; @@ -538,6 +492,8 @@ flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths, { if (glob.has_path ()) paths.emplace_back (glob.get_path ()); + else + paths.emplace_back (AST::SimplePath ({}, false, glob.get_locus ())); } void diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h index 3ff37ed..8d3da92 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -160,8 +160,7 @@ private: void visit (AST::Module &module) override; void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl) override; - void visit (AST::TraitImpl &impl) override; + void maybe_insert_big_self (AST::Impl &impl) override; void visit (AST::TraitItemType &trait_item) override; void visit (AST::MacroRulesDefinition ¯o) override; void visit (AST::Function &function) override; @@ -177,7 +176,7 @@ private: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::TypeAlias &type_item) override; - void visit (AST::ExternCrate &crate) override; + void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) override; void visit (AST::TypeParam &type_param) override; void visit (AST::ConstGenericParam &const_param) override; diff --git a/gcc/rust/rust-attribs.cc b/gcc/rust/rust-attribs.cc index 74cb2af..a98c1fa 100644 --- a/gcc/rust/rust-attribs.cc +++ b/gcc/rust/rust-attribs.cc @@ -38,35 +38,27 @@ along with GCC; see the file COPYING3. If not see * future. */ -extern const attribute_spec grs_langhook_common_attribute_table[]; +extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table; +extern const struct scoped_attribute_specs grs_langhook_common_attribute_table; /* Internal attribute handlers for built-in functions. */ -static tree -handle_noreturn_attribute (tree *, tree, tree, int, bool *); -static tree -handle_leaf_attribute (tree *, tree, tree, int, bool *); -static tree -handle_const_attribute (tree *, tree, tree, int, bool *); -static tree -handle_malloc_attribute (tree *, tree, tree, int, bool *); -static tree -handle_pure_attribute (tree *, tree, tree, int, bool *); -static tree -handle_novops_attribute (tree *, tree, tree, int, bool *); -static tree -handle_nonnull_attribute (tree *, tree, tree, int, bool *); -static tree -handle_nothrow_attribute (tree *, tree, tree, int, bool *); -static tree -handle_type_generic_attribute (tree *, tree, tree, int, bool *); -static tree -handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); -static tree -handle_returns_twice_attribute (tree *, tree, tree, int, bool *); -static tree -handle_fnspec_attribute (tree *, tree, tree, int, bool *); -static tree -handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); +static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); +static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); +static tree handle_const_attribute (tree *, tree, tree, int, bool *); +static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); +static tree handle_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_novops_attribute (tree *, tree, tree, int, bool *); +static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); +static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); +static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); +static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); +static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); +static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); + +/* Rust attribute handlers for user defined attributes. */ +static tree handle_cold_attribute (tree *, tree, tree, int, bool *); +static tree handle_hot_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -74,6 +66,10 @@ handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); name, function, type, variable \ } +// clang-format off +// Disabling clang-format because it insists in having several ATTR_EXCL() on a +// single line. + static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = { // ATTR_EXCL ("alloc_size", true, true, true), ATTR_EXCL ("const", true, true, true), @@ -89,11 +85,22 @@ static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] ATTR_EXCL (NULL, false, false, false), }; +extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] = { + + ATTR_EXCL ("cold", true, true, true), + ATTR_EXCL ("hot", true, true, true), + ATTR_EXCL (NULL, false, false, false) +}; + static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = { // ATTR_EXCL ("alloc_size", true, true, true), ATTR_EXCL ("const", true, true, true), ATTR_EXCL ("noreturn", true, true, true), - ATTR_EXCL ("pure", true, true, true), ATTR_EXCL (NULL, false, false, false)}; + ATTR_EXCL ("pure", true, true, true), + ATTR_EXCL (NULL, false, false, false) +}; + +// clang-format on /* Helper to define an attribute. */ #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \ @@ -105,7 +112,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = { /* Table of machine-independent attributes. For internal use (marking of built-ins) only. */ -const attribute_spec grs_langhook_common_attribute_table[] = { +static const attribute_spec grs_langhook_common_attributes[] = { ATTR_SPEC ("noreturn", 0, 0, true, false, false, false, handle_noreturn_attribute, attr_noreturn_exclusions), ATTR_SPEC ("leaf", 0, 0, true, false, false, false, handle_leaf_attribute, @@ -132,9 +139,21 @@ const attribute_spec grs_langhook_common_attribute_table[] = { NULL), ATTR_SPEC ("omp declare simd", 0, -1, true, false, false, false, handle_omp_declare_simd_attribute, NULL), - ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL), }; +const scoped_attribute_specs grs_langhook_common_attribute_table + = {"gnu", {grs_langhook_common_attributes}}; + +static const attribute_spec grs_langhook_gnu_attributes[] = { + ATTR_SPEC ("cold", 0, 0, true, false, false, false, handle_cold_attribute, + attr_cold_hot_exclusions), + ATTR_SPEC ("hot", 0, 0, true, false, false, false, handle_hot_attribute, + attr_cold_hot_exclusions), +}; + +const scoped_attribute_specs grs_langhook_gnu_attribute_table + = {"gnu", {grs_langhook_gnu_attributes}}; + /* Built-in attribute handlers. These functions take the arguments: (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ @@ -204,7 +223,7 @@ handle_const_attribute (tree *node, tree, tree, int, bool *) /* Handle a "malloc" attribute; arguments as in struct attribute_spec.handler. */ -tree +static tree handle_malloc_attribute (tree *node, tree, tree, int, bool *) { gcc_assert (TREE_CODE (*node) == FUNCTION_DECL @@ -217,9 +236,14 @@ handle_malloc_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_pure_attribute (tree *node, tree, tree, int, bool *) +handle_pure_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + DECL_PURE_P (*node) = 1; return NULL_TREE; } @@ -228,9 +252,14 @@ handle_pure_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_novops_attribute (tree *node, tree, tree, int, bool *) +handle_novops_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + DECL_IS_NOVOPS (*node) = 1; return NULL_TREE; } @@ -301,9 +330,14 @@ handle_nonnull_attribute (tree *node, tree, tree args, int, bool *) struct attribute_spec.handler. */ static tree -handle_nothrow_attribute (tree *node, tree, tree, int, bool *) +handle_nothrow_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + TREE_NOTHROW (*node) = 1; return NULL_TREE; } @@ -339,9 +373,14 @@ handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_returns_twice_attribute (tree *node, tree, tree, int, bool *) +handle_returns_twice_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } DECL_IS_RETURNS_TWICE (*node) = 1; @@ -351,7 +390,7 @@ handle_returns_twice_attribute (tree *node, tree, tree, int, bool *) /* Handle a "fn spec" attribute; arguments as in struct attribute_spec.handler. */ -tree +static tree handle_fnspec_attribute (tree *, tree, tree args, int, bool *) { gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST @@ -362,9 +401,46 @@ handle_fnspec_attribute (tree *, tree, tree args, int, bool *) /* Handle an "omp declare simd" attribute; arguments as in struct attribute_spec.handler. */ -tree -handle_omp_declare_simd_attribute (tree *node, tree, tree, int, bool *) +static tree +handle_omp_declare_simd_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Language specific attribute handlers. + These functions take the arguments: + (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ + +/* Handle a "cold" and attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_cold_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +static tree +handle_hot_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + return NULL_TREE; } diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 414799e..99496e6 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -27,6 +27,8 @@ #include "rust-linemap.h" #include "rust-diagnostics.h" #include "util/rust-operators.h" +#include "util/rust-ggc.h" +#include "util/optional.h" #include "tree.h" #include "rust-gcc.h" @@ -42,69 +44,60 @@ class Bvariable; namespace Backend { -void -init (); +namespace GGC { + +using Rust::GGC::Ident; + +} // namespace GGC + +void init (); // Name/type/location. Used for function parameters, struct fields, // interface methods. struct typed_identifier { - std::string name; + GGC::Ident name; tree type; location_t location; - typed_identifier () : name (), type (NULL_TREE), location (UNKNOWN_LOCATION) - {} - - typed_identifier (const std::string &a_name, tree a_type, - location_t a_location) + typed_identifier (GGC::Ident a_name, tree a_type, location_t a_location) : name (a_name), type (a_type), location (a_location) {} }; // debug void debug (tree); -void -debug (Bvariable *); +void debug (Bvariable *); -tree -get_identifier_node (const std::string &str); +tree get_identifier_node (const std::string &str); // Types. // Get the wchar type -tree -wchar_type (); +tree wchar_type (); // Get the Host pointer size in bits -int -get_pointer_size (); +int get_pointer_size (); // Get the raw str type const char* -tree -raw_str_type (); +tree raw_str_type (); // Get an unnamed integer type with the given signedness and number // of bits. -tree -integer_type (bool is_unsigned, int bits); +tree integer_type (bool is_unsigned, int bits); // Get an unnamed floating point type with the given number of bits // (32 or 64). -tree -float_type (int bits); +tree float_type (int bits); // Get a pointer type. -tree -pointer_type (tree to_type); +tree pointer_type (tree to_type); // Get a reference type. -tree -reference_type (tree to_type); +tree reference_type (tree to_type); // make type immutable -tree -immutable_type (tree base); +tree immutable_type (tree base); // Get a function type. The receiver, parameter, and results are // generated from the types in the Function_type. The Function_type @@ -115,41 +108,36 @@ immutable_type (tree base); // one result, RESULT_STRUCT is a struct type to hold the results, // and RESULTS may be ignored; if there are zero or one results, // RESULT_STRUCT is NULL. -tree -function_type (const typed_identifier &receiver, - const std::vector<typed_identifier> ¶meters, - const std::vector<typed_identifier> &results, tree result_struct, - location_t location); - -tree -function_type_variadic (const typed_identifier &receiver, - const std::vector<typed_identifier> ¶meters, - const std::vector<typed_identifier> &results, - tree result_struct, location_t location); - -tree -function_ptr_type (tree result, const std::vector<tree> &praameters, - location_t location); +tree function_type (const typed_identifier &receiver, + const std::vector<typed_identifier> ¶meters, + const std::vector<typed_identifier> &results, + tree result_struct, location_t location); + +tree function_type_variadic (const typed_identifier &receiver, + const std::vector<typed_identifier> ¶meters, + const std::vector<typed_identifier> &results, + tree result_struct, location_t location); + +tree function_ptr_type (tree result, const std::vector<tree> &praameters, + location_t location); // Get a struct type. -tree -struct_type (const std::vector<typed_identifier> &fields, bool layout = true); +tree struct_type (const std::vector<typed_identifier> &fields, + bool layout = true); // Get a union type. -tree -union_type (const std::vector<typed_identifier> &fields, bool layout = true); +tree union_type (const std::vector<typed_identifier> &fields, + bool layout = true); // Get an array type. -tree -array_type (tree element_type, tree length); +tree array_type (tree element_type, tree length); // Return a named version of a type. The location is the location // of the type definition. This will not be called for a type // created via placeholder_pointer_type, placeholder_struct_type, or // placeholder_array_type.. (It may be called for a pointer, // struct, or array type in a case like "type P *byte; type Q P".) -tree -named_type (const std::string &name, tree, location_t); +tree named_type (GGC::Ident name, tree, location_t); // Return the size of a type. int64_t type_size (tree); @@ -164,8 +152,7 @@ int64_t type_field_alignment (tree); // Return the offset of field INDEX in a struct type. INDEX is the // entry in the FIELDS std::vector parameter of struct_type or // set_placeholder_struct_type. -int64_t -type_field_offset (tree, size_t index); +int64_t type_field_offset (tree, size_t index); // Expressions. @@ -175,155 +162,135 @@ type_field_offset (tree, size_t index); tree zero_expression (tree); // Create a reference to a variable. -tree -var_expression (Bvariable *var, location_t); +tree var_expression (Bvariable *var, location_t); // Return an expression for the floating point value VAL in BTYPE. -tree -float_constant_expression (tree btype, mpfr_t val); +tree float_constant_expression (tree btype, mpfr_t val); // Return an expression for the string value VAL. -tree -string_constant_expression (const std::string &val); +tree string_constant_expression (const std::string &val); // Get a char literal -tree -char_constant_expression (char c); +tree char_constant_expression (char c); // Get a char literal -tree -wchar_constant_expression (wchar_t c); +tree wchar_constant_expression (wchar_t c); + +// Get a size literal +tree size_constant_expression (size_t val); // Return an expression for the boolean value VAL. -tree -boolean_constant_expression (bool val); +tree boolean_constant_expression (bool val); // Return an expression that converts EXPR to TYPE. -tree -convert_expression (tree type, tree expr, location_t); +tree convert_expression (tree type, tree expr, location_t); // Return an expression for the field at INDEX in BSTRUCT. -tree -struct_field_expression (tree bstruct, size_t index, location_t); +tree struct_field_expression (tree bstruct, size_t index, location_t); // Create an expression that executes BSTAT before BEXPR. -tree -compound_expression (tree bstat, tree bexpr, location_t); +tree compound_expression (tree bstat, tree bexpr, location_t); // Return an expression that executes THEN_EXPR if CONDITION is true, or // ELSE_EXPR otherwise and returns the result as type BTYPE, within the // specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL. -tree -conditional_expression (tree function, tree btype, tree condition, - tree then_expr, tree else_expr, location_t); +tree conditional_expression (tree function, tree btype, tree condition, + tree then_expr, tree else_expr, location_t); // Return an expression for the negation operation OP EXPR. // Supported values of OP are enumerated in NegationOperator. -tree -negation_expression (NegationOperator op, tree expr, location_t); +tree negation_expression (NegationOperator op, tree expr, location_t); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ArithmeticOrLogicalOperator. -tree -arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left, - tree right, location_t loc); +tree arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, + tree left, tree right, location_t loc); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ArithmeticOrLogicalOperator. // This function adds overflow checking and returns a list of statements to // add to the current function context. The `receiver` variable refers to the // variable which will contain the result of that operation. -tree -arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op, - tree left, tree right, location_t loc, - Bvariable *receiver); +tree arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op, + tree left, tree right, + location_t loc, + Bvariable *receiver); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ComparisonOperator. -tree -comparison_expression (ComparisonOperator op, tree left, tree right, - location_t loc); +tree comparison_expression (ComparisonOperator op, tree left, tree right, + location_t loc); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in LazyBooleanOperator. -tree -lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right, - location_t); +tree lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right, + location_t); // Return an expression that constructs BTYPE with VALS. BTYPE must be the // backend representation a of struct. VALS must be in the same order as the // corresponding fields in BTYPE. -tree -constructor_expression (tree btype, bool is_variant, - const std::vector<tree> &vals, int, location_t); +tree constructor_expression (tree btype, bool is_variant, + const std::vector<tree> &vals, int, location_t); // Return an expression that constructs an array of BTYPE with INDEXES and // VALS. INDEXES and VALS must have the same amount of elements. Each index // in INDEXES must be in the same order as the corresponding value in VALS. -tree -array_constructor_expression (tree btype, - const std::vector<unsigned long> &indexes, - const std::vector<tree> &vals, location_t); +tree array_constructor_expression (tree btype, + const std::vector<unsigned long> &indexes, + const std::vector<tree> &vals, location_t); -tree -array_initializer (tree, tree, tree, tree, tree, tree *, location_t); +tree array_initializer (tree, tree, tree, tree, tree, tree *, location_t); // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid // fixed-length array, not a slice. -tree -array_index_expression (tree array, tree index, location_t); +tree array_index_expression (tree array, tree index, location_t); + +// Return an expresison for SLICE[INDEX] as an l-value. SLICE is represented +// with a DST. +tree slice_index_expression (tree slice, tree index, location_t); // Create an expression for a call to FN with ARGS, taking place within // caller CALLER. -tree -call_expression (tree fn, const std::vector<tree> &args, tree static_chain, - location_t); +tree call_expression (tree fn, const std::vector<tree> &args, tree static_chain, + location_t); // Statements. // Create a variable initialization statement in the specified // function. This initializes a local variable at the point in the // program flow where it is declared. -tree -init_statement (tree, Bvariable *var, tree init); +tree init_statement (tree, Bvariable *var, tree init); // Create an assignment statement within the specified function. -tree -assignment_statement (tree lhs, tree rhs, location_t); +tree assignment_statement (tree lhs, tree rhs, location_t); // Create return statement for an decl for a value (can be NULL_TREE) at a // location -tree -return_statement (tree fndecl, tree val, location_t); +tree return_statement (tree fndecl, tree val, location_t); // Create an if statement within a function. ELSE_BLOCK may be NULL. -tree -if_statement (tree, tree condition, tree then_block, tree else_block, - location_t); +tree if_statement (tree, tree condition, tree then_block, tree else_block, + location_t); // infinite loop expressions -tree -loop_expression (tree body, location_t); +tree loop_expression (tree body, location_t); // exit expressions -tree -exit_expression (tree condition, location_t); +tree exit_expression (tree condition, location_t); // Create a single statement from two statements. tree compound_statement (tree, tree); // Create a single statement from a list of statements. -tree -statement_list (const std::vector<tree> &); +tree statement_list (const std::vector<tree> &); // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if // an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and // if not NULL, it will always be executed. This is used for handling defers // in Go functions. In C++, the resulting code is of this form: // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } -tree -exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt, - location_t); +tree exception_handler_statement (tree bstat, tree except_stmt, + tree finally_stmt, location_t); // Blocks. @@ -337,16 +304,14 @@ exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt, // the initial curly brace. END_LOCATION is the location of the end // of the block, more or less the location of the final curly brace. // The statements will be added after the block is created. -tree -block (tree function, tree enclosing, const std::vector<Bvariable *> &vars, - location_t start_location, location_t end_location); +tree block (tree function, tree enclosing, const std::vector<Bvariable *> &vars, + location_t start_location, location_t end_location); // Add the statements to a block. The block is created first. Then // the statements are created. Then the statements are added to the // block. This will called exactly once per block. The vector may // be empty if there are no statements. -void -block_add_statements (tree, const std::vector<tree> &); +void block_add_statements (tree, const std::vector<tree> &); // Variables. @@ -360,10 +325,9 @@ block_add_statements (tree, const std::vector<tree> &); // be put into a unique section if possible; this is intended to // permit the linker to garbage collect the variable if it is not // referenced. LOCATION is where the variable was defined. -Bvariable * -global_variable (const std::string &name, const std::string &asm_name, - tree btype, bool is_external, bool is_hidden, - bool in_unique_section, location_t location); +Bvariable *global_variable (GGC::Ident name, GGC::Ident asm_name, tree btype, + bool is_external, bool is_hidden, + bool in_unique_section, location_t location); // A global variable will 1) be initialized to zero, or 2) be // initialized to a constant value, or 3) be initialized in the init @@ -371,8 +335,7 @@ global_variable (const std::string &name, const std::string &asm_name, // global_variable_set_init to set the initial value. If this is // not called, the backend should initialize a global variable to 0. // The init function may then assign a value to it. -void -global_variable_set_init (Bvariable *, tree); +void global_variable_set_init (Bvariable *, tree); // Create a local variable. The frontend will create the local // variables first, and then create the block which contains them. @@ -386,21 +349,18 @@ 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, const std::string &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, const std::string &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, const std::string &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 @@ -413,18 +373,16 @@ static_chain_variable (tree function, const std::string &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. -// Create a new label. NAME will be empty if this is a label +// Create a new label. NAME will be tl::nullopt if this is a label // created by the frontend for a loop construct. The location is // where the label is defined. -tree -label (tree, const std::string &name, location_t); +tree label (tree, tl::optional<GGC::Ident> name, location_t); // Create a statement which defines a label. This statement will be // put into the codestream at the point where the label should be @@ -439,6 +397,12 @@ tree goto_statement (tree, location_t); // recover. tree label_address (tree, location_t); +// Lookup a field from a type given its name. +// Build the `component` tree with `Backend::get_identifier_node`. +// +// Forked from the C frontend. +tree lookup_field (const_tree, tree); + // Functions. // Bit flags to pass to the function method. @@ -460,43 +424,38 @@ static const unsigned int function_does_not_return = 1 << 2; static const unsigned int function_in_unique_section = 1 << 3; // Declare or define a function of FNTYPE. -// NAME is the Go name of the function. ASM_NAME, if not the empty -// string, is the name that should be used in the symbol table; this +// NAME is the Go name of the function. ASM_NAME, if not tl::nullopt, +// is the name that should be used in the symbol table; this // will be non-empty if a magic extern comment is used. FLAGS is // bit flags described above. -tree -function (tree fntype, const std::string &name, const std::string &asm_name, - unsigned int flags, location_t); +tree function (tree fntype, GGC::Ident name, tl::optional<GGC::Ident> asm_name, + unsigned int flags, location_t); // Create a statement that runs all deferred calls for FUNCTION. This should // be a statement that looks like this in C++: // finish: // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } -tree -function_defer_statement (tree function, tree undefer, tree check_defer, - location_t); +tree function_defer_statement (tree function, tree undefer, tree check_defer, + location_t); // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. // This will only be called for a function definition. Returns true on // success, false on failure. -bool -function_set_parameters (tree function, - const std::vector<Bvariable *> ¶m_vars); +bool function_set_parameters (tree function, + const std::vector<Bvariable *> ¶m_vars); // Utility. // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. -void -write_global_definitions (const std::vector<tree> &type_decls, - const std::vector<tree> &constant_decls, - const std::vector<tree> &function_decls, - const std::vector<Bvariable *> &variable_decls); +void write_global_definitions (const std::vector<tree> &type_decls, + const std::vector<tree> &constant_decls, + const std::vector<tree> &function_decls, + const std::vector<Bvariable *> &variable_decls); // TODO: make static -tree -fill_in_fields (tree, const std::vector<typed_identifier> &, bool); +tree fill_in_fields (tree, const std::vector<typed_identifier> &, bool); tree fill_in_array (tree, tree, tree); diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc index 0c0ef6e..5965bb4 100644 --- a/gcc/rust/rust-diagnostics.cc +++ b/gcc/rust/rust-diagnostics.cc @@ -22,7 +22,7 @@ #include "rust-diagnostics.h" #include "options.h" -#include "diagnostic-metadata.h" +#include "diagnostics/metadata.h" static std::string mformat_value () @@ -48,27 +48,33 @@ expand_format (const char *fmt) c++; switch (*c) { - case '\0': { + case '\0': + { // malformed format string rust_unreachable (); } - case '%': { + case '%': + { ss << "%"; break; } - case 'm': { + case 'm': + { ss << mformat_value (); break; } - case '<': { + case '<': + { ss << rust_open_quote (); break; } - case '>': { + case '>': + { ss << rust_close_quote (); break; } - case 'q': { + case 'q': + { ss << rust_open_quote (); c++; if (*c == 'm') @@ -82,7 +88,8 @@ expand_format (const char *fmt) ss << rust_close_quote (); break; } - default: { + default: + { ss << "%" << *c; } } @@ -104,8 +111,8 @@ expand_format (const char *fmt) // calling function must need to have attribute gnu_printf as well, even // though there is already an attribute declaration for it. -static std::string -expand_message (const char *fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG (1, 0); +static std::string expand_message (const char *fmt, va_list ap) + RUST_ATTRIBUTE_GCC_DIAG (1, 0); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsuggest-attribute=format" @@ -192,7 +199,7 @@ rust_error_at (const location_t location, const char *fmt, ...) va_end (ap); } -class rust_error_code_rule : public diagnostic_metadata::rule +class rust_error_code_rule : public diagnostics::metadata::rule { public: rust_error_code_rule (const ErrorCode code) : m_code (code) {} @@ -237,7 +244,7 @@ rust_be_error_at (const location_t location, const ErrorCode code, const std::string &errmsg) { rich_location gcc_loc (line_table, location); - diagnostic_metadata m; + diagnostics::metadata m; rust_error_code_rule rule (code); m.add_rule (rule); error_meta (&gcc_loc, m, "%s", errmsg.c_str ()); @@ -260,7 +267,7 @@ rust_be_error_at (const rich_location &location, const ErrorCode code, { /* TODO: 'error_at' would like a non-'const' 'rich_location *'. */ rich_location &gcc_loc = const_cast<rich_location &> (location); - diagnostic_metadata m; + diagnostics::metadata m; rust_error_code_rule rule (code); m.add_rule (rule); error_meta (&gcc_loc, m, "%s", errmsg.c_str ()); @@ -281,7 +288,7 @@ void rust_be_error_at (rich_location *richloc, const ErrorCode code, const std::string &errmsg) { - diagnostic_metadata m; + diagnostics::metadata m; rust_error_code_rule rule (code); m.add_rule (rule); error_meta (richloc, m, "%s", errmsg.c_str ()); @@ -420,24 +427,24 @@ namespace Rust { */ // simple location -static Error -va_constructor (Error::Kind kind, location_t locus, const char *fmt, - va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0); +static Error va_constructor (Error::Kind kind, location_t locus, + const char *fmt, va_list args) + RUST_ATTRIBUTE_GCC_DIAG (3, 0); // simple location + error code -static Error -va_constructor (Error::Kind kind, location_t locus, const ErrorCode code, - const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); +static Error va_constructor (Error::Kind kind, location_t locus, + const ErrorCode code, const char *fmt, + va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); // rich location -static Error -va_constructor (Error::Kind kind, rich_location *r_locus, const char *fmt, - va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0); +static Error va_constructor (Error::Kind kind, rich_location *r_locus, + const char *fmt, va_list args) + RUST_ATTRIBUTE_GCC_DIAG (3, 0); // rich location + error code -static Error -va_constructor (Error::Kind kind, rich_location *r_locus, const ErrorCode code, - const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); +static Error va_constructor (Error::Kind kind, rich_location *r_locus, + const ErrorCode code, const char *fmt, + va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); // simple location static Error diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h index a13dc6a2..09d5e24 100644 --- a/gcc/rust/rust-diagnostics.h +++ b/gcc/rust/rust-diagnostics.h @@ -31,7 +31,7 @@ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) #define RUST_ATTRIBUTE_GCC_DIAG(m, n) \ __attribute__ ((__format__ (__gcc_tdiag__, m, n))) \ - __attribute__ ((__nonnull__ (m))) + __attribute__ ((__nonnull__ (m))) #else #define RUST_ATTRIBUTE_GCC_DIAG(m, n) #endif @@ -119,10 +119,8 @@ rust_error_at(rich_location *richloc, const ErrorCode, const char *fmt, ...) // These interfaces provide a way for the front end to ask for // the open/close quote characters it should use when formatting // diagnostics (warnings, errors). -extern const char * -rust_open_quote (); -extern const char * -rust_close_quote (); +extern const char *rust_open_quote (); +extern const char *rust_close_quote (); // These interfaces are used by utilities above to pass warnings and // errors (once format specifiers have been expanded) to the back end, @@ -185,7 +183,7 @@ struct Error Error (Kind kind, location_t locus, std::string message) : kind (kind), locus (locus), message (std::move (message)) { - message.shrink_to_fit (); + this->message.shrink_to_fit (); } // simple location + error code Error (Kind kind, location_t locus, ErrorCode code, std::string message) @@ -193,13 +191,13 @@ struct Error message (std::move (message)) { is_errorcode = true; - message.shrink_to_fit (); + this->message.shrink_to_fit (); } // rich location Error (Kind kind, rich_location *richlocus, std::string message) : kind (kind), richlocus (richlocus), message (std::move (message)) { - message.shrink_to_fit (); + this->message.shrink_to_fit (); } // rich location + error code Error (Kind kind, rich_location *richlocus, ErrorCode code, @@ -208,7 +206,7 @@ struct Error message (std::move (message)) { is_errorcode = true; - message.shrink_to_fit (); + this->message.shrink_to_fit (); } // simple location Error (location_t locus, std::string message) @@ -306,8 +304,7 @@ struct Error #define rust_sorry_at(location, ...) sorry_at (location, __VA_ARGS__) -void -rust_debug_loc (const location_t location, const char *fmt, - ...) ATTRIBUTE_PRINTF_2; +void rust_debug_loc (const location_t location, const char *fmt, + ...) ATTRIBUTE_PRINTF_2; #endif // !defined(RUST_DIAGNOSTICS_H) diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index a6e8ea9..750c392 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -61,7 +61,7 @@ tree Bvariable::get_tree (location_t location) const { - if (this->t_ == error_mark_node) + if (error_operand_p (this->t_)) return error_mark_node; TREE_USED (this->t_) = 1; @@ -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 @@ -91,12 +108,6 @@ Bvariable::error_variable () // A helper function to create a GCC identifier from a C++ string. -static inline tree -get_identifier_from_string (const std::string &str) -{ - return get_identifier_with_length (str.data (), str.length ()); -} - namespace Backend { // Define the built-in functions that are exposed to GCCRust. @@ -431,7 +442,7 @@ float_type (int bits) tree pointer_type (tree to_type) { - if (to_type == error_mark_node) + if (error_operand_p (to_type)) return error_mark_node; tree type = build_pointer_type (to_type); return type; @@ -442,7 +453,7 @@ pointer_type (tree to_type) tree reference_type (tree to_type) { - if (to_type == error_mark_node) + if (error_operand_p (to_type)) return error_mark_node; tree type = build_reference_type (to_type); return type; @@ -453,7 +464,7 @@ reference_type (tree to_type) tree immutable_type (tree base) { - if (base == error_mark_node) + if (error_operand_p (base)) return error_mark_node; tree constified = build_qualified_type (base, TYPE_QUAL_CONST); return constified; @@ -472,17 +483,16 @@ function_type (const typed_identifier &receiver, if (receiver.type != NULL_TREE) { tree t = receiver.type; - if (t == error_mark_node) + if (error_operand_p (t)) return error_mark_node; *pp = tree_cons (NULL_TREE, t, NULL_TREE); pp = &TREE_CHAIN (*pp); } - for (std::vector<typed_identifier>::const_iterator p = parameters.begin (); - p != parameters.end (); ++p) + for (const auto &p : parameters) { - tree t = p->type; - if (t == error_mark_node) + tree t = p.type; + if (error_operand_p (t)) return error_mark_node; *pp = tree_cons (NULL_TREE, t, NULL_TREE); pp = &TREE_CHAIN (*pp); @@ -502,11 +512,11 @@ function_type (const typed_identifier &receiver, gcc_assert (result_struct != NULL); result = result_struct; } - if (result == error_mark_node) + if (error_operand_p (result)) return error_mark_node; tree fntype = build_function_type (result, args); - if (fntype == error_mark_node) + if (error_operand_p (fntype)) return error_mark_node; return build_pointer_type (fntype); @@ -521,21 +531,16 @@ function_type_variadic (const typed_identifier &receiver, size_t n = parameters.size () + (receiver.type != NULL_TREE ? 1 : 0); tree *args = XALLOCAVEC (tree, n); size_t offs = 0; + if (error_operand_p (receiver.type)) + return error_mark_node; if (receiver.type != NULL_TREE) - { - tree t = receiver.type; - if (t == error_mark_node) - return error_mark_node; - - args[offs++] = t; - } + args[offs++] = receiver.type; - for (std::vector<typed_identifier>::const_iterator p = parameters.begin (); - p != parameters.end (); ++p) + for (const auto &p : parameters) { - tree t = p->type; - if (t == error_mark_node) + tree t = p.type; + if (error_operand_p (t)) return error_mark_node; args[offs++] = t; } @@ -550,11 +555,11 @@ function_type_variadic (const typed_identifier &receiver, gcc_assert (result_struct != NULL_TREE); result = result_struct; } - if (result == error_mark_node) + if (error_operand_p (result)) return error_mark_node; tree fntype = build_varargs_function_type_array (result, n, args); - if (fntype == error_mark_node) + if (error_operand_p (fntype)) return error_mark_node; return build_pointer_type (fntype); @@ -569,7 +574,7 @@ function_ptr_type (tree result_type, const std::vector<tree> ¶meters, for (auto ¶m : parameters) { - if (param == error_mark_node) + if (error_operand_p (param)) return error_mark_node; *pp = tree_cons (NULL_TREE, param, NULL_TREE); @@ -583,7 +588,7 @@ function_ptr_type (tree result_type, const std::vector<tree> ¶meters, result = void_type_node; tree fntype = build_function_type (result, args); - if (fntype == error_mark_node) + if (error_operand_p (fntype)) return error_mark_node; return build_pointer_type (fntype); @@ -613,14 +618,13 @@ fill_in_fields (tree fill, const std::vector<typed_identifier> &fields, { tree field_trees = NULL_TREE; tree *pp = &field_trees; - for (std::vector<typed_identifier>::const_iterator p = fields.begin (); - p != fields.end (); ++p) + for (const auto &p : fields) { - tree name_tree = get_identifier_from_string (p->name); - tree type_tree = p->type; - if (type_tree == error_mark_node) + tree name_tree = p.name.as_tree (); + tree type_tree = p.type; + if (error_operand_p (type_tree)) return error_mark_node; - tree field = build_decl (p->location, FIELD_DECL, name_tree, type_tree); + tree field = build_decl (p.location, FIELD_DECL, name_tree, type_tree); DECL_CONTEXT (field) = fill; *pp = field; pp = &DECL_CHAIN (field); @@ -652,7 +656,7 @@ array_type (tree element_type, tree length) tree fill_in_array (tree fill, tree element_type, tree length_tree) { - if (element_type == error_mark_node || length_tree == error_mark_node) + if (error_operand_p (element_type) || error_operand_p (length_tree)) return error_mark_node; gcc_assert (TYPE_SIZE (element_type) != NULL_TREE); @@ -682,9 +686,9 @@ fill_in_array (tree fill, tree element_type, tree length_tree) // Return a named version of a type. tree -named_type (const std::string &name, tree type, location_t location) +named_type (GGC::Ident name, tree type, location_t location) { - if (type == error_mark_node) + if (error_operand_p (type)) return error_mark_node; // The middle-end expects a basic type to have a name. In Rust every @@ -695,15 +699,14 @@ named_type (const std::string &name, tree type, location_t location) || TREE_CODE (type) == COMPLEX_TYPE || TREE_CODE (type) == BOOLEAN_TYPE)) { - tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, - get_identifier_from_string (name), type); + tree decl + = build_decl (BUILTINS_LOCATION, TYPE_DECL, name.as_tree (), type); TYPE_NAME (type) = decl; return type; } tree copy = build_variant_type_copy (type); - tree decl - = build_decl (location, TYPE_DECL, get_identifier_from_string (name), copy); + tree decl = build_decl (location, TYPE_DECL, name.as_tree (), copy); DECL_ORIGINAL_TYPE (decl) = type; TYPE_NAME (copy) = decl; return copy; @@ -714,7 +717,7 @@ named_type (const std::string &name, tree type, location_t location) int64_t type_size (tree t) { - if (t == error_mark_node) + if (error_operand_p (t)) return 1; if (t == void_type_node) return 0; @@ -732,7 +735,7 @@ type_size (tree t) int64_t type_alignment (tree t) { - if (t == error_mark_node) + if (error_operand_p (t)) return 1; return TYPE_ALIGN_UNIT (t); } @@ -742,7 +745,7 @@ type_alignment (tree t) int64_t type_field_alignment (tree t) { - if (t == error_mark_node) + if (error_operand_p (t)) return 1; return rust_field_alignment (t); } @@ -752,7 +755,7 @@ type_field_alignment (tree t) int64_t type_field_offset (tree struct_tree, size_t index) { - if (struct_tree == error_mark_node) + if (error_operand_p (struct_tree)) return 0; gcc_assert (TREE_CODE (struct_tree) == RECORD_TYPE); tree field = TYPE_FIELDS (struct_tree); @@ -773,7 +776,7 @@ tree zero_expression (tree t) { tree ret; - if (t == error_mark_node) + if (error_operand_p (t)) ret = error_mark_node; else ret = build_zero_cst (t); @@ -794,7 +797,7 @@ tree float_constant_expression (tree t, mpfr_t val) { tree ret; - if (t == error_mark_node) + if (error_operand_p (t)) return error_mark_node; REAL_VALUE_TYPE r1; @@ -832,6 +835,12 @@ char_constant_expression (char c) return build_int_cst (char_type_node, c); } +tree +size_constant_expression (size_t val) +{ + return size_int (val); +} + // Make a constant boolean expression. tree @@ -845,8 +854,7 @@ boolean_constant_expression (bool val) tree convert_expression (tree type_tree, tree expr_tree, location_t location) { - if (type_tree == error_mark_node || expr_tree == error_mark_node - || TREE_TYPE (expr_tree) == error_mark_node) + if (error_operand_p (type_tree) || error_operand_p (expr_tree)) return error_mark_node; tree ret; @@ -878,8 +886,7 @@ convert_expression (tree type_tree, tree expr_tree, location_t location) tree struct_field_expression (tree struct_tree, size_t index, location_t location) { - if (struct_tree == error_mark_node - || TREE_TYPE (struct_tree) == error_mark_node) + if (error_operand_p (struct_tree)) return error_mark_node; gcc_assert (TREE_CODE (TREE_TYPE (struct_tree)) == RECORD_TYPE || TREE_CODE (TREE_TYPE (struct_tree)) == UNION_TYPE); @@ -895,7 +902,7 @@ struct_field_expression (tree struct_tree, size_t index, location_t location) field = DECL_CHAIN (field); gcc_assert (field != NULL_TREE); } - if (TREE_TYPE (field) == error_mark_node) + if (error_operand_p (TREE_TYPE (field))) return error_mark_node; tree ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (field), struct_tree, field, NULL_TREE); @@ -909,7 +916,7 @@ struct_field_expression (tree struct_tree, size_t index, location_t location) tree compound_expression (tree stat, tree expr, location_t location) { - if (stat == error_mark_node || expr == error_mark_node) + if (error_operand_p (stat) || error_operand_p (expr)) return error_mark_node; tree ret = fold_build2_loc (location, COMPOUND_EXPR, TREE_TYPE (expr), stat, expr); @@ -923,8 +930,8 @@ tree conditional_expression (tree, tree type_tree, tree cond_expr, tree then_expr, tree else_expr, location_t location) { - if (type_tree == error_mark_node || cond_expr == error_mark_node - || then_expr == error_mark_node || else_expr == error_mark_node) + if (error_operand_p (type_tree) || error_operand_p (cond_expr) + || error_operand_p (then_expr) || error_operand_p (else_expr)) return error_mark_node; tree ret = build3_loc (location, COND_EXPR, type_tree, cond_expr, then_expr, else_expr); @@ -1021,12 +1028,12 @@ operator_to_tree_code (LazyBooleanOperator op) } } -/* Helper function for deciding if a tree is a floating point node. */ +/* Returns true if the type of EXP is a floating point type. + False otherwise. */ bool -is_floating_point (tree t) +is_floating_point (tree exp) { - auto tree_type = TREE_CODE (TREE_TYPE (t)); - return tree_type == REAL_TYPE || tree_type == COMPLEX_TYPE; + return FLOAT_TYPE_P (TREE_TYPE (exp)); } // Return an expression for the negation operation OP EXPR. @@ -1035,7 +1042,7 @@ negation_expression (NegationOperator op, tree expr_tree, location_t location) { /* Check if the expression is an error, in which case we return an error expression. */ - if (expr_tree == error_mark_node || TREE_TYPE (expr_tree) == error_mark_node) + if (error_operand_p (expr_tree)) return error_mark_node; /* For negation operators, the resulting type should be the same as its @@ -1071,9 +1078,15 @@ arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left, { /* Check if either expression is an error, in which case we return an error expression. */ - if (left == error_mark_node || right == error_mark_node) + if (error_operand_p (left) || error_operand_p (right)) return error_mark_node; + // unwrap the const decls if set + if (TREE_CODE (left) == CONST_DECL) + left = DECL_INITIAL (left); + if (TREE_CODE (right) == CONST_DECL) + right = DECL_INITIAL (right); + /* We need to determine if we're doing floating point arithmetics of integer arithmetics. */ bool floating_point = is_floating_point (left); @@ -1112,6 +1125,7 @@ arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left, rust_error_at (location, "division by zero"); } else if (op == ArithmeticOrLogicalOperator::LEFT_SHIFT + && TREE_CODE (right) == INTEGER_CST && (compare_tree_int (right, TYPE_PRECISION (TREE_TYPE (ret))) >= 0)) { rust_error_at (location, "left shift count >= width of type"); @@ -1176,7 +1190,7 @@ arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op, { /* Check if either expression is an error, in which case we return an error expression. */ - if (left == error_mark_node || right == error_mark_node) + if (error_operand_p (left) || error_operand_p (right)) return error_mark_node; // FIXME: Add `if (!debug_mode)` @@ -1216,7 +1230,7 @@ comparison_expression (ComparisonOperator op, tree left_tree, tree right_tree, { /* Check if either expression is an error, in which case we return an error expression. */ - if (left_tree == error_mark_node || right_tree == error_mark_node) + if (error_operand_p (left_tree) || error_operand_p (right_tree)) return error_mark_node; /* For comparison operators, the resulting type should be boolean. */ @@ -1236,7 +1250,7 @@ lazy_boolean_expression (LazyBooleanOperator op, tree left_tree, { /* Check if either expression is an error, in which case we return an error expression. */ - if (left_tree == error_mark_node || right_tree == error_mark_node) + if (error_operand_p (left_tree) || error_operand_p (right_tree)) return error_mark_node; /* For lazy boolean operators, the resulting type should be the same as the @@ -1257,11 +1271,11 @@ constructor_expression (tree type_tree, bool is_variant, const std::vector<tree> &vals, int union_index, location_t location) { - if (type_tree == error_mark_node) + if (error_operand_p (type_tree)) return error_mark_node; vec<constructor_elt, va_gc> *init; - vec_alloc (init, vals.size ()); + vec_alloc (init, union_index != -1 ? 1 : vals.size ()); tree sink = NULL_TREE; bool is_constant = true; @@ -1299,8 +1313,8 @@ constructor_expression (tree type_tree, bool is_variant, gcc_assert (field != NULL_TREE); field = DECL_CHAIN (field); } - if (TREE_TYPE (field) == error_mark_node || val == error_mark_node - || TREE_TYPE (val) == error_mark_node) + + if (TREE_TYPE (field) == error_mark_node || error_operand_p (val)) return error_mark_node; if (int_size_in_bytes (TREE_TYPE (field)) == 0) @@ -1330,8 +1344,7 @@ constructor_expression (tree type_tree, bool is_variant, { gcc_assert (field != NULL_TREE); tree val = (*p); - if (TREE_TYPE (field) == error_mark_node || val == error_mark_node - || TREE_TYPE (val) == error_mark_node) + if (TREE_TYPE (field) == error_mark_node || error_operand_p (val)) return error_mark_node; if (int_size_in_bytes (TREE_TYPE (field)) == 0) @@ -1370,7 +1383,7 @@ array_constructor_expression (tree type_tree, const std::vector<tree> &vals, location_t location) { - if (type_tree == error_mark_node) + if (error_operand_p (type_tree)) return error_mark_node; gcc_assert (indexes.size () == vals.size ()); @@ -1387,7 +1400,7 @@ array_constructor_expression (tree type_tree, tree index = size_int (indexes[i]); tree val = vals[i]; - if (index == error_mark_node || val == error_mark_node) + if (error_operand_p (index) || error_operand_p (val)) return error_mark_node; if (element_size == 0) @@ -1491,8 +1504,7 @@ array_initializer (tree fndecl, tree block, tree array_type, tree length, tree array_index_expression (tree array_tree, tree index_tree, location_t location) { - if (array_tree == error_mark_node || TREE_TYPE (array_tree) == error_mark_node - || index_tree == error_mark_node) + if (error_operand_p (array_tree) || error_operand_p (index_tree)) return error_mark_node; // A function call that returns a zero sized object will have been @@ -1509,12 +1521,40 @@ array_index_expression (tree array_tree, tree index_tree, location_t location) return ret; } +// Return an expression representing SLICE[INDEX] + +tree +slice_index_expression (tree slice_tree, tree index_tree, location_t location) +{ + if (error_operand_p (slice_tree) || error_operand_p (index_tree)) + return error_mark_node; + + // A slice is created in TyTyResolvecompile::create_slice_type_record + // For example: + // &[i32] is turned directly into a struct { i32* data, usize len }; + // [i32] is also turned into struct { i32* data, usize len } + + // it should have RS_DST_FLAG set to 1 + rust_assert (RS_DST_FLAG_P (TREE_TYPE (slice_tree))); + + tree data_field = struct_field_expression (slice_tree, 0, location); + tree data_field_deref = build_fold_indirect_ref_loc (location, data_field); + + tree element_type = TREE_TYPE (data_field_deref); + tree data_pointer = TREE_OPERAND (data_field_deref, 0); + rust_assert (POINTER_TYPE_P (TREE_TYPE (data_pointer))); + tree data_offset_expr + = Rust::pointer_offset_expression (data_pointer, index_tree, location); + + return build1_loc (location, INDIRECT_REF, element_type, data_offset_expr); +} + // Create an expression for a call to FN_EXPR with FN_ARGS. tree call_expression (tree fn, const std::vector<tree> &fn_args, tree chain_expr, location_t location) { - if (fn == error_mark_node || TREE_TYPE (fn) == error_mark_node) + if (error_operand_p (fn)) return error_mark_node; gcc_assert (FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn))); @@ -1594,7 +1634,7 @@ tree init_statement (tree, Bvariable *var, tree init_tree) { tree var_tree = var->get_decl (); - if (var_tree == error_mark_node || init_tree == error_mark_node) + if (error_operand_p (var_tree) || error_operand_p (init_tree)) return error_mark_node; gcc_assert (TREE_CODE (var_tree) == VAR_DECL); @@ -1625,7 +1665,7 @@ init_statement (tree, Bvariable *var, tree init_tree) tree assignment_statement (tree lhs, tree rhs, location_t location) { - if (lhs == error_mark_node || rhs == error_mark_node) + if (error_operand_p (lhs) || error_operand_p (rhs)) return error_mark_node; // To avoid problems with GNU ld, we don't make zero-sized @@ -1650,14 +1690,14 @@ assignment_statement (tree lhs, tree rhs, location_t location) tree return_statement (tree fntree, tree val, location_t location) { - if (fntree == error_mark_node) + if (error_operand_p (fntree)) return error_mark_node; tree result = DECL_RESULT (fntree); - if (result == error_mark_node) + if (error_operand_p (result)) return error_mark_node; - if (val == error_mark_node) + if (error_operand_p (val)) return error_mark_node; tree set @@ -1675,8 +1715,8 @@ tree exception_handler_statement (tree try_stmt, tree except_stmt, tree finally_stmt, location_t location) { - if (try_stmt == error_mark_node || except_stmt == error_mark_node - || finally_stmt == error_mark_node) + if (error_operand_p (try_stmt) || error_operand_p (except_stmt) + || error_operand_p (finally_stmt)) return error_mark_node; if (except_stmt != NULL_TREE) @@ -1695,8 +1735,8 @@ tree if_statement (tree, tree cond_tree, tree then_tree, tree else_tree, location_t location) { - if (cond_tree == error_mark_node || then_tree == error_mark_node - || else_tree == error_mark_node) + if (error_operand_p (cond_tree) || error_operand_p (then_tree) + || error_operand_p (else_tree)) return error_mark_node; tree ret = build3_loc (location, COND_EXPR, void_type_node, cond_tree, then_tree, else_tree); @@ -1722,15 +1762,12 @@ exit_expression (tree cond_tree, location_t locus) tree compound_statement (tree s1, tree s2) { - tree stmt_list = NULL_TREE; - tree t = s1; - if (t == error_mark_node) - return error_mark_node; - append_to_statement_list (t, &stmt_list); - t = s2; - if (t == error_mark_node) + if (error_operand_p (s1) || error_operand_p (s2)) return error_mark_node; - append_to_statement_list (t, &stmt_list); + + tree stmt_list = NULL_TREE; + append_to_statement_list (s1, &stmt_list); + append_to_statement_list (s2, &stmt_list); // If neither statement has any side effects, stmt_list can be NULL // at this point. @@ -1746,11 +1783,9 @@ tree statement_list (const std::vector<tree> &statements) { tree stmt_list = NULL_TREE; - for (std::vector<tree>::const_iterator p = statements.begin (); - p != statements.end (); ++p) + for (tree t : statements) { - tree t = (*p); - if (t == error_mark_node) + if (error_operand_p (t)) return error_mark_node; append_to_statement_list (t, &stmt_list); } @@ -1802,12 +1837,13 @@ block (tree fndecl, tree enclosing, const std::vector<Bvariable *> &vars, *pp = block_tree; } + // Chain the variables of the scope together so they are all connected + // to the block. tree *pp = &BLOCK_VARS (block_tree); - for (std::vector<Bvariable *>::const_iterator pv = vars.begin (); - pv != vars.end (); ++pv) + for (Bvariable *bv : vars) { - *pp = (*pv)->get_decl (); - if (*pp != error_mark_node) + *pp = bv->get_decl (); + if (!error_operand_p (*pp)) pp = &DECL_CHAIN (*pp); } *pp = NULL_TREE; @@ -1826,11 +1862,9 @@ void block_add_statements (tree bind_tree, const std::vector<tree> &statements) { tree stmt_list = NULL_TREE; - for (std::vector<tree>::const_iterator p = statements.begin (); - p != statements.end (); ++p) + for (tree s : statements) { - tree s = (*p); - if (s != error_mark_node) + if (!error_operand_p (s)) append_to_statement_list (s, &stmt_list); } @@ -1886,7 +1920,8 @@ non_zero_size_type (tree type) } return rust_non_zero_struct; - case ARRAY_TYPE: { + case ARRAY_TYPE: + { tree element_type = non_zero_size_type (TREE_TYPE (type)); return build_array_type_nelts (element_type, 1); } @@ -1908,8 +1943,7 @@ convert_tree (tree type_tree, tree expr_tree, location_t location) if (type_tree == TREE_TYPE (expr_tree)) return expr_tree; - if (type_tree == error_mark_node || expr_tree == error_mark_node - || TREE_TYPE (expr_tree) == error_mark_node) + if (error_operand_p (type_tree) || error_operand_p (expr_tree)) return error_mark_node; if (POINTER_TYPE_P (type_tree) || INTEGRAL_TYPE_P (type_tree) @@ -1934,11 +1968,11 @@ convert_tree (tree type_tree, tree expr_tree, location_t location) // Make a global variable. Bvariable * -global_variable (const std::string &var_name, const std::string &asm_name, - tree type_tree, bool is_external, bool is_hidden, - bool in_unique_section, location_t location) +global_variable (GGC::Ident var_name, GGC::Ident asm_name, tree type_tree, + bool is_external, bool is_hidden, bool in_unique_section, + location_t location) { - if (type_tree == error_mark_node) + if (error_operand_p (type_tree)) return Bvariable::error_variable (); // The GNU linker does not like dynamic variables with zero size. @@ -1946,8 +1980,7 @@ global_variable (const std::string &var_name, const std::string &asm_name, if ((is_external || !is_hidden) && int_size_in_bytes (type_tree) == 0) type_tree = non_zero_size_type (type_tree); - tree decl = build_decl (location, VAR_DECL, - get_identifier_from_string (var_name), type_tree); + tree decl = build_decl (location, VAR_DECL, var_name.as_tree (), type_tree); if (is_external) DECL_EXTERNAL (decl) = 1; else @@ -1955,11 +1988,11 @@ global_variable (const std::string &var_name, const std::string &asm_name, if (!is_hidden) { TREE_PUBLIC (decl) = 1; - SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); + SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ()); } else { - SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); + SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ()); } TREE_USED (decl) = 1; @@ -1977,11 +2010,11 @@ global_variable (const std::string &var_name, const std::string &asm_name, void global_variable_set_init (Bvariable *var, tree expr_tree) { - if (expr_tree == error_mark_node) + if (error_operand_p (expr_tree)) return; gcc_assert (TREE_CONSTANT (expr_tree)); tree var_decl = var->get_decl (); - if (var_decl == error_mark_node) + if (error_operand_p (var_decl)) return; DECL_INITIAL (var_decl) = expr_tree; @@ -1998,14 +2031,13 @@ global_variable_set_init (Bvariable *var, tree expr_tree) // Make a local variable. -Bvariable * -local_variable (tree function, const std::string &name, tree type_tree, +LocalVariable +local_variable (tree function, GGC::Ident name, tree type_tree, Bvariable *decl_var, location_t location) { - if (type_tree == error_mark_node) - return Bvariable::error_variable (); - tree decl = build_decl (location, VAR_DECL, get_identifier_from_string (name), - type_tree); + if (error_operand_p (type_tree)) + return LocalVariable::error_variable (); + tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree); DECL_CONTEXT (decl) = function; if (decl_var != NULL) @@ -2014,36 +2046,34 @@ local_variable (tree function, const std::string &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 * -parameter_variable (tree function, const std::string &name, tree type_tree, +LocalVariable +parameter_variable (tree function, GGC::Ident name, tree type_tree, location_t location) { - if (type_tree == error_mark_node) - return Bvariable::error_variable (); - tree decl = build_decl (location, PARM_DECL, - get_identifier_from_string (name), type_tree); + if (error_operand_p (type_tree)) + 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 * -static_chain_variable (tree fndecl, const std::string &name, tree type_tree, +LocalVariable +static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree, location_t location) { - if (type_tree == error_mark_node) - return Bvariable::error_variable (); - tree decl = build_decl (location, PARM_DECL, - get_identifier_from_string (name), type_tree); + if (error_operand_p (type_tree)) + 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; TREE_USED (decl) = 1; @@ -2063,22 +2093,22 @@ static_chain_variable (tree fndecl, const std::string &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) { gcc_assert (fndecl != NULL_TREE); - if (type_tree == error_mark_node || init_tree == error_mark_node - || fndecl == error_mark_node) + if (error_operand_p (type_tree) || error_operand_p (init_tree) + || error_operand_p (fndecl)) { *pstatement = error_mark_node; - return Bvariable::error_variable (); + return LocalVariable::error_variable (); } tree var; @@ -2128,16 +2158,16 @@ 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. tree -label (tree func_tree, const std::string &name, location_t location) +label (tree func_tree, tl::optional<GGC::Ident> name, location_t location) { tree decl; - if (name.empty ()) + if (!name.has_value ()) { if (DECL_STRUCT_FUNCTION (func_tree) == NULL) push_struct_function (func_tree); @@ -2150,7 +2180,7 @@ label (tree func_tree, const std::string &name, location_t location) } else { - tree id = get_identifier_from_string (name); + tree id = name->as_tree (); decl = build_decl (location, LABEL_DECL, id, void_type_node); DECL_CONTEXT (decl) = func_tree; } @@ -2189,21 +2219,21 @@ label_address (tree label, location_t location) // Declare or define a new function. tree -function (tree functype, const std::string &name, const std::string &asm_name, +function (tree functype, GGC::Ident name, tl::optional<GGC::Ident> asm_name, unsigned int flags, location_t location) { - if (functype != error_mark_node) - { - gcc_assert (FUNCTION_POINTER_TYPE_P (functype)); - functype = TREE_TYPE (functype); - } - tree id = get_identifier_from_string (name); - if (functype == error_mark_node || id == error_mark_node) + if (error_operand_p (functype)) + return error_mark_node; + + gcc_assert (FUNCTION_POINTER_TYPE_P (functype)); + functype = TREE_TYPE (functype); + tree id = name.as_tree (); + if (error_operand_p (id)) return error_mark_node; tree decl = build_decl (location, FUNCTION_DECL, id, functype); - if (!asm_name.empty ()) - SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); + if (asm_name.has_value ()) + SET_DECL_ASSEMBLER_NAME (decl, asm_name->as_tree ()); if ((flags & function_is_declaration) != 0) DECL_EXTERNAL (decl) = 1; @@ -2236,8 +2266,8 @@ tree function_defer_statement (tree function, tree undefer_tree, tree defer_tree, location_t location) { - if (undefer_tree == error_mark_node || defer_tree == error_mark_node - || function == error_mark_node) + if (error_operand_p (undefer_tree) || error_operand_p (defer_tree) + || error_operand_p (function)) return error_mark_node; if (DECL_STRUCT_FUNCTION (function) == NULL) @@ -2246,7 +2276,7 @@ function_defer_statement (tree function, tree undefer_tree, tree defer_tree, push_cfun (DECL_STRUCT_FUNCTION (function)); tree stmt_list = NULL; - tree label = Backend::label (function, "", location); + tree label = Backend::label (function, tl::nullopt, location); tree label_def = label_definition_statement (label); append_to_statement_list (label_def, &stmt_list); @@ -2269,16 +2299,15 @@ bool function_set_parameters (tree function, const std::vector<Bvariable *> ¶m_vars) { - if (function == error_mark_node) + if (error_operand_p (function)) return false; tree params = NULL_TREE; tree *pp = ¶ms; - for (std::vector<Bvariable *>::const_iterator pv = param_vars.begin (); - pv != param_vars.end (); ++pv) + for (Bvariable *bv : param_vars) { - *pp = (*pv)->get_decl (); - gcc_assert (*pp != error_mark_node); + *pp = bv->get_decl (); + gcc_assert (!error_operand_p (*pp)); pp = &DECL_CHAIN (*pp); } *pp = NULL_TREE; @@ -2303,23 +2332,19 @@ write_global_definitions (const std::vector<tree> &type_decls, // Convert all non-erroneous declarations into Gimple form. size_t i = 0; - for (std::vector<Bvariable *>::const_iterator p = variable_decls.begin (); - p != variable_decls.end (); ++p) + for (Bvariable *bv : variable_decls) { - tree v = (*p)->get_decl (); - if (v != error_mark_node) - { - defs[i] = v; - rust_preserve_from_gc (defs[i]); - ++i; - } + tree v = bv->get_decl (); + if (error_operand_p (v)) + continue; + defs[i] = v; + rust_preserve_from_gc (defs[i]); + ++i; } - for (std::vector<tree>::const_iterator p = type_decls.begin (); - p != type_decls.end (); ++p) + for (tree type_tree : type_decls) { - tree type_tree = (*p); - if (type_tree != error_mark_node && IS_TYPE_OR_DECL_P (type_tree)) + if (!error_operand_p (type_tree) && IS_TYPE_OR_DECL_P (type_tree)) { defs[i] = TYPE_NAME (type_tree); gcc_assert (defs[i] != NULL); @@ -2327,21 +2352,18 @@ write_global_definitions (const std::vector<tree> &type_decls, ++i; } } - for (std::vector<tree>::const_iterator p = constant_decls.begin (); - p != constant_decls.end (); ++p) + for (tree t : constant_decls) { - if ((*p) != error_mark_node) + if (!error_operand_p (t)) { - defs[i] = (*p); + defs[i] = t; rust_preserve_from_gc (defs[i]); ++i; } } - for (std::vector<tree>::const_iterator p = function_decls.begin (); - p != function_decls.end (); ++p) + for (tree decl : function_decls) { - tree decl = (*p); - if (decl != error_mark_node) + if (!error_operand_p (decl)) { rust_preserve_from_gc (decl); if (DECL_STRUCT_FUNCTION (decl) == NULL) @@ -2361,4 +2383,30 @@ write_global_definitions (const std::vector<tree> &type_decls, delete[] defs; } +tree +lookup_field (const_tree type, tree component) +{ + tree field; + + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + if (DECL_NAME (field) == NULL_TREE + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))) + { + tree anon = lookup_field (TREE_TYPE (field), component); + + if (anon) + return tree_cons (NULL_TREE, field, anon); + } + + if (DECL_NAME (field) == component) + break; + } + + if (field == NULL_TREE) + return NULL_TREE; + + return tree_cons (NULL_TREE, field, NULL_TREE); +} + } // namespace Backend 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/rust-lang.cc b/gcc/rust/rust-lang.cc index f3a155d..1088845 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -34,7 +34,6 @@ #include "selftest.h" #include "rust-cfg-parser.h" #include "rust-privacy-ctx.h" -#include "rust-ast-resolve-item.h" #include "rust-lex.h" #include "optional.h" #include "rust-unicode.h" @@ -51,10 +50,10 @@ // FIXME: test saving intellisense #include "options.h" -// version check to stop compiling if c++ isn't c++11 or higher -#if __cplusplus < 201103 +// version check to stop compiling if c++ isn't c++14 or higher +#if __cplusplus < 201402 #error \ - "GCC Rust frontend requires C++11 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that." + "GCC Rust frontend requires C++14 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that." #endif // TODO: is this best way to do it? Is it allowed? (should be) @@ -373,7 +372,13 @@ rust_localize_identifier (const char *ident) return identifier_to_locale (ident); } -extern const attribute_spec grs_langhook_common_attribute_table[]; +extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table; +extern const struct scoped_attribute_specs grs_langhook_common_attribute_table; + +const scoped_attribute_specs *const grs_langhook_attribute_table[] = { + &grs_langhook_gnu_attribute_table, + &grs_langhook_common_attribute_table, +}; /* The language hooks data structure. This is the main interface between the GCC * front-end and the GCC middle-end/back-end. A list of language hooks could be @@ -394,8 +399,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[]; #undef LANG_HOOKS_WRITE_GLOBALS #undef LANG_HOOKS_GIMPLIFY_EXPR #undef LANG_HOOKS_EH_PERSONALITY - -#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE +#undef LANG_HOOKS_ATTRIBUTE_TABLE #define LANG_HOOKS_NAME "GNU Rust" #define LANG_HOOKS_INIT grs_langhook_init @@ -417,7 +421,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[]; #define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr #define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality -#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE grs_langhook_common_attribute_table +#define LANG_HOOKS_ATTRIBUTE_TABLE grs_langhook_attribute_table #if CHECKING_P @@ -437,7 +441,6 @@ run_rust_tests () rust_cfg_parser_test (); rust_privacy_ctx_test (); rust_crate_name_validation_test (); - rust_simple_path_resolve_test (); } } // namespace selftest diff --git a/gcc/rust/rust-object-export.h b/gcc/rust/rust-object-export.h index fe055c3..784fef3 100644 --- a/gcc/rust/rust-object-export.h +++ b/gcc/rust/rust-object-export.h @@ -21,13 +21,10 @@ #include "rust-system.h" -extern unsigned int -rust_field_alignment (tree t); - -extern const char * -rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, - int *perr); -extern void -rust_write_export_data (const char *bytes, unsigned int size); +extern unsigned int rust_field_alignment (tree t); + +extern const char *rust_read_export_data (int fd, off_t offset, char **pbuf, + size_t *plen, int *perr); +extern void rust_write_export_data (const char *bytes, unsigned int size); #endif // RUST_OBJECT_EXPORT_H diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 15f21ef..6418118 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -20,14 +20,15 @@ #include "rust-collect-lang-items.h" #include "rust-desugar-for-loops.h" #include "rust-desugar-question-mark.h" +#include "rust-desugar-apit.h" #include "rust-diagnostics.h" +#include "rust-expression-yeast.h" #include "rust-hir-pattern-analysis.h" #include "rust-immutable-name-resolution-context.h" #include "rust-unsafe-checker.h" #include "rust-lex.h" #include "rust-parse.h" #include "rust-macro-expand.h" -#include "rust-ast-resolve.h" #include "rust-ast-lower.h" #include "rust-hir-type-check.h" #include "rust-privacy-check.h" @@ -44,10 +45,10 @@ #include "rust-imports.h" #include "rust-extern-crate.h" #include "rust-attributes.h" -#include "rust-early-name-resolver.h" #include "rust-name-resolution-context.h" #include "rust-early-name-resolver-2.0.h" #include "rust-late-name-resolver-2.0.h" +#include "rust-resolve-builtins.h" #include "rust-cfg-strip.h" #include "rust-expand-visitor.h" #include "rust-unicode.h" @@ -61,11 +62,9 @@ #include "tm.h" #include "rust-target.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); -extern Linemap * -rust_get_linemap (); +extern Linemap *rust_get_linemap (); namespace Rust { @@ -150,9 +149,9 @@ validate_crate_name (const std::string &crate_name, Error &error) { if (!(is_alphabetic (c.value) || is_numeric (c.value) || c.value == '_')) { - error = Error (UNDEF_LOCATION, - "invalid character %qs in crate name: %qs", - c.as_string ().c_str (), crate_name.c_str ()); + error + = Error (UNDEF_LOCATION, "invalid character %qs in crate name: %qs", + c.as_string ().c_str (), crate_name.c_str ()); return false; } } @@ -203,14 +202,16 @@ Session::handle_option ( switch (code) { case OPT_I: - case OPT_L: { + case OPT_L: + { // TODO: add search path const std::string p = std::string (arg); add_search_path (p); } break; - case OPT_frust_extern_: { + case OPT_frust_extern_: + { std::string input (arg); ret = handle_extern_option (input); } @@ -251,7 +252,8 @@ Session::handle_option ( Compile::Mangler::set_mangling (flag_rust_mangling); break; - case OPT_frust_cfg_: { + case OPT_frust_cfg_: + { auto string_arg = std::string (arg); ret = handle_cfg_option (string_arg); break; @@ -419,32 +421,31 @@ Session::handle_crate_name (const char *filename, { if (attr.get_path () != "crate_name") continue; - if (!attr.has_attr_input ()) + + auto msg_str = Analysis::Attributes::extract_string_literal (attr); + if (!msg_str.has_value ()) { rust_error_at (attr.get_locus (), - "%<crate_name%> accepts one argument"); + "malformed %<crate_name%> attribute input"); continue; } - auto &literal - = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &msg_str = literal.get_literal ().as_string (); - if (!validate_crate_name (msg_str, error)) + if (!validate_crate_name (*msg_str, error)) { error.locus = attr.get_locus (); error.emit (); continue; } - if (options.crate_name_set_manually && (options.crate_name != msg_str)) + if (options.crate_name_set_manually && (options.crate_name != *msg_str)) { rust_error_at (attr.get_locus (), "%<-frust-crate-name%> and %<#[crate_name]%> are " "required to match, but %qs does not match %qs", - options.crate_name.c_str (), msg_str.c_str ()); + options.crate_name.c_str (), msg_str->c_str ()); } crate_name_found = true; - options.set_crate_name (msg_str); + options.set_crate_name (*msg_str); } options.crate_name_set_manually |= crate_name_found; @@ -548,10 +549,6 @@ Session::compile_crate (const char *filename) handle_crate_name (filename, *ast_crate.get ()); // dump options except lexer dump - if (options.dump_option_enabled (CompileOptions::AST_DUMP_PRETTY)) - { - dump_ast_pretty (*ast_crate.get ()); - } if (options.dump_option_enabled (CompileOptions::TARGET_OPTION_DUMP)) { options.target_data.dump_target_options (); @@ -560,6 +557,11 @@ Session::compile_crate (const char *filename) if (saw_errors ()) return; + if (options.dump_option_enabled (CompileOptions::AST_DUMP_PRETTY)) + { + dump_ast_pretty (*ast_crate.get ()); + } + // setup the mappings for this AST CrateNum current_crate = mappings.get_current_crate (); AST::Crate &parsed_crate @@ -610,15 +612,12 @@ Session::compile_crate (const char *filename) if (last_step == CompileOptions::CompileStep::Expansion) return; - AST::CollectLangItems ().go (parsed_crate); - AST::DesugarQuestionMark ().go (parsed_crate); - auto name_resolution_ctx = Resolver2_0::NameResolutionContext (); // expansion pipeline stage expansion (parsed_crate, name_resolution_ctx); - AST::DesugarForLoops ().go (parsed_crate); + AST::CollectLangItems ().go (parsed_crate); rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m"); if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP)) @@ -644,10 +643,7 @@ Session::compile_crate (const char *filename) return; // resolution pipeline stage - if (flag_name_resolution_2_0) - Resolver2_0::Late (name_resolution_ctx).go (parsed_crate); - else - Resolver::NameResolution::Resolve (parsed_crate); + Resolver2_0::Late (name_resolution_ctx).go (parsed_crate); if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP)) dump_name_resolution (name_resolution_ctx); @@ -682,6 +678,7 @@ Session::compile_crate (const char *filename) Resolver2_0::ImmutableNameResolutionContext::init (name_resolution_ctx); // type resolve + Compile::Context *ctx = Compile::Context::get (); Resolver::TypeResolution::Resolve (hir); Resolver::TypeCheckContext::get ()->get_variance_analysis_ctx ().solve (); @@ -729,16 +726,15 @@ Session::compile_crate (const char *filename) return; // do compile to gcc generic - Compile::Context ctx; - Compile::CompileCrate::Compile (hir, &ctx); + Compile::CompileCrate::Compile (hir, ctx); // we can't do static analysis if there are errors to worry about if (!saw_errors ()) { // lints Analysis::ScanDeadcode::Scan (hir); - Analysis::UnusedVariables::Lint (ctx); - Analysis::ReadonlyCheck::Lint (ctx); + Analysis::UnusedVariables::Lint (*ctx); + HIR::ReadonlyChecker ().go (hir); // metadata bool specified_emit_metadata @@ -758,8 +754,11 @@ Session::compile_crate (const char *filename) } } + if (saw_errors ()) + return; + // pass to GCC middle-end - ctx.write_to_backend (); + ctx->write_to_backend (); } void @@ -937,28 +936,23 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) MacroExpander expander (crate, cfg, *this); std::vector<Error> macro_errors; + Resolver2_0::Builtins::setup_lang_prelude (ctx); + while (!fixed_point_reached && iterations < cfg.recursion_limit) { - CfgStrip ().go (crate); + CfgStrip (cfg).go (crate); // Errors might happen during cfg strip pass - bool visitor_dirty = false; - if (flag_name_resolution_2_0) - { - Resolver2_0::Early early (ctx); - early.go (crate); - macro_errors = early.get_macro_resolve_errors (); - visitor_dirty = early.is_dirty (); - } - else - Resolver::EarlyNameResolver ().go (crate); + Resolver2_0::Early early (ctx); + early.go (crate); + macro_errors = early.get_macro_resolve_errors (); if (saw_errors ()) break; ExpandVisitor (expander).go (crate); - fixed_point_reached = !expander.has_changed () && !visitor_dirty; + fixed_point_reached = !expander.has_changed () && !early.is_dirty (); expander.reset_changed_state (); iterations++; @@ -983,6 +977,19 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) rust_error_at (range, "reached recursion limit"); } + // handle AST desugaring + if (!saw_errors ()) + { + AST::ExpressionYeast ().go (crate); + + AST::DesugarApit ().go (crate); + + // HACK: we may need a final TopLevel pass + // however, this should not count towards the recursion limit + // and we don't need a full Early pass + Resolver2_0::TopLevel (ctx).go (crate); + } + // error reporting - check unused macros, get missing fragment specifiers // build test harness @@ -1108,8 +1115,7 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus) if (stream == NULL // No stream and && proc_macros.empty ()) // no proc macros { - rust_error_at (locus, "failed to locate crate %qs", - import_name.c_str ()); + rust_error_at (locus, "failed to locate crate %qs", import_name.c_str ()); return UNKNOWN_NODEID; } @@ -1177,17 +1183,6 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus) mappings.insert_bang_proc_macros (crate_num, bang_macros); mappings.insert_derive_proc_macros (crate_num, derive_macros); - // name resolve it - Resolver::NameResolution::Resolve (parsed_crate); - - // perform hir lowering - std::unique_ptr<HIR::Crate> lowered - = HIR::ASTLowering::Resolve (parsed_crate); - HIR::Crate &hir = mappings.insert_hir_crate (std::move (lowered)); - - // perform type resolution - Resolver::TypeResolution::Resolve (hir); - // always restore the crate_num mappings.set_current_crate (saved_crate_num); diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 83ba121..9af103c 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -441,8 +441,7 @@ private: #if CHECKING_P namespace selftest { -extern void -rust_crate_name_validation_test (void); +extern void rust_crate_name_validation_test (void); } #endif // CHECKING_P diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index 986428b..a455123 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -88,10 +88,8 @@ constexpr static const char *file_separator = "/"; */ #define rust_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__)) -extern void -rust_preserve_from_gc (tree t); +extern void rust_preserve_from_gc (tree t); -extern const char * -rust_localize_identifier (const char *ident); +extern const char *rust_localize_identifier (const char *ident); #endif // !defined(RUST_SYSTEM_H) diff --git a/gcc/rust/rust-target.h b/gcc/rust/rust-target.h index dbc2baf..e61ea51 100644 --- a/gcc/rust/rust-target.h +++ b/gcc/rust/rust-target.h @@ -26,8 +26,7 @@ #include "rust-target.def" /* Used by target to add target-related info. */ -extern void -rust_add_target_info (const char *, const char *); +extern void rust_add_target_info (const char *, const char *); /* Each target can provide their own. */ extern struct gcc_targetrustm targetrustm; diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc index 6aa20a8..8cc2b7b 100644 --- a/gcc/rust/typecheck/rust-autoderef.cc +++ b/gcc/rust/typecheck/rust-autoderef.cc @@ -26,8 +26,7 @@ namespace Rust { namespace Resolver { -static bool -resolve_operator_overload_fn ( +static bool resolve_operator_overload_fn ( LangItem::Kind lang_item_type, TyTy::BaseType *ty, TyTy::FnType **resolved_fn, Adjustment::AdjustmentType *requires_ref_adjustment); @@ -248,7 +247,6 @@ resolve_operator_overload_fn ( const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (lhs); auto s = fn->get_self_type ()->get_root (); - rust_assert (s->can_eq (adt, false)); rust_assert (s->get_kind () == TyTy::TypeKind::ADT); const TyTy::ADTType *self_adt = static_cast<const TyTy::ADTType *> (s); @@ -427,8 +425,7 @@ AutoderefCycle::try_autoderefed (TyTy::BaseType *r) TyTy::ReferenceType *r1 = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()), Mutability::Imm); - adjustments.push_back ( - Adjustment (Adjustment::AdjustmentType::IMM_REF, r, r1)); + adjustments.emplace_back (Adjustment::AdjustmentType::IMM_REF, r, r1); if (select (*r1)) return true; @@ -438,8 +435,7 @@ AutoderefCycle::try_autoderefed (TyTy::BaseType *r) TyTy::ReferenceType *r2 = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()), Mutability::Mut); - adjustments.push_back ( - Adjustment (Adjustment::AdjustmentType::MUT_REF, r, r2)); + adjustments.emplace_back (Adjustment::AdjustmentType::MUT_REF, r, r2); if (select (*r2)) return true; diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc index 90bdef1..7d08601 100644 --- a/gcc/rust/typecheck/rust-casts.cc +++ b/gcc/rust/typecheck/rust-casts.cc @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-casts.h" +#include "rust-tyty-util.h" namespace Rust { namespace Resolver { @@ -28,15 +29,20 @@ TypeCastRules::TypeCastRules (location_t locus, TyTy::TyWithLocation from, TypeCoercionRules::CoercionResult TypeCastRules::resolve (location_t locus, TyTy::TyWithLocation from, - TyTy::TyWithLocation to) + TyTy::TyWithLocation to, bool emit_error) { TypeCastRules cast_rules (locus, from, to); - return cast_rules.check (); + return cast_rules.check (emit_error); } TypeCoercionRules::CoercionResult -TypeCastRules::check () +TypeCastRules::check (bool emit_error) { + // try the simple cast rules + auto simple_cast = cast_rules (); + if (!simple_cast.is_error ()) + return simple_cast; + // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/cast.rs#L565-L582 auto possible_coercion = TypeCoercionRules::TryCoerce (from.get_ty (), to.get_ty (), locus, @@ -51,13 +57,9 @@ TypeCastRules::check () true /*is_cast_site*/); } - // try the simple cast rules - auto simple_cast = cast_rules (); - if (!simple_cast.is_error ()) - return simple_cast; + if (emit_error) + TypeCastRules::emit_cast_error (locus, from, to); - // failed to cast - emit_cast_error (); return TypeCoercionRules::CoercionResult::get_error (); } @@ -73,7 +75,8 @@ TypeCastRules::cast_rules () to.get_ty ()->debug_str ().c_str ()); switch (from_type->get_kind ()) { - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *from_infer = static_cast<TyTy::InferType *> (from_type); switch (from_infer->get_infer_kind ()) @@ -85,7 +88,8 @@ TypeCastRules::cast_rules () case TyTy::InferType::InferTypeKind::INTEGRAL: switch (to.get_ty ()->get_kind ()) { - case TyTy::TypeKind::CHAR: { + case TyTy::TypeKind::CHAR: + { // only u8 and char bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT; @@ -108,7 +112,8 @@ TypeCastRules::cast_rules () return TypeCoercionRules::CoercionResult{ {}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast<TyTy::InferType *> (to.get_ty ()); @@ -140,7 +145,8 @@ TypeCastRules::cast_rules () return TypeCoercionRules::CoercionResult{ {}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast<TyTy::InferType *> (to.get_ty ()); @@ -187,7 +193,8 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::INT: switch (to.get_ty ()->get_kind ()) { - case TyTy::TypeKind::CHAR: { + case TyTy::TypeKind::CHAR: + { // only u8 and char bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT; bool was_u8 = was_uint @@ -200,7 +207,8 @@ TypeCastRules::cast_rules () } break; - case TyTy::TypeKind::FLOAT: { + case TyTy::TypeKind::FLOAT: + { // can only do this for number types not char bool from_char = from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR; @@ -210,7 +218,8 @@ TypeCastRules::cast_rules () } break; - case TyTy::TypeKind::POINTER: { + case TyTy::TypeKind::POINTER: + { // char can't be casted as a ptr bool from_char = from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR; @@ -244,7 +253,8 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::FLOAT: return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast<TyTy::InferType *> (to.get_ty ()); @@ -267,16 +277,19 @@ TypeCastRules::cast_rules () break; case TyTy::TypeKind::REF: + case TyTy::TypeKind::FNPTR: case TyTy::TypeKind::POINTER: switch (to.get_ty ()->get_kind ()) { case TyTy::TypeKind::USIZE: case TyTy::TypeKind::ISIZE: case TyTy::TypeKind::UINT: - case TyTy::TypeKind::INT: { + case TyTy::TypeKind::INT: + { // refs should not cast to numeric type - bool from_ptr - = from.get_ty ()->get_kind () == TyTy::TypeKind::POINTER; + auto kind = from.get_ty ()->get_kind (); + bool from_ptr = kind == TyTy::TypeKind::POINTER + || kind == TyTy::TypeKind::FNPTR; if (from_ptr) { return TypeCoercionRules::CoercionResult{ @@ -320,7 +333,27 @@ TypeCastRules::check_ptr_ptr_cast () } else if (from_is_ref && to_is_ref) { - // mutability must be coercedable + const auto &from_ref = *from.get_ty ()->as<TyTy::ReferenceType> (); + const auto &to_ref = *to.get_ty ()->as<TyTy::ReferenceType> (); + + if (from_ref.is_dyn_object () != to_ref.is_dyn_object ()) + { + // this needs to be handled by coercion logic + return TypeCoercionRules::CoercionResult::get_error (); + } + + // are the underlying types safely simple castable? + const auto to_underly = to_ref.get_base (); + const auto from_underly = from_ref.get_base (); + auto res = resolve (locus, TyTy::TyWithLocation (from_underly), + TyTy::TyWithLocation (to_underly), false); + if (res.is_error ()) + { + // this needs to be handled by coercion logic + return TypeCoercionRules::CoercionResult::get_error (); + } + + // mutability must be coerceable TyTy::ReferenceType &f = static_cast<TyTy::ReferenceType &> (*from.get_ty ()); TyTy::ReferenceType &t @@ -337,7 +370,8 @@ TypeCastRules::check_ptr_ptr_cast () } void -TypeCastRules::emit_cast_error () const +TypeCastRules::emit_cast_error (location_t locus, TyTy::TyWithLocation from, + TyTy::TyWithLocation to) { rich_location r (line_table, locus); r.add_range (from.get_locus ()); diff --git a/gcc/rust/typecheck/rust-casts.h b/gcc/rust/typecheck/rust-casts.h index 0d6ed68..10bb006 100644 --- a/gcc/rust/typecheck/rust-casts.h +++ b/gcc/rust/typecheck/rust-casts.h @@ -30,15 +30,17 @@ class TypeCastRules public: static TypeCoercionRules::CoercionResult resolve (location_t locus, TyTy::TyWithLocation from, - TyTy::TyWithLocation to); + TyTy::TyWithLocation to, + bool emit_error = true); + + static void emit_cast_error (location_t locus, TyTy::TyWithLocation from, + TyTy::TyWithLocation to); protected: - TypeCoercionRules::CoercionResult check (); + TypeCoercionRules::CoercionResult check (bool emit_error); TypeCoercionRules::CoercionResult cast_rules (); TypeCoercionRules::CoercionResult check_ptr_ptr_cast (); - void emit_cast_error () const; - protected: TypeCastRules (location_t locus, TyTy::TyWithLocation from, TyTy::TyWithLocation to); diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc index 5905992..e027d9c 100644 --- a/gcc/rust/typecheck/rust-coercion.cc +++ b/gcc/rust/typecheck/rust-coercion.cc @@ -61,60 +61,21 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) // see: // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs - // handle never - // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155 if (receiver->get_kind () == TyTy::TypeKind::NEVER) { - // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound - // type variable, we want `?T` to fallback to `!` if not - // otherwise constrained. An example where this arises: - // - // let _: Option<?T> = Some({ return; }); - // - // here, we would coerce from `!` to `?T`. - if (expected->has_substitutions_defined () && !expected->is_concrete ()) - { - location_t locus = mappings.lookup_location (receiver->get_ref ()); - TyTy::TyVar implicit_var - = TyTy::TyVar::get_implicit_infer_var (locus); - try_result = CoercionResult{{}, implicit_var.get_tyty ()}; - return true; - } - else - { - bool expected_is_infer_var - = expected->get_kind () == TyTy::TypeKind::INFER; - bool expected_is_general_infer_var - = expected_is_infer_var - && (static_cast<TyTy::InferType *> (expected)->get_infer_kind () - == TyTy::InferType::InferTypeKind::GENERAL); - - // FIXME this 'expected_is_general_infer_var' case needs to eventually - // should go away see: compile/never_type_err1.rs - // - // I think we need inference obligations to say that yes we have a - // general inference variable but we add the oligation to the expected - // type that it could default to '!' - if (expected_is_general_infer_var) - try_result = CoercionResult{{}, receiver}; - else - try_result = CoercionResult{{}, expected->clone ()}; - - return true; - } + try_result = coerce_never (receiver); + return true; } // unsize - bool unsafe_error = false; - CoercionResult unsize_coercion - = coerce_unsized (receiver, expected, unsafe_error); - bool valid_unsize_coercion = !unsize_coercion.is_error (); - if (valid_unsize_coercion) + tl::expected<CoercionResult, CoerceUnsizedError> unsize_coercion + = coerce_unsized (receiver, expected); + if (unsize_coercion) { - try_result = unsize_coercion; + try_result = unsize_coercion.value (); return true; } - else if (unsafe_error) + else if (unsize_coercion.error () == CoerceUnsizedError::Unsafe) { // location_t lhs = mappings.lookup_location (receiver->get_ref ()); // location_t rhs = mappings.lookup_location (expected->get_ref ()); @@ -125,15 +86,16 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) // pointers switch (expected->get_kind ()) { - case TyTy::TypeKind::POINTER: { - TyTy::PointerType *ptr = static_cast<TyTy::PointerType *> (expected); + case TyTy::TypeKind::POINTER: + { + auto *ptr = expected->as<TyTy::PointerType> (); try_result = coerce_unsafe_ptr (receiver, ptr, ptr->mutability ()); return !try_result.is_error (); } - case TyTy::TypeKind::REF: { - TyTy::ReferenceType *ptr - = static_cast<TyTy::ReferenceType *> (expected); + case TyTy::TypeKind::REF: + { + auto *ptr = expected->as<TyTy::ReferenceType> (); try_result = coerce_borrowed_pointer (receiver, ptr, ptr->mutability ()); return !try_result.is_error (); @@ -147,7 +109,8 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L210 switch (receiver->get_kind ()) { - default: { + default: + { rust_debug ( "do_coercion default unify and infer expected: %s receiver %s", receiver->debug_str ().c_str (), expected->debug_str ().c_str ()); @@ -171,6 +134,44 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) } TypeCoercionRules::CoercionResult +TypeCoercionRules::coerce_never (TyTy::BaseType *receiver) +{ + // handle never + // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155 + + // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound + // type variable, we want `?T` to fallback to `!` if not + // otherwise constrained. An example where this arises: + // + // let _: Option<?T> = Some({ return; }); + // + // here, we would coerce from `!` to `?T`. + if (expected->has_substitutions_defined () && !expected->is_concrete ()) + { + location_t locus = mappings.lookup_location (receiver->get_ref ()); + TyTy::TyVar implicit_var = TyTy::TyVar::get_implicit_infer_var (locus); + return CoercionResult{{}, implicit_var.get_tyty ()}; + } + + bool expected_is_infer_var = expected->get_kind () == TyTy::TypeKind::INFER; + bool expected_is_general_infer_var + = expected_is_infer_var + && (static_cast<TyTy::InferType *> (expected)->get_infer_kind () + == TyTy::InferType::InferTypeKind::GENERAL); + + // FIXME this 'expected_is_general_infer_var' case needs to eventually + // should go away see: compile/never_type_err1.rs + // + // I think we need inference obligations to say that yes we have a + // general inference variable but we add the oligation to the expected + // type that it could default to '!' + if (expected_is_general_infer_var) + return CoercionResult{{}, receiver}; + else + return CoercionResult{{}, expected->clone ()}; +} + +TypeCoercionRules::CoercionResult TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver, TyTy::PointerType *expected, Mutability to_mutbl) @@ -182,7 +183,8 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver, TyTy::BaseType *element = nullptr; switch (receiver->get_kind ()) { - case TyTy::TypeKind::REF: { + case TyTy::TypeKind::REF: + { TyTy::ReferenceType *ref = static_cast<TyTy::ReferenceType *> (receiver); from_mutbl = ref->mutability (); @@ -190,16 +192,19 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver, } break; - case TyTy::TypeKind::POINTER: { + case TyTy::TypeKind::POINTER: + { TyTy::PointerType *ref = static_cast<TyTy::PointerType *> (receiver); from_mutbl = ref->mutability (); element = ref->get_base (); } break; - default: { - // FIXME this can probably turn into a unify_and - if (receiver->can_eq (expected, false)) + default: + { + if (types_compatable (TyTy::TyWithLocation (receiver), + TyTy::TyWithLocation (expected), UNKNOWN_LOCATION, + false)) return CoercionResult{{}, expected->clone ()}; return CoercionResult::get_error (); @@ -264,17 +269,13 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver, Mutability from_mutbl = Mutability::Imm; switch (receiver->get_kind ()) { - case TyTy::TypeKind::REF: { - TyTy::ReferenceType *from - = static_cast<TyTy::ReferenceType *> (receiver); - from_mutbl = from->mutability (); + case TyTy::TypeKind::REF: + { + from_mutbl = receiver->as<TyTy::ReferenceType> ()->mutability (); } break; - - default: { - // FIXME - // we might be able to replace this with a can_eq because we default - // back to a final unity anyway + default: + { rust_debug ("coerce_borrowed_pointer -- unify"); TyTy::BaseType *result = unify_site_and (receiver->get_ref (), @@ -312,9 +313,10 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver, // &[T; n] or &mut [T; n] -> &[T] // or &mut [T; n] -> &mut [T] // or &Concrete -> &Trait, etc. -TypeCoercionRules::CoercionResult +tl::expected<TypeCoercionRules::CoercionResult, + TypeCoercionRules::CoerceUnsizedError> TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, - TyTy::BaseType *target, bool &unsafe_error) + TyTy::BaseType *target) { rust_debug ("coerce_unsized(source={%s}, target={%s})", source->debug_str ().c_str (), target->debug_str ().c_str ()); @@ -338,11 +340,11 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, Mutability to_mutbl = target_ref->mutability (); if (!coerceable_mutability (from_mutbl, to_mutbl)) { - unsafe_error = true; location_t lhs = mappings.lookup_location (source->get_ref ()); location_t rhs = mappings.lookup_location (target->get_ref ()); mismatched_mutability_error (locus, lhs, rhs); - return TypeCoercionRules::CoercionResult::get_error (); + return tl::unexpected<CoerceUnsizedError> ( + CoerceUnsizedError::Unsafe); } ty_a = source_ref->get_base (); @@ -350,8 +352,8 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, needs_reborrow = true; expected_mutability = to_mutbl; - adjustments.push_back ( - Adjustment (Adjustment::AdjustmentType::INDIRECTION, source_ref, ty_a)); + adjustments.emplace_back (Adjustment::AdjustmentType::INDIRECTION, + source_ref, ty_a); } else if (source_is_ref && target_is_ptr) { @@ -363,11 +365,11 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, Mutability to_mutbl = target_ref->mutability (); if (!coerceable_mutability (from_mutbl, to_mutbl)) { - unsafe_error = true; location_t lhs = mappings.lookup_location (source->get_ref ()); location_t rhs = mappings.lookup_location (target->get_ref ()); mismatched_mutability_error (locus, lhs, rhs); - return TypeCoercionRules::CoercionResult::get_error (); + return tl::unexpected<CoerceUnsizedError> ( + CoerceUnsizedError::Unsafe); } ty_a = source_ref->get_base (); @@ -375,8 +377,8 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, needs_reborrow = true; expected_mutability = to_mutbl; - adjustments.push_back ( - Adjustment (Adjustment::AdjustmentType::INDIRECTION, source_ref, ty_a)); + adjustments.emplace_back (Adjustment::AdjustmentType::INDIRECTION, + source_ref, ty_a); } // FIXME @@ -393,19 +395,16 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, if (expect_dyn && need_unsize) { - bool bounds_compatible = b->bounds_compatible (*a, locus, true); + bool bounds_compatible = b->bounds_compatible (*a, locus, false); if (!bounds_compatible) - { - unsafe_error = true; - return TypeCoercionRules::CoercionResult::get_error (); - } + return tl::unexpected<CoerceUnsizedError> (CoerceUnsizedError::Unsafe); // return the unsize coercion TyTy::BaseType *result = b->clone (); // result->set_ref (a->get_ref ()); // append a dyn coercion adjustment - adjustments.push_back (Adjustment (Adjustment::UNSIZE, a, result)); + adjustments.emplace_back (Adjustment::UNSIZE, a, result); // reborrow if needed if (needs_reborrow) @@ -418,7 +417,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, Adjustment::AdjustmentType borrow_type = expected_mutability == Mutability::Imm ? Adjustment::IMM_REF : Adjustment::MUT_REF; - adjustments.push_back (Adjustment (borrow_type, result, reborrow)); + adjustments.emplace_back (borrow_type, result, reborrow); result = reborrow; } @@ -426,7 +425,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, } adjustments.clear (); - return TypeCoercionRules::CoercionResult::get_error (); + return tl::unexpected<CoerceUnsizedError> (CoerceUnsizedError::Regular); } bool @@ -440,7 +439,8 @@ TypeCoercionRules::select (TyTy::BaseType &autoderefed) = unify_site_and (autoderefed.get_ref (), TyTy::TyWithLocation (expected), TyTy::TyWithLocation (&autoderefed), UNDEF_LOCATION /* locus */, false /*emit_errors*/, - false /*commit_if_ok*/, true /*infer*/, true /*cleanup*/); + !try_flag /*commit_if_ok*/, try_flag /*infer*/, + try_flag /*cleanup*/); bool ok = result->get_kind () != TyTy::TypeKind::ERROR; if (!ok) return false; diff --git a/gcc/rust/typecheck/rust-coercion.h b/gcc/rust/typecheck/rust-coercion.h index b268966..864f48a 100644 --- a/gcc/rust/typecheck/rust-coercion.h +++ b/gcc/rust/typecheck/rust-coercion.h @@ -21,6 +21,7 @@ #include "rust-autoderef.h" #include "rust-hir-type-check.h" +#include "expected.h" namespace Rust { namespace Resolver { @@ -28,6 +29,12 @@ namespace Resolver { class TypeCoercionRules : protected AutoderefCycle { public: + enum class CoerceUnsizedError + { + Regular, + Unsafe + }; + struct CoercionResult { std::vector<Adjustment> adjustments; @@ -51,6 +58,7 @@ public: bool allow_autoderef, bool is_cast_site = false); + CoercionResult coerce_never (TyTy::BaseType *receiver); CoercionResult coerce_unsafe_ptr (TyTy::BaseType *receiver, TyTy::PointerType *expected, Mutability mutability); @@ -59,8 +67,8 @@ public: TyTy::ReferenceType *expected, Mutability mutability); - CoercionResult coerce_unsized (TyTy::BaseType *receiver, - TyTy::BaseType *expected, bool &unsafe_error); + tl::expected<CoercionResult, CoerceUnsizedError> + coerce_unsized (TyTy::BaseType *receiver, TyTy::BaseType *expected); static bool coerceable_mutability (Mutability from_mutbl, Mutability to_mutbl); diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc index c1165e9..296cc44 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.cc +++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc @@ -51,6 +51,9 @@ MethodResolver::Select (std::set<MethodCandidate> &candidates, { TyTy::BaseType *candidate_type = candidate.candidate.ty; rust_assert (candidate_type->get_kind () == TyTy::TypeKind::FNDEF); + if (candidate_type == nullptr + || candidate_type->get_kind () != TyTy::TypeKind::FNDEF) + continue; TyTy::FnType &fn = *static_cast<TyTy::FnType *> (candidate_type); // match the number of arguments @@ -102,26 +105,16 @@ MethodResolver::try_hook (const TyTy::BaseType &r) } } -bool -MethodResolver::select (TyTy::BaseType &receiver) +std::vector<MethodResolver::impl_item_candidate> +MethodResolver::assemble_inherent_impl_candidates ( + const TyTy::BaseType &receiver) { - rust_debug ("MethodResolver::select reciever=[%s] path=[%s]", - receiver.debug_str ().c_str (), - segment_name.as_string ().c_str ()); - - struct impl_item_candidate - { - HIR::Function *item; - HIR::ImplBlock *impl_block; - TyTy::FnType *ty; - }; - + std::vector<impl_item_candidate> inherent_impl_fns; const TyTy::BaseType *raw = receiver.destructure (); bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER; bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF; - // assemble inherent impl items - std::vector<impl_item_candidate> inherent_impl_fns; + // Assemble inherent impl items (non-trait impl blocks) mappings.iterate_impl_items ( [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool { bool is_trait_impl = impl->has_trait_ref (); @@ -146,11 +139,11 @@ MethodResolver::select (TyTy::BaseType &receiver) TyTy::BaseType *ty = nullptr; if (!query_type (func->get_mappings ().get_hirid (), &ty)) return true; - rust_assert (ty != nullptr); - if (ty->get_kind () == TyTy::TypeKind::ERROR) + if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR) + return true; + if (ty->get_kind () != TyTy::TypeKind::FNDEF) return true; - rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); const TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl); @@ -185,21 +178,24 @@ MethodResolver::select (TyTy::BaseType &receiver) return true; } - inherent_impl_fns.push_back ({func, impl, fnty}); + inherent_impl_fns.emplace_back (func, impl, fnty); return true; }); - struct trait_item_candidate - { - const HIR::TraitItemFunc *item; - const HIR::Trait *trait; - TyTy::FnType *ty; - const TraitReference *reference; - const TraitItemReference *item_ref; - }; + return inherent_impl_fns; +} + +void +MethodResolver::assemble_trait_impl_candidates ( + const TyTy::BaseType &receiver, + std::vector<impl_item_candidate> &impl_candidates, + std::vector<trait_item_candidate> &trait_candidates) +{ + const TyTy::BaseType *raw = receiver.destructure (); + bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER; + bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF; - std::vector<trait_item_candidate> trait_fns; mappings.iterate_impl_blocks ([&] (HirId id, HIR::ImplBlock *impl) mutable -> bool { bool is_trait_impl = impl->has_trait_ref (); @@ -227,10 +223,11 @@ MethodResolver::select (TyTy::BaseType &receiver) TyTy::BaseType *ty = nullptr; if (!query_type (func->get_mappings ().get_hirid (), &ty)) continue; - if (ty->get_kind () == TyTy::TypeKind::ERROR) + if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR) + continue; + if (ty->get_kind () != TyTy::TypeKind::FNDEF) continue; - rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); const TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl); @@ -266,7 +263,7 @@ MethodResolver::select (TyTy::BaseType &receiver) continue; } - inherent_impl_fns.push_back ({func, impl, fnty}); + impl_candidates.emplace_back (func, impl, fnty); return true; } @@ -289,35 +286,25 @@ MethodResolver::select (TyTy::BaseType &receiver) return true; TyTy::BaseType *ty = item_ref->get_tyty (); - rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF); + if (ty == nullptr || ty->get_kind () != TyTy::TypeKind::FNDEF) + return true; TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); - trait_item_candidate candidate{func, trait, fnty, trait_ref, item_ref}; - trait_fns.push_back (candidate); + trait_candidates.emplace_back (func, trait, fnty, trait_ref, item_ref); return true; }); +} - // lookup specified bounds for an associated item - struct precdicate_candidate - { - TyTy::TypeBoundPredicateItem lookup; - TyTy::FnType *fntype; - }; - - // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694 - - rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, " - "predicate_items found {%lu}", - (unsigned long) inherent_impl_fns.size (), - (unsigned long) trait_fns.size (), - (unsigned long) predicate_items.size ()); - +bool +MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver) +{ bool found_possible_candidate = false; for (const auto &predicate : predicate_items) { const TyTy::FnType *fn = predicate.fntype; - rust_assert (fn->is_method ()); + if (!fn->is_method ()) + continue; TyTy::BaseType *fn_self = fn->get_self_type (); rust_debug ("dot-operator predicate fn_self={%s} can_eq receiver={%s}", @@ -346,60 +333,34 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - if (found_possible_candidate) - { - return true; - } + return found_possible_candidate; +} - for (auto &impl_item : inherent_impl_fns) +bool +MethodResolver::try_select_inherent_impl_candidates ( + TyTy::BaseType &receiver, const std::vector<impl_item_candidate> &candidates, + bool trait_impl_blocks_only) +{ + bool found_possible_candidate = false; + for (auto &impl_item : candidates) { bool is_trait_impl_block = impl_item.impl_block->has_trait_ref (); - if (is_trait_impl_block) + if (trait_impl_blocks_only && !is_trait_impl_block) continue; - - TyTy::FnType *fn = impl_item.ty; - rust_assert (fn->is_method ()); - - TyTy::BaseType *fn_self = fn->get_self_type (); - rust_debug ("dot-operator impl_item fn_self={%s} can_eq receiver={%s}", - fn_self->debug_str ().c_str (), - receiver.debug_str ().c_str ()); - - auto res - = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION, - false /*allow-autoderef*/); - bool ok = !res.is_error (); - if (ok) - { - std::vector<Adjustment> adjs = append_adjustments (res.adjustments); - PathProbeCandidate::ImplItemCandidate c{impl_item.item, - impl_item.impl_block}; - auto try_result = MethodCandidate{ - PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC, - fn, impl_item.item->get_locus (), c), - adjs}; - result.insert (std::move (try_result)); - found_possible_candidate = true; - } - } - if (found_possible_candidate) - { - return true; - } - - for (auto &impl_item : inherent_impl_fns) - { - bool is_trait_impl_block = impl_item.impl_block->has_trait_ref (); - if (!is_trait_impl_block) + if (!trait_impl_blocks_only && is_trait_impl_block) continue; TyTy::FnType *fn = impl_item.ty; - rust_assert (fn->is_method ()); + if (!fn->is_method ()) + continue; TyTy::BaseType *fn_self = fn->get_self_type (); - rust_debug ( - "dot-operator trait_impl_item fn_self={%s} can_eq receiver={%s}", - fn_self->debug_str ().c_str (), receiver.debug_str ().c_str ()); + + const char *debug_prefix + = trait_impl_blocks_only ? "trait_impl_item" : "impl_item"; + rust_debug ("dot-operator %s fn_self={%s} can_eq receiver={%s}", + debug_prefix, fn_self->debug_str ().c_str (), + receiver.debug_str ().c_str ()); auto res = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION, @@ -418,15 +379,19 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - if (found_possible_candidate) - { - return true; - } + return found_possible_candidate; +} - for (auto trait_item : trait_fns) +bool +MethodResolver::try_select_trait_impl_candidates ( + TyTy::BaseType &receiver, const std::vector<trait_item_candidate> &candidates) +{ + bool found_possible_candidate = false; + for (auto trait_item : candidates) { TyTy::FnType *fn = trait_item.ty; - rust_assert (fn->is_method ()); + if (!fn->is_method ()) + continue; TyTy::BaseType *fn_self = fn->get_self_type (); rust_debug ("dot-operator trait_item fn_self={%s} can_eq receiver={%s}", @@ -451,10 +416,53 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - return found_possible_candidate; } +bool +MethodResolver::select (TyTy::BaseType &receiver) +{ + rust_debug ("MethodResolver::select reciever=[%s] path=[%s]", + receiver.debug_str ().c_str (), + segment_name.as_string ().c_str ()); + + // Assemble candidates + std::vector<impl_item_candidate> inherent_impl_fns + = assemble_inherent_impl_candidates (receiver); + std::vector<impl_item_candidate> trait_impl_fns; + std::vector<trait_item_candidate> trait_fns; + assemble_trait_impl_candidates (receiver, trait_impl_fns, trait_fns); + + // Combine inherent and trait impl functions + inherent_impl_fns.insert (inherent_impl_fns.end (), trait_impl_fns.begin (), + trait_impl_fns.end ()); + + // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694 + + rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, " + "predicate_items found {%lu}", + (unsigned long) inherent_impl_fns.size (), + (unsigned long) trait_fns.size (), + (unsigned long) predicate_items.size ()); + + // Try selection in the priority order defined by Rust's method resolution: + + // 1. Try predicate candidates first (highest priority) + if (try_select_predicate_candidates (receiver)) + return true; + + // 2. Try inherent impl functions (non-trait impl blocks) + if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, false)) + return true; + + // 3. Try inherent impl functions from trait impl blocks + if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, true)) + return true; + + // 4. Try trait functions (lowest priority) + return try_select_trait_impl_candidates (receiver, trait_fns); +} + std::vector<MethodResolver::predicate_candidate> MethodResolver::get_predicate_items ( const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver, @@ -463,20 +471,17 @@ MethodResolver::get_predicate_items ( std::vector<predicate_candidate> predicate_items; for (auto &bound : specified_bounds) { - TyTy::TypeBoundPredicateItem lookup + tl::optional<TyTy::TypeBoundPredicateItem> lookup = bound.lookup_associated_item (segment_name.as_string ()); - if (lookup.is_error ()) + if (!lookup.has_value ()) continue; - TyTy::BaseType *ty = lookup.get_tyty_for_receiver (&receiver); + TyTy::BaseType *ty = lookup->get_tyty_for_receiver (&receiver); if (ty->get_kind () == TyTy::TypeKind::FNDEF) { TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); if (fnty->is_method ()) - { - predicate_candidate candidate{lookup, fnty}; - predicate_items.push_back (candidate); - } + predicate_items.emplace_back (lookup.value (), fnty); } } diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h index ab95a5a..d2f11d1 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.h +++ b/gcc/rust/typecheck/rust-hir-dot-operator.h @@ -49,6 +49,10 @@ class MethodResolver : private TypeCheckBase, protected AutoderefCycle public: struct predicate_candidate { + predicate_candidate (TyTy::TypeBoundPredicateItem lookup, + TyTy::FnType *fntype) + : lookup (lookup), fntype (fntype) + {} TyTy::TypeBoundPredicateItem lookup; TyTy::FnType *fntype; }; @@ -65,6 +69,34 @@ public: const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver, const std::vector<TyTy::TypeBoundPredicate> &specified_bounds); + struct impl_item_candidate + { + impl_item_candidate (HIR::Function *item, HIR::ImplBlock *impl_block, + TyTy::FnType *ty) + : item (item), impl_block (impl_block), ty (ty) + {} + + HIR::Function *item; + HIR::ImplBlock *impl_block; + TyTy::FnType *ty; + }; + + struct trait_item_candidate + { + trait_item_candidate (const HIR::TraitItemFunc *item, + const HIR::Trait *trait, TyTy::FnType *ty, + const TraitReference *reference, + const TraitItemReference *item_ref) + : item (item), trait (trait), ty (ty), reference (reference), + item_ref (item_ref) + {} + const HIR::TraitItemFunc *item; + const HIR::Trait *trait; + TyTy::FnType *ty; + const TraitReference *reference; + const TraitItemReference *item_ref; + }; + protected: MethodResolver (bool autoderef_flag, const HIR::PathIdentSegment &segment_name); @@ -77,6 +109,25 @@ private: std::vector<Adjustment> append_adjustments (const std::vector<Adjustment> &adjustments) const; + std::vector<impl_item_candidate> + assemble_inherent_impl_candidates (const TyTy::BaseType &receiver); + + void assemble_trait_impl_candidates ( + const TyTy::BaseType &receiver, + std::vector<impl_item_candidate> &impl_candidates, + std::vector<trait_item_candidate> &trait_candidates); + + bool try_select_predicate_candidates (TyTy::BaseType &receiver); + + bool try_select_inherent_impl_candidates ( + TyTy::BaseType &receiver, + const std::vector<impl_item_candidate> &candidates, + bool trait_impl_blocks_only); + + bool try_select_trait_impl_candidates ( + TyTy::BaseType &receiver, + const std::vector<trait_item_candidate> &candidates); + private: // search const HIR::PathIdentSegment &segment_name; diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h index 5537b14..a66396f 100644 --- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h @@ -79,27 +79,29 @@ public: if (query == candidate) continue; - if (query->can_eq (candidate, false)) + if (!types_compatable (TyTy::TyWithLocation (query), + TyTy::TyWithLocation (candidate), + UNKNOWN_LOCATION, false)) + continue; + + // we might be in the case that we have: + // + // *const T vs *const [T] + // + // so lets use an equality check when the + // candidates are both generic to be sure we dont emit a false + // positive + + bool a = query->is_concrete (); + bool b = candidate->is_concrete (); + bool both_generic = !a && !b; + if (both_generic) { - // we might be in the case that we have: - // - // *const T vs *const [T] - // - // so lets use an equality check when the - // candidates are both generic to be sure we dont emit a false - // positive - - bool a = query->is_concrete (); - bool b = candidate->is_concrete (); - bool both_generic = !a && !b; - if (both_generic) - { - if (!query->is_equal (*candidate)) - continue; - } - - possible_collision (it->second, iy->second); + if (!query->is_equal (*candidate)) + continue; } + + possible_collision (it->second, iy->second); } } } diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc index 32e2399..59118e6 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.cc +++ b/gcc/rust/typecheck/rust-hir-path-probe.cc @@ -137,7 +137,7 @@ PathProbeCandidate::operator< (const PathProbeCandidate &c) const // PathProbeType -PathProbeType::PathProbeType (const TyTy::BaseType *receiver, +PathProbeType::PathProbeType (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query, DefId specific_trait_id) : TypeCheckBase (), receiver (receiver), search (query), @@ -145,7 +145,7 @@ PathProbeType::PathProbeType (const TyTy::BaseType *receiver, {} std::set<PathProbeCandidate> -PathProbeType::Probe (const TyTy::BaseType *receiver, +PathProbeType::Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name, bool probe_impls, bool probe_bounds, bool ignore_mandatory_trait_items, @@ -302,11 +302,10 @@ PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item, if (!query_type (impl_ty_id, &impl_block_ty)) return; - if (!receiver->can_eq (impl_block_ty, false)) - { - if (!impl_block_ty->can_eq (receiver, false)) - return; - } + if (!types_compatable (TyTy::TyWithLocation (receiver), + TyTy::TyWithLocation (impl_block_ty), + impl->get_locus (), false)) + return; // lets visit the impl_item item->accept_vis (*this); @@ -367,15 +366,15 @@ PathProbeType::process_predicate_for_candidates ( { const TraitReference *trait_ref = predicate.get (); - TyTy::TypeBoundPredicateItem item + tl::optional<TyTy::TypeBoundPredicateItem> item = predicate.lookup_associated_item (search.as_string ()); - if (item.is_error ()) + if (!item.has_value ()) return; - if (ignore_mandatory_trait_items && item.needs_implementation ()) + if (ignore_mandatory_trait_items && item->needs_implementation ()) return; - const TraitItemReference *trait_item_ref = item.get_raw_item (); + const TraitItemReference *trait_item_ref = item->get_raw_item (); PathProbeCandidate::CandidateType candidate_type; switch (trait_item_ref->get_trait_item_type ()) { @@ -395,9 +394,9 @@ PathProbeType::process_predicate_for_candidates ( break; } - TyTy::BaseType *trait_item_tyty = item.get_raw_item ()->get_tyty (); + TyTy::BaseType *trait_item_tyty = item->get_raw_item ()->get_tyty (); if (receiver->get_kind () != TyTy::DYNAMIC) - trait_item_tyty = item.get_tyty_for_receiver (receiver); + trait_item_tyty = item->get_tyty_for_receiver (receiver); PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref, trait_item_ref, @@ -425,10 +424,10 @@ PathProbeType::union_bounds ( } std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set; + for (auto it = mapper.begin (); it != mapper.end (); it++) - { - union_set.push_back ({it->second.first, it->second.second}); - } + union_set.emplace_back (it->second.first, it->second.second); + return union_set; } @@ -443,7 +442,7 @@ PathProbeType::is_receiver_generic () const // PathProbImplTrait -PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver, +PathProbeImplTrait::PathProbeImplTrait (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query, const TraitReference *trait_reference) : PathProbeType (receiver, query, UNKNOWN_DEFID), @@ -451,7 +450,7 @@ PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver, {} std::set<PathProbeCandidate> -PathProbeImplTrait::Probe (const TyTy::BaseType *receiver, +PathProbeImplTrait::Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name, const TraitReference *trait_reference) { diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index 59ffeb1..936bcb9 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -108,9 +108,8 @@ class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor { public: static std::set<PathProbeCandidate> - Probe (const TyTy::BaseType *receiver, - const HIR::PathIdentSegment &segment_name, bool probe_impls, - bool probe_bounds, bool ignore_mandatory_trait_items, + Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name, + bool probe_impls, bool probe_bounds, bool ignore_mandatory_trait_items, DefId specific_trait_id = UNKNOWN_DEFID); void visit (HIR::TypeAlias &alias) override; @@ -135,8 +134,8 @@ protected: bool ignore_mandatory_trait_items); protected: - PathProbeType (const TyTy::BaseType *receiver, - const HIR::PathIdentSegment &query, DefId specific_trait_id); + PathProbeType (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query, + DefId specific_trait_id); std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_bounds ( @@ -147,7 +146,7 @@ protected: bool is_receiver_generic () const; - const TyTy::BaseType *receiver; + TyTy::BaseType *receiver; const HIR::PathIdentSegment &search; std::set<PathProbeCandidate> candidates; HIR::ImplBlock *current_impl; @@ -178,12 +177,11 @@ class PathProbeImplTrait : public PathProbeType { public: static std::set<PathProbeCandidate> - Probe (const TyTy::BaseType *receiver, - const HIR::PathIdentSegment &segment_name, + Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name, const TraitReference *trait_reference); private: - PathProbeImplTrait (const TyTy::BaseType *receiver, + PathProbeImplTrait (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query, const TraitReference *trait_reference); diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc index 83985f0..74856f0 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.cc +++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc @@ -342,7 +342,15 @@ TraitReference::on_resolved () { for (auto &item : item_refs) { - item.on_resolved (); + if (item.get_trait_item_type () + == TraitItemReference::TraitItemType::TYPE) + item.on_resolved (); + } + for (auto &item : item_refs) + { + if (item.get_trait_item_type () + != TraitItemReference::TraitItemType::TYPE) + item.on_resolved (); } } @@ -424,7 +432,13 @@ TraitReference::trait_has_generics () const return !trait_substs.empty (); } -std::vector<TyTy::SubstitutionParamMapping> +std::vector<TyTy::SubstitutionParamMapping> & +TraitReference::get_trait_substs () +{ + return trait_substs; +} + +const std::vector<TyTy::SubstitutionParamMapping> & TraitReference::get_trait_substs () const { return trait_substs; diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h index 8b1ac7d..473513e 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.h +++ b/gcc/rust/typecheck/rust-hir-trait-reference.h @@ -224,7 +224,9 @@ public: bool trait_has_generics () const; - std::vector<TyTy::SubstitutionParamMapping> get_trait_substs () const; + std::vector<TyTy::SubstitutionParamMapping> &get_trait_substs (); + + const std::vector<TyTy::SubstitutionParamMapping> &get_trait_substs () const; bool satisfies_bound (const TraitReference &reference) const; diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index e4a61bd..03121d1 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -22,9 +22,6 @@ #include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" -// used for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Resolver { @@ -123,28 +120,16 @@ bool TraitResolver::resolve_path_to_trait (const HIR::TypePath &path, HIR::Trait **resolved) const { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + NodeId ref; - bool ok; - if (flag_name_resolution_2_0) + if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ())) { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ()); - - if ((ok = ref_opt.has_value ())) - ref = *ref_opt; + ref = *ref_opt; } else { - auto path_nodeid = path.get_mappings ().get_nodeid (); - ok = resolver->lookup_resolved_type (path_nodeid, &ref) - || resolver->lookup_resolved_name (path_nodeid, &ref) - || resolver->lookup_resolved_macro (path_nodeid, &ref); - } - - if (!ok) - { rust_error_at (path.get_locus (), "Failed to resolve path to node-id"); return false; } @@ -157,7 +142,13 @@ TraitResolver::resolve_path_to_trait (const HIR::TypePath &path, } auto resolved_item = mappings.lookup_hir_item (hid.value ()); - rust_assert (resolved_item.has_value ()); + if (!resolved_item.has_value ()) + { + rust_error_at (path.get_locus (), + "Failed to resolve trait by looking up hir node"); + return false; + } + if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait) { rich_location r (line_table, path.get_locus ()); @@ -218,7 +209,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) // handling. break; - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { auto &typaram = static_cast<HIR::TypeParam &> (*generic_param); bool is_self = typaram.get_type_representation ().as_string ().compare ("Self") @@ -228,10 +220,11 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) // The one exception is the implicit Self type of a trait bool apply_sized = !is_self; auto param_type - = TypeResolveGenericParam::Resolve (*generic_param, apply_sized); + = TypeResolveGenericParam::Resolve (*generic_param, true, + apply_sized); + context->insert_type (generic_param->get_mappings (), param_type); - substitutions.push_back ( - TyTy::SubstitutionParamMapping (typaram, param_type)); + substitutions.emplace_back (typaram, param_type); if (is_self) { @@ -253,17 +246,17 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) // copy the substitition mappings std::vector<TyTy::SubstitutionParamMapping> self_subst_copy; + self_subst_copy.reserve (substitutions.size ()); + for (auto &sub : substitutions) self_subst_copy.push_back (sub.clone ()); // They also inherit themselves as a bound this enables a trait item to // reference other Self::trait_items - auto self_hrtb - = TyTy::TypeBoundPredicate (trait_reference->get_mappings ().get_defid (), - std::move (self_subst_copy), - BoundPolarity::RegularBound, - trait_reference->get_locus ()); - specified_bounds.push_back (self_hrtb); + specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (), + std::move (self_subst_copy), + BoundPolarity::RegularBound, + trait_reference->get_locus ()); // look for any std::vector<TyTy::TypeBoundPredicate> super_traits; @@ -279,7 +272,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) auto predicate = get_predicate_from_bound ( b->get_path (), - tl::nullopt /*this will setup a PLACEHOLDER for self*/); + tl::nullopt /*this will setup a PLACEHOLDER for self*/, + BoundPolarity::RegularBound, false, true); if (predicate.is_error ()) return &TraitReference::error_node (); @@ -296,6 +290,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) { // make a copy of the substs std::vector<TyTy::SubstitutionParamMapping> item_subst; + item_subst.reserve (substitutions.size ()); + for (auto &sub : substitutions) item_subst.push_back (sub.clone ()); @@ -376,7 +372,26 @@ TraitItemReference::resolve_item (HIR::TraitItemType &type) void TraitItemReference::resolve_item (HIR::TraitItemConst &constant) { - // TODO + TyTy::BaseType *ty = nullptr; + if (constant.has_type ()) + ty = TypeCheckType::Resolve (constant.get_type ()); + + TyTy::BaseType *expr = nullptr; + if (constant.has_expr ()) + expr = TypeCheckExpr::Resolve (constant.get_expr ()); + + bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> (); + bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> (); + + if (have_specified_ty && have_expr_ty) + { + coercion_site (constant.get_mappings ().get_hirid (), + TyTy::TyWithLocation (ty, + constant.get_type ().get_locus ()), + TyTy::TyWithLocation (expr, + constant.get_expr ().get_locus ()), + constant.get_locus ()); + } } void @@ -416,11 +431,27 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty) const { rust_assert (get_trait_item_type () == TraitItemType::TYPE); + // this isnt super safe there are cases like the FnTraits where the type is + // set to the impls placeholder associated type. For example + // + // type Output = F::Output; -- see the fn trait impls in libcore + // + // then this projection ends up resolving back to this placeholder so it just + // ends up being cyclical + TyTy::BaseType *item_ty = get_tyty (); rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER); TyTy::PlaceholderType *placeholder = static_cast<TyTy::PlaceholderType *> (item_ty); + if (ty->is<TyTy::ProjectionType> ()) + { + const auto &projection = *static_cast<const TyTy::ProjectionType *> (ty); + const auto resolved = projection.get (); + if (resolved == item_ty) + return; + } + placeholder->set_associated_type (ty->get_ty_ref ()); } @@ -516,15 +547,16 @@ AssociatedImplTrait::setup_associated_types ( // handling. break; - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { TyTy::BaseType *l = nullptr; bool ok = context->lookup_type ( generic_param->get_mappings ().get_hirid (), &l); if (ok && l->get_kind () == TyTy::TypeKind::PARAM) { - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast<HIR::TypeParam &> (*generic_param), - static_cast<TyTy::ParamType *> (l))); + substitutions.emplace_back (static_cast<HIR::TypeParam &> ( + *generic_param), + static_cast<TyTy::ParamType *> (l)); } } break; @@ -548,14 +580,13 @@ AssociatedImplTrait::setup_associated_types ( if (p.needs_substitution () && infer) { TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus); - subst_args.push_back ( - TyTy::SubstitutionArg (&p, infer_var.get_tyty ())); + subst_args.emplace_back (&p, infer_var.get_tyty ()); } else { - TyTy::ParamType *param = p.get_param_ty (); - TyTy::BaseType *resolved = param->destructure (); - subst_args.push_back (TyTy::SubstitutionArg (&p, resolved)); + auto param = p.get_param_ty (); + auto resolved = param->destructure (); + subst_args.emplace_back (&p, resolved); param_mappings[param->get_symbol ()] = resolved->get_ref (); } } @@ -582,8 +613,8 @@ AssociatedImplTrait::setup_associated_types ( if (i == 0) continue; - const TyTy::ParamType *p = arg.get_param_ty (); - TyTy::BaseType *r = p->resolve (); + const auto p = arg.get_param_ty (); + auto r = p->resolve (); if (!r->is_concrete ()) { r = SubstMapperInternal::Resolve (r, infer_arguments); @@ -599,8 +630,8 @@ AssociatedImplTrait::setup_associated_types ( if (i == 0) continue; - const TyTy::ParamType *p = arg.get_param_ty (); - TyTy::BaseType *r = p->resolve (); + const auto p = arg.get_param_ty (); + auto r = p->resolve (); if (!r->is_concrete ()) { r = SubstMapperInternal::Resolve (r, infer_arguments); @@ -726,7 +757,8 @@ TraitItemReference::is_object_safe () const // https://doc.rust-lang.org/reference/items/traits.html#object-safety switch (get_trait_item_type ()) { - case TraitItemReference::TraitItemType::FN: { + case TraitItemReference::TraitItemType::FN: + { // lets be boring and just check that this is indeed a method will do // for now const HIR::TraitItem *item = get_hir_trait_item (); diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h index 82333f1..392ff20 100644 --- a/gcc/rust/typecheck/rust-hir-type-bounds.h +++ b/gcc/rust/typecheck/rust-hir-type-bounds.h @@ -30,21 +30,25 @@ class TypeBoundsProbe : public TypeCheckBase { public: static std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> - Probe (const TyTy::BaseType *receiver); + Probe (TyTy::BaseType *receiver); static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver, TraitReference *ref); private: void scan (); - void assemble_sized_builtin (); + bool + process_impl_block (HirId id, HIR::ImplBlock *impl, + std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>> + &possible_trait_paths); + void assemble_marker_builtins (); void add_trait_bound (HIR::Trait *trait); void assemble_builtin_candidate (LangItem::Kind item); private: - TypeBoundsProbe (const TyTy::BaseType *receiver); + TypeBoundsProbe (TyTy::BaseType *receiver); - const TyTy::BaseType *receiver; + TyTy::BaseType *receiver; std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> trait_references; }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 34a726c..f878720 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -17,31 +17,48 @@ // <http://www.gnu.org/licenses/>. #include "rust-hir-type-check-base.h" +#include "rust-compile-base.h" +#include "rust-hir-item.h" #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-type.h" #include "rust-hir-trait-resolve.h" #include "rust-type-util.h" #include "rust-attribute-values.h" +#include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Resolver { TypeCheckBase::TypeCheckBase () - : mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()), - context (TypeCheckContext::get ()) + : mappings (Analysis::Mappings::get ()), context (TypeCheckContext::get ()) {} +void +TypeCheckBase::ResolveGenericParams ( + const HIR::Item::ItemKind item_kind, location_t item_locus, + const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params, + std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign, + ABI abi) +{ + TypeCheckBase ctx; + ctx.resolve_generic_params (item_kind, item_locus, generic_params, + substitutions, is_foreign, abi); +} + static void walk_types_to_constrain (std::set<HirId> &constrained_symbols, const TyTy::SubstitutionArgumentMappings &constraints) { for (const auto &c : constraints.get_mappings ()) { - const TyTy::BaseType *arg = c.get_tyty (); + auto arg = c.get_tyty (); if (arg != nullptr) { - const TyTy::BaseType *p = arg->get_root (); + const auto p = arg->get_root (); + constrained_symbols.insert (p->get_ref ()); constrained_symbols.insert (p->get_ty_ref ()); + if (p->has_substitutions_defined ()) { walk_types_to_constrain (constrained_symbols, @@ -51,12 +68,89 @@ walk_types_to_constrain (std::set<HirId> &constrained_symbols, } } +static void +walk_type_to_constrain (std::set<HirId> &constrained_symbols, TyTy::BaseType &r) +{ + switch (r.get_kind ()) + { + case TyTy::TypeKind::POINTER: + { + auto &p = static_cast<TyTy::PointerType &> (r); + walk_type_to_constrain (constrained_symbols, *p.get_base ()); + } + break; + case TyTy::TypeKind::REF: + { + auto &ref = static_cast<TyTy::ReferenceType &> (r); + walk_type_to_constrain (constrained_symbols, *ref.get_base ()); + } + break; + case TyTy::TypeKind::ARRAY: + { + auto &arr = static_cast<TyTy::ArrayType &> (r); + walk_type_to_constrain (constrained_symbols, *arr.get_element_type ()); + } + break; + case TyTy::TypeKind::FNDEF: + { + auto &fn = static_cast<TyTy::FnType &> (r); + for (auto ¶m : fn.get_params ()) + walk_type_to_constrain (constrained_symbols, *param.get_type ()); + walk_type_to_constrain (constrained_symbols, *fn.get_return_type ()); + } + break; + case TyTy::TypeKind::PARAM: + { + auto ¶m = static_cast<TyTy::ParamType &> (r); + constrained_symbols.insert (param.get_ty_ref ()); + } + break; + case TyTy::SLICE: + { + auto &slice = static_cast<TyTy::SliceType &> (r); + walk_type_to_constrain (constrained_symbols, + *slice.get_element_type ()); + } + break; + case TyTy::FNPTR: + { + auto &ptr = static_cast<TyTy::FnPtr &> (r); + for (auto ¶m : ptr.get_params ()) + walk_type_to_constrain (constrained_symbols, *param.get_tyty ()); + walk_type_to_constrain (constrained_symbols, *ptr.get_return_type ()); + } + break; + case TyTy::TUPLE: + { + auto &tuple = static_cast<TyTy::TupleType &> (r); + for (auto &ty : tuple.get_fields ()) + walk_type_to_constrain (constrained_symbols, *ty.get_tyty ()); + } + break; + case TyTy::DYNAMIC: + { + auto &dyn = static_cast<TyTy::DynamicObjectType &> (r); + constrained_symbols.insert (dyn.get_ty_ref ()); + } + break; + case TyTy::CLOSURE: + { + auto &clos = static_cast<TyTy::ClosureType &> (r); + walk_type_to_constrain (constrained_symbols, clos.get_parameters ()); + walk_type_to_constrain (constrained_symbols, *clos.get_return_type ()); + } + break; + default: + break; + } +} + bool TypeCheckBase::check_for_unconstrained ( const std::vector<TyTy::SubstitutionParamMapping> ¶ms_to_constrain, const TyTy::SubstitutionArgumentMappings &constraint_a, const TyTy::SubstitutionArgumentMappings &constraint_b, - const TyTy::BaseType *reference) + TyTy::BaseType *reference) { bool check_result = false; bool check_completed @@ -72,21 +166,13 @@ TypeCheckBase::check_for_unconstrained ( HirId ref = p.get_param_ty ()->get_ref (); symbols_to_constrain.insert (ref); symbol_to_location.insert ({ref, p.get_param_locus ()}); - - rust_debug_loc (p.get_param_locus (), "XX constrain THIS"); } // set up the set of constrained symbols std::set<HirId> constrained_symbols; walk_types_to_constrain (constrained_symbols, constraint_a); walk_types_to_constrain (constrained_symbols, constraint_b); - - const auto root = reference->get_root (); - if (root->get_kind () == TyTy::TypeKind::PARAM) - { - const TyTy::ParamType *p = static_cast<const TyTy::ParamType *> (root); - constrained_symbols.insert (p->get_ty_ref ()); - } + walk_type_to_constrain (constrained_symbols, *reference); // check for unconstrained bool unconstrained = false; @@ -114,7 +200,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, TyTy::BaseType *infered = nullptr; switch (literal.get_lit_type ()) { - case HIR::Literal::LitType::INT: { + case HIR::Literal::LitType::INT: + { bool ok = false; switch (literal.get_type_hint ()) @@ -181,7 +268,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::FLOAT: { + case HIR::Literal::LitType::FLOAT: + { bool ok = false; switch (literal.get_type_hint ()) @@ -206,25 +294,29 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::BOOL: { + case HIR::Literal::LitType::BOOL: + { auto ok = context->lookup_builtin ("bool", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::CHAR: { + case HIR::Literal::LitType::CHAR: + { auto ok = context->lookup_builtin ("char", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::BYTE: { + case HIR::Literal::LitType::BYTE: + { auto ok = context->lookup_builtin ("u8", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::STRING: { + case HIR::Literal::LitType::STRING: + { TyTy::BaseType *base = nullptr; auto ok = context->lookup_builtin ("str", &base); rust_assert (ok); @@ -236,7 +328,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::BYTE_STRING: { + case HIR::Literal::LitType::BYTE_STRING: + { /* This is an arraytype of u8 reference (&[u8;size]). It isn't in UTF-8, but really just a byte array. Code to construct the array reference copied from ArrayElemsValues and ArrayType. */ @@ -270,10 +363,21 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, crate_num), UNKNOWN_LOCAL_DEFID); - TyTy::ArrayType *array - = new TyTy::ArrayType (array_mapping.get_hirid (), locus, - *literal_capacity, - TyTy::TyVar (u8->get_ref ())); + auto ctx = Compile::Context::get (); + tree capacity = Compile::HIRCompileBase::query_compile_const_expr ( + ctx, expected_ty, *literal_capacity); + + HirId capacity_expr_id = literal_capacity->get_mappings ().get_hirid (); + auto capacity_expr + = new TyTy::ConstValueType (capacity, expected_ty, capacity_expr_id, + capacity_expr_id); + context->insert_type (literal_capacity->get_mappings (), + capacity_expr->as_base_type ()); + + TyTy::ArrayType *array = new TyTy::ArrayType ( + array_mapping.get_hirid (), locus, + TyTy::TyVar (capacity_expr->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (u8->get_ref ())); context->insert_type (array_mapping, array); infered = new TyTy::ReferenceType (expr_mappings.get_hirid (), @@ -298,7 +402,8 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) repr.pack = 0; repr.align = 0; - // FIXME handle repr types.... + // Default repr for enums is isize, but we now check for other repr in the + // attributes. bool ok = context->lookup_builtin ("isize", &repr.repr); rust_assert (ok); @@ -307,7 +412,7 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) bool is_repr = attr.get_path ().as_string () == Values::Attributes::REPR; if (is_repr && !attr.has_attr_input ()) { - rust_error_at (attr.get_locus (), "malformed %qs attribute", "repr"); + rust_error_at (attr.get_locus (), "malformed %<repr%> attribute"); continue; } @@ -316,7 +421,11 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) const AST::AttrInput &input = attr.get_attr_input (); bool is_token_tree = input.get_attr_input_type () == AST::AttrInput::AttrInputType::TOKEN_TREE; - rust_assert (is_token_tree); + if (!is_token_tree) + { + rust_error_at (attr.get_locus (), "malformed %<repr%> attribute"); + continue; + } const auto &option = static_cast<const AST::DelimTokenTree &> (input); AST::AttrInputMetaItemContainer *meta_items = option.parse_to_meta_item (); @@ -343,13 +452,29 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) // manually parsing the string "packed(2)" here. size_t oparen = inline_option.find ('(', 0); - bool is_pack = false, is_align = false; + bool is_pack = false; + bool is_align = false; + bool is_c = false; + bool is_integer = false; unsigned char value = 1; if (oparen == std::string::npos) { is_pack = inline_option.compare ("packed") == 0; is_align = inline_option.compare ("align") == 0; + is_c = inline_option.compare ("C") == 0; + is_integer = (inline_option.compare ("isize") == 0 + || inline_option.compare ("i8") == 0 + || inline_option.compare ("i16") == 0 + || inline_option.compare ("i32") == 0 + || inline_option.compare ("i64") == 0 + || inline_option.compare ("i128") == 0 + || inline_option.compare ("usize") == 0 + || inline_option.compare ("u8") == 0 + || inline_option.compare ("u16") == 0 + || inline_option.compare ("u32") == 0 + || inline_option.compare ("u64") == 0 + || inline_option.compare ("u128") == 0); } else @@ -369,9 +494,28 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) } if (is_pack) - repr.pack = value; + { + repr.repr_kind = TyTy::ADTType::ReprKind::PACKED; + repr.pack = value; + } else if (is_align) - repr.align = value; + { + repr.repr_kind = TyTy::ADTType::ReprKind::ALIGN; + repr.align = value; + } + else if (is_c) + { + repr.repr_kind = TyTy::ADTType::ReprKind::C; + } + else if (is_integer) + { + repr.repr_kind = TyTy::ADTType::ReprKind::INT; + bool ok = context->lookup_builtin (inline_option, &repr.repr); + if (!ok) + { + rust_error_at (attr.get_locus (), "Invalid repr type"); + } + } delete meta_items; @@ -386,32 +530,60 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) void TypeCheckBase::resolve_generic_params ( + const HIR::Item::ItemKind item_kind, location_t item_locus, const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params, - std::vector<TyTy::SubstitutionParamMapping> &substitutions) + std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign, + ABI abi) { for (auto &generic_param : generic_params) { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::LIFETIME: { + case HIR::GenericParam::GenericKind::LIFETIME: + { auto lifetime_param = static_cast<HIR::LifetimeParam &> (*generic_param); auto lifetime = lifetime_param.get_lifetime (); - rust_assert (lifetime.get_lifetime_type () - == AST::Lifetime::LifetimeType::NAMED); context->get_lifetime_resolver ().insert_mapping ( context->intern_lifetime (lifetime)); } - break; - case HIR::GenericParam::GenericKind::CONST: { + case HIR::GenericParam::GenericKind::CONST: + { + if (is_foreign && abi != Rust::ABI::INTRINSIC) + { + rust_error_at (generic_param->get_locus (), ErrorCode::E0044, + "foreign items may not have const parameters"); + } + auto ¶m = static_cast<HIR::ConstGenericParam &> (*generic_param); auto specified_type = TypeCheckType::Resolve (param.get_type ()); if (param.has_default_expression ()) { + switch (item_kind) + { + case HIR::Item::ItemKind::Struct: + case HIR::Item::ItemKind::Enum: + case HIR::Item::ItemKind::TypeAlias: + case HIR::Item::ItemKind::Trait: + case HIR::Item::ItemKind::Union: + break; + + default: + { + rich_location r (line_table, item_locus); + r.add_fixit_remove (param.get_locus ()); + rust_error_at ( + r, + "default values for const generic parameters are not " + "allowed here"); + } + break; + } + auto expr_type = TypeCheckExpr::Resolve (param.get_default_expression ()); @@ -421,23 +593,69 @@ TypeCheckBase::resolve_generic_params ( expr_type, param.get_default_expression ().get_locus ()), param.get_locus ()); + + // fold the default value + auto ctx = Compile::Context::get (); + auto &expr = param.get_default_expression (); + tree default_value + = Compile::HIRCompileBase::query_compile_const_expr ( + ctx, specified_type, expr); + + auto default_const_decl + = new TyTy::ConstValueType (default_value, specified_type, + expr.get_mappings ().get_hirid (), + expr.get_mappings ().get_hirid (), + {}); + + context->insert_type (expr.get_mappings (), default_const_decl); } - context->insert_type (generic_param->get_mappings (), - specified_type); + TyTy::BaseGeneric *const_decl + = new TyTy::ConstParamType (param.get_name (), param.get_locus (), + specified_type, + param.get_mappings ().get_hirid (), + param.get_mappings ().get_hirid (), + {}); + + context->insert_type (generic_param->get_mappings (), const_decl); + TyTy::SubstitutionParamMapping p (*generic_param, const_decl); + substitutions.push_back (p); } break; - case HIR::GenericParam::GenericKind::TYPE: { - auto param_type = TypeResolveGenericParam::Resolve (*generic_param); + case HIR::GenericParam::GenericKind::TYPE: + { + if (is_foreign && abi != Rust::ABI::INTRINSIC) + { + rust_error_at (generic_param->get_locus (), ErrorCode::E0044, + "foreign items may not have type parameters"); + } + + auto param_type = TypeResolveGenericParam::Resolve ( + *generic_param, false /*resolve_trait_bounds*/); context->insert_type (generic_param->get_mappings (), param_type); - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast<HIR::TypeParam &> (*generic_param), param_type)); + TyTy::SubstitutionParamMapping p (*generic_param, param_type); + substitutions.push_back (p); } break; } } + + // now walk them to setup any specified type param bounds + for (auto &subst : substitutions) + { + auto &generic = subst.get_generic_param (); + if (generic.get_kind () != HIR::GenericParam::GenericKind::TYPE) + continue; + + auto &type_param = static_cast<HIR::TypeParam &> (generic); + auto bpty = subst.get_param_ty (); + rust_assert (bpty->get_kind () == TyTy::TypeKind::PARAM); + auto pty = static_cast<TyTy::ParamType *> (bpty); + + TypeResolveGenericParam::ApplyAnyTraitBounds (type_param, pty); + } } TyTy::TypeBoundPredicate diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index 8a1bf6f..6430089 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -32,6 +32,12 @@ class TypeCheckBase public: virtual ~TypeCheckBase () {} + static void ResolveGenericParams ( + const HIR::Item::ItemKind item_kind, location_t item_locus, + const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params, + std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign, + ABI abi); + protected: TypeCheckBase (); @@ -41,13 +47,13 @@ protected: HIR::TypePath &path, tl::optional<std::reference_wrapper<HIR::Type>> associated_self, BoundPolarity polarity = BoundPolarity::RegularBound, - bool is_qualified_type = false); + bool is_qualified_type = false, bool is_super_trait = false); bool check_for_unconstrained ( const std::vector<TyTy::SubstitutionParamMapping> ¶ms_to_constrain, const TyTy::SubstitutionArgumentMappings &constraint_a, const TyTy::SubstitutionArgumentMappings &constraint_b, - const TyTy::BaseType *reference); + TyTy::BaseType *reference); TyTy::BaseType *resolve_literal (const Analysis::NodeMapping &mappings, HIR::Literal &literal, location_t locus); @@ -56,14 +62,15 @@ protected: location_t locus); void resolve_generic_params ( + const HIR::Item::ItemKind item_kind, location_t item_locus, const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params, - std::vector<TyTy::SubstitutionParamMapping> &substitutions); + std::vector<TyTy::SubstitutionParamMapping> &substitutions, + bool is_foreign = false, ABI abi = ABI::RUST); TyTy::TypeBoundPredicate get_marker_predicate (LangItem::Kind item_type, location_t locus); Analysis::Mappings &mappings; - Resolver *resolver; TypeCheckContext *context; }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc index c80a12f..23a8cca 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc @@ -23,9 +23,6 @@ #include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Resolver { @@ -79,25 +76,13 @@ TypeCheckEnumItem::visit (HIR::EnumItem &item) rust_assert (ok); context->insert_type (mapping, isize); - tl::optional<CanonicalPath> canonical_path; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); - } - else - { - canonical_path - = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path.has_value ()); + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); - RustIdent ident{*canonical_path, item.get_locus ()}; + RustIdent ident{canonical_path, item.get_locus ()}; variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), item.get_mappings ().get_defid (), item.get_identifier ().as_string (), ident, @@ -123,25 +108,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item) TyTy::TyWithLocation (expected_ty), TyTy::TyWithLocation (capacity_type), item.get_locus ()); - tl::optional<CanonicalPath> canonical_path; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); - } - else - { - canonical_path - = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path.has_value ()); + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); - RustIdent ident{*canonical_path, item.get_locus ()}; + RustIdent ident{canonical_path, item.get_locus ()}; variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), item.get_mappings ().get_defid (), @@ -185,25 +158,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemTuple &item) rust_assert (ok); context->insert_type (mapping, isize); - tl::optional<CanonicalPath> canonical_path; + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); - } - else - { - canonical_path - = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ()); - } - - rust_assert (canonical_path.has_value ()); + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); - RustIdent ident{*canonical_path, item.get_locus ()}; + RustIdent ident{canonical_path, item.get_locus ()}; variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), item.get_mappings ().get_defid (), item.get_identifier ().as_string (), ident, @@ -245,25 +206,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemStruct &item) rust_assert (ok); context->insert_type (mapping, isize); - tl::optional<CanonicalPath> canonical_path; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); - } - else - { - canonical_path - = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path.has_value ()); + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); - RustIdent ident{*canonical_path, item.get_locus ()}; + RustIdent ident{canonical_path, item.get_locus ()}; variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), item.get_mappings ().get_defid (), item.get_identifier ().as_string (), ident, diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index b7fdc13..1c00fd96 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -16,6 +16,9 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "optional.h" +#include "rust-common.h" +#include "rust-hir-expr.h" #include "rust-system.h" #include "rust-tyty-call.h" #include "rust-hir-type-check-struct-field.h" @@ -29,9 +32,10 @@ #include "rust-hir-type-check-item.h" #include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" - -// for flag_name_resolution_2_0 -#include "options.h" +#include "rust-compile-base.h" +#include "rust-tyty-util.h" +#include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Resolver { @@ -49,10 +53,32 @@ 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; +} + +TyTy::BaseType * +TypeCheckExpr::ResolveOpOverload (LangItem::Kind lang_item_type, + HIR::OperatorExprMeta expr, + TyTy::BaseType *lhs, TyTy::BaseType *rhs, + HIR::PathIdentSegment specified_segment) +{ + TypeCheckExpr resolver; + + resolver.resolve_operator_overload (lang_item_type, expr, lhs, rhs, + specified_segment); return resolver.infered; } @@ -109,7 +135,13 @@ TypeCheckExpr::visit (HIR::TupleIndexExpr &expr) } TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (resolved); - rust_assert (!adt->is_enum ()); + if (!adt->is_tuple_struct ()) + { + rust_error_at (expr.get_locus (), + "expected tuple or tuple struct, found %qs", + adt->get_name ().c_str ()); + return; + } rust_assert (adt->number_of_variants () == 1); TyTy::VariantDef *variant = adt->get_variants ().at (0); @@ -144,7 +176,7 @@ TypeCheckExpr::visit (HIR::TupleExpr &expr) for (auto &elem : expr.get_tuple_elems ()) { auto field_ty = TypeCheckExpr::Resolve (*elem); - fields.push_back (TyTy::TyVar (field_ty->get_ref ())); + fields.emplace_back (field_ty->get_ref ()); } infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), expr.get_locus (), fields); @@ -371,7 +403,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) switch (expr.get_expr_type ()) { case ArithmeticOrLogicalOperator::LEFT_SHIFT: - case ArithmeticOrLogicalOperator::RIGHT_SHIFT: { + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + { TyTy::TyWithLocation from (rhs, expr.get_rhs ().get_locus ()); TyTy::TyWithLocation to (lhs, expr.get_lhs ().get_locus ()); infered = cast_site (expr.get_mappings ().get_hirid (), from, to, @@ -379,7 +412,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) } break; - default: { + default: + { infered = unify_site ( expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()), @@ -468,7 +502,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr) // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators switch (expr.get_expr_type ()) { - case NegationOperator::NEGATE: { + case NegationOperator::NEGATE: + { bool valid = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) @@ -490,7 +525,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr) } break; - case NegationOperator::NOT: { + case NegationOperator::NOT: + { bool valid = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL) || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) @@ -609,10 +645,9 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) if (s->is_unit_check_needed () && !resolved->is_unit ()) { auto unit = TyTy::TupleType::get_unit_type (); - resolved - = unify_site (s->get_mappings ().get_hirid (), - TyTy::TyWithLocation (unit), - TyTy::TyWithLocation (resolved), s->get_locus ()); + unify_site (s->get_mappings ().get_hirid (), + TyTy::TyWithLocation (unit), + TyTy::TyWithLocation (resolved), s->get_locus ()); } } @@ -641,6 +676,26 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) } void +TypeCheckExpr::visit (HIR::AnonConst &expr) +{ + if (!expr.is_deferred ()) + { + infered = TypeCheckExpr::Resolve (expr.get_inner_expr ()); + return; + } + + TyTy::TyVar var + = TyTy::TyVar::get_implicit_const_infer_var (expr.get_locus ()); + infered = var.get_tyty (); +} + +void +TypeCheckExpr::visit (HIR::ConstBlock &expr) +{ + infered = TypeCheckExpr::Resolve (expr.get_const_expr ()); +} + +void TypeCheckExpr::visit (HIR::RangeFromToExpr &expr) { auto lang_item_type = LangItem::Kind::RANGE; @@ -683,7 +738,7 @@ TypeCheckExpr::visit (HIR::RangeFromToExpr &expr) // substitute it in std::vector<TyTy::SubstitutionArg> subst_mappings; const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); - subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified)); + subst_mappings.emplace_back (param_ref, unified); TyTy::SubstitutionArgumentMappings subst ( subst_mappings, {}, adt->get_substitution_arguments ().get_regions (), @@ -727,7 +782,7 @@ TypeCheckExpr::visit (HIR::RangeFromExpr &expr) // substitute it in std::vector<TyTy::SubstitutionArg> subst_mappings; const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); - subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty)); + subst_mappings.emplace_back (param_ref, from_ty); TyTy::SubstitutionArgumentMappings subst ( subst_mappings, {}, adt->get_substitution_arguments ().get_regions (), @@ -771,7 +826,7 @@ TypeCheckExpr::visit (HIR::RangeToExpr &expr) // substitute it in std::vector<TyTy::SubstitutionArg> subst_mappings; const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); - subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty)); + subst_mappings.emplace_back (param_ref, from_ty); TyTy::SubstitutionArgumentMappings subst ( subst_mappings, {}, adt->get_substitution_arguments ().get_regions (), @@ -788,38 +843,45 @@ typecheck_inline_asm_operand (HIR::InlineAsm &expr) { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { auto in = operand.get_in (); TypeCheckExpr::Resolve (*in.expr); break; } - case RegisterType::Out: { + case RegisterType::Out: + { auto out = operand.get_out (); TypeCheckExpr::Resolve (*out.expr); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { auto in_out = operand.get_in_out (); TypeCheckExpr::Resolve (*in_out.expr); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split_in_out = operand.get_split_in_out (); TypeCheckExpr::Resolve (*split_in_out.in_expr); TypeCheckExpr::Resolve (*split_in_out.out_expr); break; } - case RegisterType::Const: { + case RegisterType::Const: + { auto anon_const = operand.get_const ().anon_const; - TypeCheckExpr::Resolve (*anon_const.expr); + TypeCheckExpr::Resolve (anon_const.get_inner_expr ()); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { auto sym = operand.get_sym (); TypeCheckExpr::Resolve (*sym.expr); break; } - case RegisterType::Label: { + case RegisterType::Label: + { auto label = operand.get_label (); TypeCheckExpr::Resolve (*label.expr); break; @@ -835,13 +897,39 @@ TypeCheckExpr::visit (HIR::InlineAsm &expr) // NOTE: Hoise out if we have noreturn as an option // to return a never type // TODO : new keyword for memory seems sooooo shaky - if (expr.options.count (AST::InlineAsmOption::NORETURN) == 1) + if (expr.options.count (AST::InlineAsm::Option::NORETURN) == 1) infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); else infered = TyTy::TupleType::get_unit_type (); } void +TypeCheckExpr::visit (HIR::LlvmInlineAsm &expr) +{ + for (auto &i : expr.inputs) + TypeCheckExpr::Resolve (*i.expr); + + for (auto &o : expr.outputs) + TypeCheckExpr::Resolve (*o.expr); + + // Black box hint is unit type + infered = TyTy::TupleType::get_unit_type (); +} + +void +TypeCheckExpr::visit (HIR::OffsetOf &expr) +{ + TypeCheckType::Resolve (expr.get_type ()); + + // FIXME: Does offset_of always return a usize? + TyTy::BaseType *size_ty; + bool ok = context->lookup_builtin ("usize", &size_ty); + rust_assert (ok); + + infered = size_ty; +} + +void TypeCheckExpr::visit (HIR::RangeFullExpr &expr) { auto lang_item_type = LangItem::Kind::RANGE_FULL; @@ -911,7 +999,7 @@ TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr) // substitute it in std::vector<TyTy::SubstitutionArg> subst_mappings; const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); - subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified)); + subst_mappings.emplace_back (param_ref, unified); TyTy::SubstitutionArgumentMappings subst ( subst_mappings, {}, adt->get_substitution_arguments ().get_regions (), @@ -945,7 +1033,10 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr) bool ok = context->lookup_builtin ("usize", &size_ty); rust_assert (ok); - bool maybe_simple_array_access = index_expr_ty->can_eq (size_ty, false); + bool maybe_simple_array_access + = types_compatable (TyTy::TyWithLocation (index_expr_ty), + TyTy::TyWithLocation (size_ty), expr.get_locus (), + false); if (maybe_simple_array_access && direct_array_expr_ty->get_kind () == TyTy::TypeKind::ARRAY) { @@ -981,8 +1072,7 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr) rich_location r (line_table, expr.get_locus ()); r.add_range (expr.get_array_expr ().get_locus ()); r.add_range (expr.get_index_expr ().get_locus ()); - rust_error_at (r, ErrorCode::E0277, - "the type %qs cannot be indexed by %qs", + rust_error_at (r, ErrorCode::E0277, "the type %qs cannot be indexed by %qs", array_expr_ty->get_name ().c_str (), index_expr_ty->get_name ().c_str ()); } @@ -992,35 +1082,44 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) { auto &elements = expr.get_internal_elements (); + TyTy::BaseType *expected_ty = nullptr; + bool ok = context->lookup_builtin ("usize", &expected_ty); + rust_assert (ok); + HIR::Expr *capacity_expr = nullptr; TyTy::BaseType *element_type = nullptr; + TyTy::BaseType *capacity_type = nullptr; switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::COPIED: { + case HIR::ArrayElems::ArrayExprType::COPIED: + { HIR::ArrayElemsCopied &elems = static_cast<HIR::ArrayElemsCopied &> (elements); element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); - auto capacity_type + auto capacity_expr_ty = TypeCheckExpr::Resolve (elems.get_num_copies_expr ()); + if (capacity_expr_ty->is<TyTy::ErrorType> ()) + return; - TyTy::BaseType *expected_ty = nullptr; - bool ok = context->lookup_builtin ("usize", &expected_ty); - rust_assert (ok); context->insert_type (elems.get_num_copies_expr ().get_mappings (), expected_ty); - unify_site (expr.get_mappings ().get_hirid (), - TyTy::TyWithLocation (expected_ty), - TyTy::TyWithLocation ( - capacity_type, elems.get_num_copies_expr ().get_locus ()), - expr.get_locus ()); + auto result = unify_site ( + expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty), + TyTy::TyWithLocation (capacity_expr_ty, + elems.get_num_copies_expr ().get_locus ()), + expr.get_locus ()); + if (result->is<TyTy::ErrorType> ()) + return; capacity_expr = &elems.get_num_copies_expr (); + capacity_type = expected_ty; } break; - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { HIR::ArrayElemsValues &elems = static_cast<HIR::ArrayElemsValues &> (elements); @@ -1053,17 +1152,35 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) UNDEF_LOCATION, {}); // mark the type for this implicit node - TyTy::BaseType *expected_ty = nullptr; - bool ok = context->lookup_builtin ("usize", &expected_ty); - rust_assert (ok); context->insert_type (mapping, expected_ty); + capacity_type = expected_ty; } break; } - infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), - expr.get_locus (), *capacity_expr, - TyTy::TyVar (element_type->get_ref ())); + rust_assert (capacity_expr); + rust_assert (capacity_type); + auto ctx = Compile::Context::get (); + tree capacity_value + = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type, + *capacity_expr); + + // Create ConstValueType with ref == ty_ref (both pointing to capacity_expr) + // ty_ref gets updated during substitution via set_ty_ref() + HirId capacity_expr_id = capacity_expr->get_mappings ().get_hirid (); + auto const_type + = new TyTy::ConstValueType (capacity_value, expected_ty, capacity_expr_id, + capacity_expr_id); + + // Insert the ConstValueType at its ref + context->insert_type (capacity_expr->get_mappings (), + const_type->as_base_type ()); + + infered + = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (), + TyTy::TyVar ( + const_type->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (element_type->get_ref ())); } // empty struct @@ -1127,33 +1244,119 @@ TypeCheckExpr::visit (HIR::FieldAccessExpr &expr) bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT; if (!is_valid_type) { - rust_error_at (expr.get_locus (), - "expected algebraic data type got: [%s]", - struct_base->as_string ().c_str ()); + rust_error_at (expr.get_locus (), "expected algebraic data type got %qs", + struct_base->get_name ().c_str ()); return; } TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_base); - rust_assert (!adt->is_enum ()); - rust_assert (adt->number_of_variants () == 1); - + rust_assert (adt->number_of_variants () > 0); TyTy::VariantDef *vaiant = adt->get_variants ().at (0); TyTy::StructFieldType *lookup = nullptr; bool found = vaiant->lookup_field (expr.get_field_name ().as_string (), &lookup, nullptr); - if (!found) + if (!found || adt->is_enum ()) { - rust_error_at (expr.get_locus (), ErrorCode::E0609, - "no field %qs on type %qs", + rich_location r (line_table, expr.get_locus ()); + r.add_range (expr.get_field_name ().get_locus ()); + rust_error_at (r, ErrorCode::E0609, "no field %qs on type %qs", expr.get_field_name ().as_string ().c_str (), - adt->as_string ().c_str ()); + adt->get_name ().c_str ()); return; } infered = lookup->get_field_type (); } +bool +is_default_fn (const MethodCandidate &candidate) +{ + if (candidate.candidate.is_impl_candidate ()) + { + auto *item = candidate.candidate.item.impl.impl_item; + + if (item->get_impl_item_type () == HIR::ImplItem::FUNCTION) + { + auto &fn = static_cast<HIR::Function &> (*item); + + return fn.is_default (); + } + } + + return false; +} + +void +emit_ambiguous_resolution_error (HIR::MethodCallExpr &expr, + std::set<MethodCandidate> &candidates) +{ + rich_location r (line_table, expr.get_method_name ().get_locus ()); + std::string rich_msg = "multiple " + + expr.get_method_name ().get_segment ().as_string () + + " found"; + + // We have to filter out default candidates + for (auto &c : candidates) + if (!is_default_fn (c)) + r.add_range (c.candidate.locus); + + r.add_fixit_replace (rich_msg.c_str ()); + + rust_error_at (r, ErrorCode::E0592, "duplicate definitions with name %qs", + expr.get_method_name ().get_segment ().as_string ().c_str ()); +} + +// We are allowed to have multiple candidates if they are all specializable +// functions or if all of them except one are specializable functions. +// In the later case, we just return a valid candidate without erroring out +// about ambiguity. If there are two or more specialized functions, then we +// error out. +// +// FIXME: The first case is not handled at the moment, so we error out +tl::optional<const MethodCandidate &> +handle_multiple_candidates (HIR::MethodCallExpr &expr, + std::set<MethodCandidate> &candidates) +{ + auto all_default = true; + tl::optional<const MethodCandidate &> found = tl::nullopt; + + for (auto &c : candidates) + { + if (!is_default_fn (c)) + { + all_default = false; + + // We haven't found a final candidate yet, so we can select + // this one. However, if we already have a candidate, then + // that means there are multiple non-default candidates - we + // must error out + if (!found) + { + found = c; + } + else + { + emit_ambiguous_resolution_error (expr, candidates); + return tl::nullopt; + } + } + } + + // None of the candidates were a non-default (specialized) function, so we + // error out + if (all_default) + { + rust_sorry_at (expr.get_locus (), + "cannot resolve method calls to non-specialized methods " + "(all function candidates are %qs)", + "default"); + return tl::nullopt; + } + + return found; +} + void TypeCheckExpr::visit (HIR::MethodCallExpr &expr) { @@ -1181,34 +1384,25 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr) return; } - if (candidates.size () > 1) - { - rich_location r (line_table, expr.get_method_name ().get_locus ()); - std::string rich_msg - = "multiple " + expr.get_method_name ().get_segment ().as_string () - + " found"; + tl::optional<const MethodCandidate &> candidate = *candidates.begin (); - for (auto &c : candidates) - r.add_range (c.candidate.locus); + if (candidates.size () > 1) + candidate = handle_multiple_candidates (expr, candidates); - r.add_fixit_replace (rich_msg.c_str ()); + if (!candidate) + return; - rust_error_at ( - r, ErrorCode::E0592, "duplicate definitions with name %qs", - expr.get_method_name ().get_segment ().as_string ().c_str ()); - return; - } + auto found_candidate = *candidate; - auto candidate = *candidates.begin (); rust_debug_loc (expr.get_method_name ().get_locus (), "resolved method to: {%u} {%s} with [%lu] adjustments", - candidate.candidate.ty->get_ref (), - candidate.candidate.ty->debug_str ().c_str (), - (unsigned long) candidate.adjustments.size ()); + found_candidate.candidate.ty->get_ref (), + found_candidate.candidate.ty->debug_str ().c_str (), + (unsigned long) found_candidate.adjustments.size ()); // Get the adjusted self Adjuster adj (receiver_tyty); - TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments); + TyTy::BaseType *adjusted_self = adj.adjust_type (found_candidate.adjustments); rust_debug ("receiver: %s adjusted self %s", receiver_tyty->debug_str ().c_str (), adjusted_self->debug_str ().c_str ()); @@ -1219,10 +1413,10 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr) HirId autoderef_mappings_id = expr.get_receiver ().get_mappings ().get_hirid (); context->insert_autoderef_mappings (autoderef_mappings_id, - std::move (candidate.adjustments)); + std::move (found_candidate.adjustments)); - PathProbeCandidate &resolved_candidate = candidate.candidate; - TyTy::BaseType *lookup_tyty = candidate.candidate.ty; + PathProbeCandidate &resolved_candidate = found_candidate.candidate; + TyTy::BaseType *lookup_tyty = found_candidate.candidate.ty; NodeId resolved_node_id = resolved_candidate.is_impl_candidate () ? resolved_candidate.item.impl.impl_item->get_impl_mappings () @@ -1249,8 +1443,8 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr) fn->prepare_higher_ranked_bounds (); rust_debug_loc (expr.get_locus (), "resolved method call to: {%u} {%s}", - candidate.candidate.ty->get_ref (), - candidate.candidate.ty->debug_str ().c_str ()); + found_candidate.candidate.ty->get_ref (), + found_candidate.candidate.ty->debug_str ().c_str ()); if (resolved_candidate.is_impl_candidate ()) { @@ -1316,26 +1510,11 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr) // store the expected fntype context->insert_type (expr.get_method_name ().get_mappings (), lookup); - if (flag_name_resolution_2_0) - { - auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( - Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); + auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( + Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); - nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()), - Resolver2_0::Definition (resolved_node_id)); - } - // set up the resolved name on the path - else if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node_id)) - { - resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (), - resolved_node_id); - } - else - { - resolver->insert_resolved_misc (expr.get_mappings ().get_nodeid (), - resolved_node_id); - } + nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()), + Resolver2_0::Definition (resolved_node_id)); // return the result of the function back infered = function_ret_tyty; @@ -1463,6 +1642,15 @@ TypeCheckExpr::visit (HIR::BorrowExpr &expr) } } + if (expr.is_raw_borrow ()) + { + infered = new TyTy::PointerType (expr.get_mappings ().get_hirid (), + TyTy::TyVar (resolved_base->get_ref ()), + expr.get_mut ()); + + return; + } + infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (), TyTy::TyVar (resolved_base->get_ref ()), expr.get_mut ()); @@ -1601,16 +1789,22 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr) void TypeCheckExpr::visit (HIR::ClosureExpr &expr) { - TypeCheckContextItem current_context = context->peek_context (); - TyTy::FnType *current_context_fndecl = current_context.get_context_type (); - + std::vector<TyTy::SubstitutionParamMapping> subst_refs; HirId ref = expr.get_mappings ().get_hirid (); DefId id = expr.get_mappings ().get_defid (); - RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()}; + RustIdent ident{CanonicalPath::create_empty (), expr.get_locus ()}; + + if (context->have_function_context ()) + { + TypeCheckContextItem current_context = context->peek_context (); + TyTy::FnType *current_context_fndecl + = current_context.get_context_type (); - // get from parent context - std::vector<TyTy::SubstitutionParamMapping> subst_refs - = current_context_fndecl->clone_substs (); + ident = RustIdent{current_context_fndecl->get_ident ().path, + expr.get_locus ()}; + + subst_refs = current_context_fndecl->clone_substs (); + } std::vector<TyTy::TyVar> parameter_types; for (auto &p : expr.get_params ()) @@ -1662,19 +1856,12 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr) // Resolve closure captures std::set<NodeId> captures; - if (flag_name_resolution_2_0) - { - auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( - Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); + auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( + Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); - if (auto opt_cap = nr_ctx.mappings.lookup_captures (closure_node_id)) - for (auto cap : opt_cap.value ()) - captures.insert (cap); - } - else - { - captures = resolver->get_captures (closure_node_id); - } + if (auto opt_cap = nr_ctx.mappings.lookup_captures (closure_node_id)) + for (auto cap : opt_cap.value ()) + captures.insert (cap); infered = new TyTy::ClosureType (ref, id, ident, closure_args, result_type, subst_refs, captures); @@ -1722,10 +1909,10 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr) // auto resolve because the hir id's match , expr.get_locus ()); - args.get_type_args ().push_back (std::unique_ptr<HIR::Type> (implicit_tuple)); + args.get_type_args ().emplace_back (implicit_tuple); // apply the arguments - predicate.apply_generic_arguments (&args, false); + predicate.apply_generic_arguments (&args, false, false); // finally inherit the trait bound infered->inherit_bounds ({predicate}); @@ -1744,7 +1931,16 @@ TypeCheckExpr::resolve_operator_overload ( // probe for the lang-item if (!lang_item_defined) return false; + DefId &respective_lang_item_id = lang_item_defined.value (); + auto def_lookup = mappings.lookup_defid (respective_lang_item_id); + rust_assert (def_lookup.has_value ()); + + HIR::Item *def_item = def_lookup.value (); + rust_assert (def_item->get_item_kind () == HIR::Item::ItemKind::Trait); + HIR::Trait &trait = *static_cast<HIR::Trait *> (def_item); + TraitReference *defid_trait_reference = TraitResolver::Resolve (trait); + rust_assert (!defid_trait_reference->is_error ()); // we might be in a static or const context and unknown is fine TypeCheckContextItem current_context = TypeCheckContextItem::get_error (); @@ -1788,15 +1984,49 @@ TypeCheckExpr::resolve_operator_overload ( if (selected_candidates.size () > 1) { - // mutliple candidates - rich_location r (line_table, expr.get_locus ()); - for (auto &c : resolved_candidates) - r.add_range (c.candidate.locus); + auto infer + = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty (); + auto trait_subst = defid_trait_reference->get_trait_substs (); + rust_assert (trait_subst.size () > 0); - rust_error_at ( - r, "multiple candidates found for possible operator overload"); + TyTy::TypeBoundPredicate pred (respective_lang_item_id, trait_subst, + BoundPolarity::RegularBound, + expr.get_locus ()); - return false; + std::vector<TyTy::SubstitutionArg> mappings; + auto &self_param_mapping = trait_subst[0]; + mappings.emplace_back (&self_param_mapping, lhs); + + if (rhs != nullptr) + { + rust_assert (trait_subst.size () == 2); + auto &rhs_param_mapping = trait_subst[1]; + mappings.emplace_back (&rhs_param_mapping, lhs); + } + + std::map<std::string, TyTy::BaseType *> binding_args; + binding_args["Output"] = infer; + + TyTy::SubstitutionArgumentMappings arg_mappings (mappings, binding_args, + TyTy::RegionParamList ( + trait_subst.size ()), + expr.get_locus ()); + pred.apply_argument_mappings (arg_mappings, false); + + infer->inherit_bounds ({pred}); + DeferredOpOverload defer (expr.get_mappings ().get_hirid (), + lang_item_type, specified_segment, pred, expr); + context->insert_deferred_operator_overload (std::move (defer)); + + if (rhs != nullptr) + lhs = unify_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (lhs), + TyTy::TyWithLocation (rhs), expr.get_locus ()); + + infered = unify_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (lhs), + TyTy::TyWithLocation (infer), expr.get_locus ()); + return true; } // Get the adjusted self @@ -1824,24 +2054,6 @@ TypeCheckExpr::resolve_operator_overload ( rust_debug ("is_impl_item_candidate: %s", resolved_candidate.is_impl_candidate () ? "true" : "false"); - if (resolved_candidate.is_impl_candidate ()) - { - auto infer_arguments = TyTy::SubstitutionArgumentMappings::error (); - HIR::ImplBlock &impl = *resolved_candidate.item.impl.parent; - TyTy::BaseType *impl_self_infer - = TypeCheckItem::ResolveImplBlockSelfWithInference (impl, - expr.get_locus (), - &infer_arguments); - if (impl_self_infer->get_kind () == TyTy::TypeKind::ERROR) - { - return false; - } - if (!infer_arguments.is_empty ()) - { - lookup = SubstMapperInternal::Resolve (lookup, infer_arguments); - } - } - // in the case where we resolve to a trait bound we have to be careful we are // able to do so there is a case where we are currently resolving the deref // operator overload function which is generic and this might resolve to the @@ -1939,19 +2151,11 @@ TypeCheckExpr::resolve_operator_overload ( context->insert_operator_overload (expr.get_mappings ().get_hirid (), type); // set up the resolved name on the path - if (flag_name_resolution_2_0) - { - auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( - Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); + auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( + Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); - nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()), - Resolver2_0::Definition (resolved_node_id)); - } - else - { - resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (), - resolved_node_id); - } + nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()), + Resolver2_0::Definition (resolved_node_id)); // return the result of the function back infered = function_ret_tyty; @@ -1961,16 +2165,13 @@ TypeCheckExpr::resolve_operator_overload ( HIR::PathIdentSegment TypeCheckExpr::resolve_possible_fn_trait_call_method_name ( - TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate) + const TyTy::BaseType &receiver, + TyTy::TypeBoundPredicate *associated_predicate) { - // Question - // do we need to probe possible bounds here? I think not, i think when we - // support Fn traits they are explicitly specified - // FIXME // the logic to map the FnTrait to their respective call trait-item is // duplicated over in the backend/rust-compile-expr.cc - for (auto &bound : receiver.get_specified_bounds ()) + for (const auto &bound : receiver.get_specified_bounds ()) { bool found_fn = bound.get_name ().compare ("Fn") == 0; bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0; @@ -1993,6 +2194,34 @@ TypeCheckExpr::resolve_possible_fn_trait_call_method_name ( } } + if (receiver.is<TyTy::ReferenceType> ()) + { + const auto &ref = static_cast<const TyTy::ReferenceType &> (receiver); + const auto &underlying = *ref.get_base (); + for (const auto &bound : underlying.get_specified_bounds ()) + { + bool found_fn = bound.get_name ().compare ("Fn") == 0; + bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0; + bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0; + + if (found_fn) + { + *associated_predicate = bound; + return HIR::PathIdentSegment ("call"); + } + else if (found_fn_mut) + { + *associated_predicate = bound; + return HIR::PathIdentSegment ("call_mut"); + } + else if (found_fn_once) + { + *associated_predicate = bound; + return HIR::PathIdentSegment ("call_once"); + } + } + } + // nothing *associated_predicate = TyTy::TypeBoundPredicate::error (); return HIR::PathIdentSegment (""); @@ -2086,7 +2315,7 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr, for (auto &arg : expr.get_arguments ()) { TyTy::BaseType *a = TypeCheckExpr::Resolve (*arg); - call_args.push_back (TyTy::TyVar (a->get_ref ())); + call_args.emplace_back (a->get_ref ()); } // crate implicit tuple @@ -2099,9 +2328,8 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr, context->insert_implicit_type (implicit_arg_id, tuple); std::vector<TyTy::Argument> args; - TyTy::Argument a (mapping, tuple, - expr.get_locus () /*FIXME is there a better location*/); - args.push_back (std::move (a)); + args.emplace_back (mapping, tuple, + expr.get_locus () /*FIXME is there a better location*/); TyTy::BaseType *function_ret_tyty = TyTy::TypeCheckMethodCallExpr::go (fn, expr.get_mappings (), args, @@ -2119,32 +2347,15 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr, context->insert_operator_overload (expr.get_mappings ().get_hirid (), fn); // set up the resolved name on the path - if (flag_name_resolution_2_0) - { - auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( - Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); + auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( + Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); - auto existing = nr_ctx.lookup (expr.get_mappings ().get_nodeid ()); - if (existing) - rust_assert (*existing == resolved_node_id); - else - nr_ctx.map_usage (Resolver2_0::Usage ( - expr.get_mappings ().get_nodeid ()), - Resolver2_0::Definition (resolved_node_id)); - } + auto existing = nr_ctx.lookup (expr.get_mappings ().get_nodeid ()); + if (existing) + rust_assert (*existing == resolved_node_id); else - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_mappings ().get_nodeid (), - &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (), - resolved_node_id); - } + nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()), + Resolver2_0::Definition (resolved_node_id)); // return the result of the function back *result = function_ret_tyty; @@ -2156,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-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 2a0022c..0343922 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -19,6 +19,7 @@ #ifndef RUST_HIR_TYPE_CHECK_EXPR #define RUST_HIR_TYPE_CHECK_EXPR +#include "rust-hir-expr.h" #include "rust-hir-type-check-base.h" #include "rust-hir-visitor.h" #include "rust-tyty.h" @@ -31,6 +32,11 @@ class TypeCheckExpr : private TypeCheckBase, private HIR::HIRExpressionVisitor public: static TyTy::BaseType *Resolve (HIR::Expr &expr); + static TyTy::BaseType * + ResolveOpOverload (LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, + TyTy::BaseType *lhs, TyTy::BaseType *rhs, + HIR::PathIdentSegment specified_segment); + void visit (HIR::TupleIndexExpr &expr) override; void visit (HIR::TupleExpr &expr) override; void visit (HIR::ReturnExpr &expr) override; @@ -46,6 +52,8 @@ public: void visit (HIR::IfExpr &expr) override; void visit (HIR::IfExprConseqElse &expr) override; void visit (HIR::BlockExpr &expr) override; + void visit (HIR::AnonConst &expr) override; + void visit (HIR::ConstBlock &expr) override; void visit (HIR::UnsafeBlockExpr &expr) override; void visit (HIR::ArrayIndexExpr &expr) override; void visit (HIR::ArrayExpr &expr) override; @@ -70,6 +78,8 @@ public: void visit (HIR::WhileLoopExpr &expr) override; void visit (HIR::ClosureExpr &expr) override; void visit (HIR::InlineAsm &expr) override; + void visit (HIR::LlvmInlineAsm &expr) override; + void visit (HIR::OffsetOf &expr) override; // TODO void visit (HIR::ErrorPropagationExpr &) override {} @@ -106,7 +116,8 @@ protected: TyTy::BaseType **result); HIR::PathIdentSegment resolve_possible_fn_trait_call_method_name ( - TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate); + const TyTy::BaseType &receiver, + TyTy::TypeBoundPredicate *associated_predicate); private: TypeCheckExpr (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index a5ae54b..8df8a18 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -28,9 +28,6 @@ #include "rust-tyty.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Resolver { @@ -73,44 +70,10 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function) std::vector<TyTy::SubstitutionParamMapping> substitutions; if (function.has_generics ()) { - for (auto &generic_param : function.get_generic_params ()) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - context->intern_and_insert_lifetime ( - static_cast<HIR::LifetimeParam &> (*generic_param) - .get_lifetime ()); - // TODO: handle bounds - break; - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - if (parent.get_abi () != Rust::ABI::INTRINSIC) - { - rust_error_at (function.get_locus (), ErrorCode::E0044, - "foreign items may not have const parameters"); - } - break; - - case HIR::GenericParam::GenericKind::TYPE: { - if (parent.get_abi () != Rust::ABI::INTRINSIC) - { - rust_error_at ( - function.get_locus (), ErrorCode::E0044, - "foreign items may not have type parameters"); - } - auto param_type - = TypeResolveGenericParam::Resolve (*generic_param); - context->insert_type (generic_param->get_mappings (), - param_type); - - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast<HIR::TypeParam &> (*generic_param), param_type)); - } - break; - } - } + resolve_generic_params (HIR::Item::ItemKind::Function, + function.get_locus (), + function.get_generic_params (), substitutions, + true /*is_foreign*/, parent.get_abi ()); } TyTy::RegionConstraints region_constraints; @@ -158,7 +121,7 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function) UNDEF_LOCATION, false, Mutability::Imm, std::unique_ptr<HIR::Pattern> (nullptr))); - params.push_back (TyTy::FnParam (std::move (param_pattern), param_tyty)); + params.emplace_back (std::move (param_pattern), param_tyty); context->insert_type (param.get_mappings (), param_tyty); @@ -200,128 +163,7 @@ void TypeCheckTopLevelExternItem::visit (HIR::ExternalTypeItem &type) { rust_sorry_at (type.get_locus (), "extern types are not supported yet"); - // auto binder_pin = context->push_clean_lifetime_resolver (); - - // std::vector<TyTy::SubstitutionParamMapping> substitutions; - // if (function.has_generics ()) - // { - // for (auto &generic_param : function.get_generic_params ()) - // { - // switch (generic_param.get ()->get_kind ()) - // { - // case HIR::GenericParam::GenericKind::LIFETIME: - // context->intern_and_insert_lifetime ( - // static_cast<HIR::LifetimeParam &> (*generic_param) - // .get_lifetime ()); - // // TODO: handle bounds - // break; - // case HIR::GenericParam::GenericKind::CONST: - // // FIXME: Skipping Lifetime and Const completely until better - // // handling. - // break; - - // case HIR::GenericParam::GenericKind::TYPE: { - // auto param_type - // = TypeResolveGenericParam::Resolve (generic_param.get ()); - // context->insert_type (generic_param->get_mappings (), - // param_type); - - // substitutions.push_back (TyTy::SubstitutionParamMapping ( - // static_cast<HIR::TypeParam &> (*generic_param), param_type)); - // } - // break; - // } - // } - // } - - // TyTy::RegionConstraints region_constraints; - // if (function.has_where_clause ()) - // { - // for (auto &where_clause_item : function.get_where_clause ().get_items - // ()) - // { - // ResolveWhereClauseItem::Resolve (*where_clause_item.get (), - // region_constraints); - // } - // } - - // TyTy::BaseType *ret_type = nullptr; - // if (!function.has_return_type ()) - // ret_type - // = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid - // ()); - // else - // { - // auto resolved - // = TypeCheckType::Resolve (function.get_return_type ().get ()); - // if (resolved == nullptr) - // { - // rust_error_at (function.get_locus (), - // "failed to resolve return type"); - // return; - // } - - // ret_type = resolved->clone (); - // ret_type->set_ref ( - // function.get_return_type ()->get_mappings ().get_hirid ()); - // } - - // std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params; - // for (auto ¶m : function.get_function_params ()) - // { - // // get the name as well required for later on - // auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ()); - - // // these are implicit mappings and not used - // auto crate_num = mappings->get_current_crate (); - // Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id - // (), - // mappings->get_next_hir_id (crate_num), - // UNKNOWN_LOCAL_DEFID); - - // HIR::IdentifierPattern *param_pattern - // = new HIR::IdentifierPattern (mapping, param.get_param_name (), - // UNDEF_LOCATION, false, Mutability::Imm, - // std::unique_ptr<HIR::Pattern> (nullptr)); - - // params.push_back ( - // std::pair<HIR::Pattern *, TyTy::BaseType *> (param_pattern, - // param_tyty)); - - // context->insert_type (param.get_mappings (), param_tyty); - - // // FIXME do we need error checking for patterns here? - // // see https://github.com/Rust-GCC/gccrs/issues/995 - // } - - // uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG; - // if (function.is_variadic ()) - // { - // flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG; - // if (parent.get_abi () != Rust::ABI::C) - // { - // rust_error_at ( - // function.get_locus (), ErrorCode::E0045, - // "C-variadic function must have C or cdecl calling convention"); - // } - // } - - // RustIdent ident{ - // CanonicalPath::new_seg (function.get_mappings ().get_nodeid (), - // function.get_item_name ().as_string ()), - // function.get_locus ()}; - - // auto fnType = new TyTy::FnType ( - // function.get_mappings ().get_hirid (), - // function.get_mappings ().get_defid (), - // function.get_item_name ().as_string (), ident, flags, parent.get_abi (), - // std::move (params), ret_type, std::move (substitutions), - // TyTy::SubstitutionArgumentMappings::empty ( - // context->get_lifetime_resolver ().get_num_bound_regions ()), - // region_constraints); - - // context->insert_type (function.get_mappings (), fnType); - // resolved = fnType; + // TODO } TypeCheckImplItem::TypeCheckImplItem ( @@ -360,7 +202,9 @@ TypeCheckImplItem::visit (HIR::Function &function) auto binder_pin = context->push_lifetime_binder (); if (function.has_generics ()) - resolve_generic_params (function.get_generic_params (), substitutions); + resolve_generic_params (HIR::Item::ItemKind::Function, + function.get_locus (), + function.get_generic_params (), substitutions); TyTy::RegionConstraints region_constraints; for (auto &where_clause_item : function.get_where_clause ().get_items ()) @@ -399,7 +243,7 @@ TypeCheckImplItem::visit (HIR::Function &function) // add the synthetic self param at the front, this is a placeholder for // compilation to know parameter names. The types are ignored but we // reuse the HIR identifier pattern which requires it - HIR::SelfParam &self_param = function.get_self_param (); + HIR::SelfParam &self_param = function.get_self_param_unchecked (); // FIXME: which location should be used for Rust::Identifier for `self`? std::unique_ptr<HIR::Pattern> self_pattern = std::make_unique<HIR::IdentifierPattern> ( @@ -423,14 +267,23 @@ TypeCheckImplItem::visit (HIR::Function &function) self_type = self->clone (); break; - case HIR::SelfParam::IMM_REF: { - auto region = context->lookup_and_resolve_lifetime ( - self_param.get_lifetime ()); - if (!region.has_value ()) + case HIR::SelfParam::IMM_REF: + { + tl::optional<TyTy::Region> region; + if (self_param.has_lifetime ()) { - rust_inform (self_param.get_locus (), - "failed to resolve lifetime"); - region = TyTy::Region::make_anonymous (); // FIXME + region = context->lookup_and_resolve_lifetime ( + self_param.get_lifetime ()); + if (!region.has_value ()) + { + rust_inform (self_param.get_locus (), + "failed to resolve lifetime"); + return; + } + } + else + { + region = TyTy::Region::make_anonymous (); } self_type = new TyTy::ReferenceType ( self_param.get_mappings ().get_hirid (), @@ -439,14 +292,23 @@ TypeCheckImplItem::visit (HIR::Function &function) } break; - case HIR::SelfParam::MUT_REF: { - auto region = context->lookup_and_resolve_lifetime ( - self_param.get_lifetime ()); - if (!region.has_value ()) + case HIR::SelfParam::MUT_REF: + { + tl::optional<TyTy::Region> region; + if (self_param.has_lifetime ()) + { + region = context->lookup_and_resolve_lifetime ( + self_param.get_lifetime ()); + if (!region.has_value ()) + { + rust_error_at (self_param.get_locus (), + "failed to resolve lifetime"); + return; + } + } + else { - rust_error_at (self_param.get_locus (), - "failed to resolve lifetime"); - return; + region = TyTy::Region::make_anonymous (); } self_type = new TyTy::ReferenceType ( self_param.get_mappings ().get_hirid (), @@ -462,7 +324,7 @@ TypeCheckImplItem::visit (HIR::Function &function) } context->insert_type (self_param.get_mappings (), self_type); - params.push_back (TyTy::FnParam (std::move (self_pattern), self_type)); + params.emplace_back (std::move (self_pattern), self_type); } for (auto ¶m : function.get_function_params ()) @@ -473,29 +335,17 @@ TypeCheckImplItem::visit (HIR::Function &function) context->insert_type (param.get_mappings (), param_tyty); TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); - params.push_back ( - TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty)); + params.emplace_back (param.get_param_name ().clone_pattern (), + param_tyty); } - tl::optional<CanonicalPath> canonical_path; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); - } - else - { - canonical_path = mappings.lookup_canonical_path ( - function.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path.has_value ()); + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); - RustIdent ident{*canonical_path, function.get_locus ()}; + RustIdent ident{canonical_path, function.get_locus ()}; auto fnType = new TyTy::FnType ( function.get_mappings ().get_hirid (), function.get_mappings ().get_defid (), @@ -541,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 @@ -551,7 +425,8 @@ TypeCheckImplItem::visit (HIR::TypeAlias &alias) auto binder_pin = context->push_lifetime_binder (); if (alias.has_generics ()) - resolve_generic_params (alias.get_generic_params (), substitutions); + resolve_generic_params (HIR::Item::ItemKind::TypeAlias, alias.get_locus (), + alias.get_generic_params (), substitutions); TyTy::BaseType *actual_type = TypeCheckType::Resolve (alias.get_type_aliased ()); @@ -618,8 +493,8 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant) } // get the item from the predicate - resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); + resolved_trait_item + = trait_reference.lookup_associated_item (raw_trait_item).value (); // merge the attributes const HIR::TraitItem *hir_trait_item @@ -635,16 +510,21 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant) rich_location r (line_table, constant.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); - rust_error_at ( - r, "constant %qs has an incompatible type for trait %qs", - constant.get_identifier ().as_string ().c_str (), - trait_reference.get_name ().c_str ()); + rust_error_at (r, "constant %qs has an incompatible type for trait %qs", + constant.get_identifier ().as_string ().c_str (), + trait_reference.get_name ().c_str ()); } } 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); @@ -669,8 +549,8 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) } // get the item from the predicate - resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); + resolved_trait_item + = trait_reference.lookup_associated_item (raw_trait_item).value (); // merge the attributes const HIR::TraitItem *hir_trait_item @@ -686,10 +566,9 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) rich_location r (line_table, type.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); - rust_error_at ( - r, "type alias %qs has an incompatible type for trait %qs", - type.get_new_type_name ().as_string ().c_str (), - trait_reference.get_name ().c_str ()); + rust_error_at (r, "type alias %qs has an incompatible type for trait %qs", + type.get_new_type_name ().as_string ().c_str (), + trait_reference.get_name ().c_str ()); } // its actually a projection, since we need a way to actually bind the @@ -709,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 (); @@ -729,8 +610,8 @@ TypeCheckImplItemWithTrait::visit (HIR::Function &function) } // get the item from the predicate - resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); + resolved_trait_item + = trait_reference.lookup_associated_item (raw_trait_item).value (); // merge the attributes const HIR::TraitItem *hir_trait_item diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 9774921..ee5c4e9 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -20,6 +20,7 @@ #include "optional.h" #include "rust-canonical-path.h" #include "rust-diagnostics.h" +#include "rust-hir-item.h" #include "rust-hir-type-check-enumitem.h" #include "rust-hir-type-check-implitem.h" #include "rust-hir-type-check-type.h" @@ -33,9 +34,6 @@ #include "rust-type-util.h" #include "rust-tyty-variance-analysis.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Resolver { @@ -114,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.push_back (TyTy::SubstitutionArg (&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 { - TyTy::ParamType *param = p.get_param_ty (); - TyTy::BaseType *resolved = param->destructure (); - args.push_back (TyTy::SubstitutionArg (&p, resolved)); + auto i = TyTy::TyVar::get_implicit_infer_var (locus); + argument = i.get_tyty (); } + args.emplace_back (&p, argument); } // create argument mappings @@ -170,7 +178,9 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl) std::vector<TyTy::SubstitutionParamMapping> substitutions; if (struct_decl.has_generics ()) - resolve_generic_params (struct_decl.get_generic_params (), substitutions); + resolve_generic_params (HIR::Item::ItemKind::Struct, + struct_decl.get_locus (), + struct_decl.get_generic_params (), substitutions); TyTy::RegionConstraints region_constraints; for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) @@ -195,25 +205,11 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl) // get the path - auto path = CanonicalPath::create_empty (); - - // FIXME: HACK: ARTHUR: Disgusting - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - path = nr_ctx.values - .to_canonical_path (struct_decl.get_mappings ().get_nodeid ()) - .value (); - } - else - { - path - = mappings - .lookup_canonical_path (struct_decl.get_mappings ().get_nodeid ()) - .value (); - } + CanonicalPath path + = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ()); RustIdent ident{path, struct_decl.get_locus ()}; @@ -255,7 +251,9 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl) std::vector<TyTy::SubstitutionParamMapping> substitutions; if (struct_decl.has_generics ()) - resolve_generic_params (struct_decl.get_generic_params (), substitutions); + resolve_generic_params (HIR::Item::ItemKind::Struct, + struct_decl.get_locus (), + struct_decl.get_generic_params (), substitutions); TyTy::RegionConstraints region_constraints; for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) @@ -276,27 +274,11 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl) context->insert_type (field.get_mappings (), ty_field->get_field_type ()); } - auto path = CanonicalPath::create_empty (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - // FIXME: HACK: ARTHUR: Disgusting - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto canonical_path = nr_ctx.types.to_canonical_path ( - struct_decl.get_mappings ().get_nodeid ()); - - if (!canonical_path.has_value ()) - rust_unreachable (); - path = canonical_path.value (); - } - else - { - path - = mappings - .lookup_canonical_path (struct_decl.get_mappings ().get_nodeid ()) - .value (); - } + CanonicalPath path + = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ()); RustIdent ident{path, struct_decl.get_locus ()}; @@ -337,7 +319,8 @@ TypeCheckItem::visit (HIR::Enum &enum_decl) auto lifetime_pin = context->push_clean_lifetime_resolver (); std::vector<TyTy::SubstitutionParamMapping> substitutions; if (enum_decl.has_generics ()) - resolve_generic_params (enum_decl.get_generic_params (), substitutions); + resolve_generic_params (HIR::Item::ItemKind::Enum, enum_decl.get_locus (), + enum_decl.get_generic_params (), substitutions); // Process #[repr(X)] attribute, if any const AST::AttrVec &attrs = enum_decl.get_outer_attrs (); @@ -355,26 +338,26 @@ TypeCheckItem::visit (HIR::Enum &enum_decl) variants.push_back (field_type); } - // get the path - tl::optional<CanonicalPath> canonical_path; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path = nr_ctx.types.to_canonical_path ( - enum_decl.get_mappings ().get_nodeid ()); - } - else + // Check for zero-variant enum compatibility + if (enum_decl.is_zero_variant ()) { - canonical_path = mappings.lookup_canonical_path ( - enum_decl.get_mappings ().get_nodeid ()); + if (repr.repr_kind == TyTy::ADTType::ReprKind::INT + || repr.repr_kind == TyTy::ADTType::ReprKind::C) + { + rust_error_at (enum_decl.get_locus (), + "unsupported representation for zero-variant enum"); + return; + } } - rust_assert (canonical_path.has_value ()); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - RustIdent ident{*canonical_path, enum_decl.get_locus ()}; + // get the path + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (enum_decl.get_mappings ().get_nodeid ()); + + RustIdent ident{canonical_path, enum_decl.get_locus ()}; // multi variant ADT auto *type @@ -397,7 +380,8 @@ TypeCheckItem::visit (HIR::Union &union_decl) auto lifetime_pin = context->push_clean_lifetime_resolver (); std::vector<TyTy::SubstitutionParamMapping> substitutions; if (union_decl.has_generics ()) - resolve_generic_params (union_decl.get_generic_params (), substitutions); + resolve_generic_params (HIR::Item::ItemKind::Union, union_decl.get_locus (), + union_decl.get_generic_params (), substitutions); TyTy::RegionConstraints region_constraints; for (auto &where_clause_item : union_decl.get_where_clause ().get_items ()) @@ -419,26 +403,14 @@ TypeCheckItem::visit (HIR::Union &union_decl) ty_variant->get_field_type ()); } - // get the path - tl::optional<CanonicalPath> canonical_path; + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path = nr_ctx.types.to_canonical_path ( - union_decl.get_mappings ().get_nodeid ()); - } - else - { - canonical_path = mappings.lookup_canonical_path ( - union_decl.get_mappings ().get_nodeid ()); - } - - rust_assert (canonical_path.has_value ()); + // get the path + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (union_decl.get_mappings ().get_nodeid ()); - RustIdent ident{*canonical_path, union_decl.get_locus ()}; + RustIdent ident{canonical_path, union_decl.get_locus ()}; // there is only a single variant std::vector<TyTy::VariantDef *> variants; @@ -557,8 +529,9 @@ TypeCheckItem::visit (HIR::Function &function) auto lifetime_pin = context->push_clean_lifetime_resolver (); std::vector<TyTy::SubstitutionParamMapping> substitutions; if (function.has_generics ()) - resolve_generic_params (function.get_generic_params (), - substitutions); // TODO resolve constraints + resolve_generic_params (HIR::Item::ItemKind::Function, + function.get_locus (), + function.get_generic_params (), substitutions); TyTy::RegionConstraints region_constraints; for (auto &where_clause_item : function.get_where_clause ().get_items ()) @@ -591,28 +564,15 @@ TypeCheckItem::visit (HIR::Function &function) auto param_tyty = TypeCheckType::Resolve (param.get_type ()); context->insert_type (param.get_mappings (), param_tyty); TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); - params.push_back ( - TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty)); + params.emplace_back (param.get_param_name ().clone_pattern (), + param_tyty); } - auto path = CanonicalPath::create_empty (); - - // FIXME: HACK: ARTHUR: Disgusting - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto canonical_path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - path = canonical_path.value (); - } - else - { - path = mappings - .lookup_canonical_path (function.get_mappings ().get_nodeid ()) - .value (); - } + CanonicalPath path + = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); RustIdent ident{path, function.get_locus ()}; @@ -637,6 +597,38 @@ TypeCheckItem::visit (HIR::Function &function) context->switch_to_fn_body (); auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ()); + // emit check for + // error[E0121]: the type placeholder `_` is not allowed within types on item + const auto placeholder = ret_type->contains_infer (); + if (placeholder != nullptr && function.has_return_type ()) + { + // FIXME + // this will be a great place for the Default Hir Visitor we want to + // grab the locations of the placeholders (HIR::InferredType) their + // location, for now maybe we can use their hirid to lookup the location + location_t placeholder_locus + = mappings.lookup_location (placeholder->get_ref ()); + location_t type_locus = function.get_return_type ().get_locus (); + rich_location r (line_table, placeholder_locus); + + bool have_expected_type + = block_expr_ty != nullptr && !block_expr_ty->is<TyTy::ErrorType> (); + if (!have_expected_type) + { + r.add_range (type_locus); + } + else + { + std::string fixit + = "replace with the correct type " + block_expr_ty->get_name (); + r.add_fixit_replace (type_locus, fixit.c_str ()); + } + + rust_error_at (r, ErrorCode::E0121, + "the type placeholder %<_%> is not allowed within types " + "on item signatures"); + } + location_t fn_return_locus = function.has_function_return_type () ? function.get_return_type ().get_locus () : function.get_locus (); @@ -701,13 +693,33 @@ TypeCheckItem::visit (HIR::ExternBlock &extern_block) } } +void +TypeCheckItem::visit (HIR::ExternCrate &extern_crate) +{ + if (extern_crate.references_self ()) + return; + + auto &mappings = Analysis::Mappings::get (); + CrateNum num + = mappings.lookup_crate_name (extern_crate.get_referenced_crate ()) + .value (); + HIR::Crate &crate = mappings.get_hir_crate (num); + + CrateNum saved_crate_num = mappings.get_current_crate (); + mappings.set_current_crate (num); + for (auto &item : crate.get_items ()) + TypeCheckItem::Resolve (*item); + mappings.set_current_crate (saved_crate_num); +} + std::pair<std::vector<TyTy::SubstitutionParamMapping>, TyTy::RegionConstraints> TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block, bool &failure_flag) { std::vector<TyTy::SubstitutionParamMapping> substitutions; if (impl_block.has_generics ()) - resolve_generic_params (impl_block.get_generic_params (), substitutions); + resolve_generic_params (HIR::Item::ItemKind::Impl, impl_block.get_locus (), + impl_block.get_generic_params (), substitutions); TyTy::RegionConstraints region_constraints; for (auto &where_clause_item : impl_block.get_where_clause ().get_items ()) diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 56832e7..414694b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -51,9 +51,9 @@ public: void visit (HIR::ImplBlock &impl_block) override; void visit (HIR::ExternBlock &extern_block) override; void visit (HIR::Trait &trait_block) override; + void visit (HIR::ExternCrate &extern_crate) override; // nothing to do - void visit (HIR::ExternCrate &) override {} void visit (HIR::UseDeclaration &) override {} protected: diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 1fe39aae..ffa0990 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -77,9 +77,9 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) // lookup the associated item from the specified bound HIR::PathExprSegment &item_seg = expr.get_segments ().at (0); HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment (); - TyTy::TypeBoundPredicateItem item + tl::optional<TyTy::TypeBoundPredicateItem> item = specified_bound.lookup_associated_item (item_seg_identifier.as_string ()); - if (item.is_error ()) + if (!item.has_value ()) { rust_error_at (item_seg.get_locus (), "unknown associated item"); return; @@ -116,9 +116,9 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) // and we dont need to worry if the trait item is actually implemented or // not because this will have already been validated as part of the trait // impl block - infered = item.get_tyty_for_receiver (root); + infered = item->get_tyty_for_receiver (root); root_resolved_node_id - = item.get_raw_item ()->get_mappings ().get_nodeid (); + = item->get_raw_item ()->get_mappings ().get_nodeid (); } else { @@ -157,20 +157,11 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) bool fully_resolved = expr.get_segments ().size () <= 1; if (fully_resolved) { - if (flag_name_resolution_2_0) - { - auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( - Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); + auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( + Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); - nr_ctx.map_usage (Resolver2_0::Usage ( - expr.get_mappings ().get_nodeid ()), - Resolver2_0::Definition (root_resolved_node_id)); - } - else - { - resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (), - root_resolved_node_id); - } + nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()), + Resolver2_0::Definition (root_resolved_node_id)); return; } @@ -264,24 +255,16 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, bool is_root = *offset == 0; NodeId ast_node_id = seg.get_mappings ().get_nodeid (); - // then lookup the reference_node_id - NodeId ref_node_id = UNKNOWN_NODEID; + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (flag_name_resolution_2_0) + // lookup the reference_node_id + NodeId ref_node_id; + if (auto res = nr_ctx.lookup (ast_node_id)) { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - // assign the ref_node_id if we've found something - nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) { - ref_node_id = resolved; - }); + ref_node_id = *res; } - else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); - - // ref_node_id is the NodeId that the segments refers to. - if (ref_node_id == UNKNOWN_NODEID) + else { if (root_tyty != nullptr && *offset > 0) { @@ -336,7 +319,7 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, TyTy::BaseType *lookup = nullptr; if (!query_type (ref, &lookup)) { - if (is_root) + if (is_root || root_tyty == nullptr) { rust_error_at (expr.get_locus (), ErrorCode::E0425, "cannot find value %qs in this scope", @@ -534,9 +517,8 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, const auto &predicate = impl_block_ty->lookup_predicate (trait_ref.get_defid ()); if (!predicate.is_error ()) - impl_block_ty - = associated->setup_associated_types (prev_segment, predicate, - nullptr, false); + associated->setup_associated_types (prev_segment, predicate, + nullptr, false); } } @@ -561,33 +543,12 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, } rust_assert (resolved_node_id != UNKNOWN_NODEID); - if (flag_name_resolution_2_0) - { - auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( - Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); - nr_ctx.map_usage (Resolver2_0::Usage (expr_mappings.get_nodeid ()), - Resolver2_0::Definition (resolved_node_id)); - } - // name scope first - else if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node_id)) - { - resolver->insert_resolved_name (expr_mappings.get_nodeid (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - resolver->insert_resolved_type (expr_mappings.get_nodeid (), - resolved_node_id); - } - else - { - resolver->insert_resolved_misc (expr_mappings.get_nodeid (), - resolved_node_id); - } + auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> ( + Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()); + + nr_ctx.map_usage (Resolver2_0::Usage (expr_mappings.get_nodeid ()), + Resolver2_0::Definition (resolved_node_id)); infered = tyseg; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index 3f9557a..7dae303 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -21,9 +21,8 @@ #include "rust-hir-type-check-expr.h" #include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" - -// for flag_name_resolution_2_0 -#include "options.h" +#include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Resolver { @@ -54,23 +53,13 @@ TypeCheckPattern::visit (HIR::PathInExpression &pattern) NodeId ref_node_id = UNKNOWN_NODEID; bool maybe_item = false; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ())) - { - ref_node_id = *id; - maybe_item = true; - } - } - else + if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ())) { - maybe_item |= resolver->lookup_resolved_name ( - pattern.get_mappings ().get_nodeid (), &ref_node_id); - maybe_item |= resolver->lookup_resolved_type ( - pattern.get_mappings ().get_nodeid (), &ref_node_id); + ref_node_id = *id; + maybe_item = true; } bool path_is_const_item = false; @@ -173,19 +162,32 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern) infered = pattern_ty; TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered); - rust_assert (adt->number_of_variants () > 0); - TyTy::VariantDef *variant = adt->get_variants ().at (0); + TyTy::VariantDef *variant = nullptr; if (adt->is_enum ()) { HirId variant_id = UNKNOWN_HIRID; bool ok = context->lookup_variant_definition ( pattern.get_path ().get_mappings ().get_hirid (), &variant_id); - rust_assert (ok); + if (!ok) + { + rust_error_at ( + pattern.get_locus (), ErrorCode::E0532, + "expected tuple struct or tuple variant, found enum %qs", + pattern_ty->get_name ().c_str ()); + return; + } ok = adt->lookup_variant_by_id (variant_id, &variant); rust_assert (ok); } + else + { + rust_assert (adt->number_of_variants () > 0); + variant = adt->get_variants ().at (0); + } + + rust_assert (variant != nullptr); // error[E0532]: expected tuple struct or tuple variant, found struct // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0 @@ -213,31 +215,144 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { - // TODO - rust_unreachable (); + case HIR::TupleStructItems::HAS_REST: + { + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (items); + auto &lower_patterns = items_has_rest.get_lower_patterns (); + auto &upper_patterns = items_has_rest.get_upper_patterns (); + size_t pattern_min_cap + = lower_patterns.size () + upper_patterns.size (); + if (variant->num_fields () < pattern_min_cap) + { + if (!lower_patterns.empty ()) + { + // TODO initialize rich_locus with loc of ADT definition instead + rich_location rich_locus (line_table, + lower_patterns[0]->get_locus ()); + for (auto &pattern : lower_patterns) + { + if (pattern == lower_patterns[0]) + continue; + rich_locus.add_range (pattern->get_locus (), + SHOW_RANGE_WITH_CARET); + } + for (auto &pattern : upper_patterns) + { + rich_locus.add_range (pattern->get_locus (), + SHOW_RANGE_WITH_CARET); + } + rust_error_at (rich_locus, ErrorCode::E0023, + "this pattern has %lu %s but the corresponding " + "tuple variant has %lu %s", + (unsigned long) (pattern_min_cap), + pattern_min_cap == 1 ? "field" : "fields", + (unsigned long) variant->num_fields (), + variant->num_fields () == 1 ? "field" + : "fields"); + } + else + { + // TODO initialize rich_locus with loc of ADT definition instead + rich_location rich_locus (line_table, + upper_patterns[0]->get_locus ()); + for (auto &pattern : upper_patterns) + { + if (pattern == upper_patterns[0]) + continue; + rich_locus.add_range (pattern->get_locus (), + SHOW_RANGE_WITH_CARET); + } + rust_error_at (rich_locus, ErrorCode::E0023, + "this pattern has %lu %s but the corresponding " + "tuple variant has %lu %s", + (unsigned long) (pattern_min_cap), + pattern_min_cap == 1 ? "field" : "fields", + (unsigned long) variant->num_fields (), + variant->num_fields () == 1 ? "field" + : "fields"); + } + // we continue on to try and setup the types as best we can for + // type checking + } + + // iterate the fields manually to set them up + size_t i = 0; + for (auto &pattern : lower_patterns) + { + if (i >= variant->num_fields ()) + break; + + TyTy::StructFieldType *field = variant->get_field_at_index (i++); + TyTy::BaseType *fty = field->get_field_type (); + + // setup the type on this pattern type + context->insert_type (pattern->get_mappings (), fty); + TypeCheckPattern::Resolve (*pattern, fty); + } + + i = variant->num_fields () - upper_patterns.size (); + for (auto &pattern : upper_patterns) + { + if (i >= variant->num_fields ()) + break; + + TyTy::StructFieldType *field = variant->get_field_at_index (i++); + TyTy::BaseType *fty = field->get_field_type (); + + // setup the type on this pattern type + context->insert_type (pattern->get_mappings (), fty); + TypeCheckPattern::Resolve (*pattern, fty); + } } break; - case HIR::TupleStructItems::MULTIPLE: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); + case HIR::TupleStructItems::NO_REST: + { + HIR::TupleStructItemsNoRest &items_no_rest + = static_cast<HIR::TupleStructItemsNoRest &> (items); + auto &patterns = items_no_rest.get_patterns (); - if (items_no_range.get_patterns ().size () != variant->num_fields ()) + if (patterns.size () != variant->num_fields ()) { - rust_error_at ( - pattern.get_locus (), ErrorCode::E0023, - "this pattern has %lu fields but the corresponding " - "tuple variant has %lu field", - (unsigned long) items_no_range.get_patterns ().size (), - (unsigned long) variant->num_fields ()); + if (patterns.empty ()) + { + rust_error_at (pattern.get_locus (), ErrorCode::E0023, + "this pattern has %lu %s but the corresponding " + "tuple variant has %lu %s", + (unsigned long) patterns.size (), + patterns.size () == 1 ? "field" : "fields", + (unsigned long) variant->num_fields (), + variant->num_fields () == 1 ? "field" + : "fields"); + } + else + { + rich_location rich_locus (line_table, + patterns[0]->get_locus ()); + for (auto &pattern : items_no_rest.get_patterns ()) + { + if (pattern == patterns[0]) + continue; + rich_locus.add_range (pattern->get_locus (), + SHOW_RANGE_WITH_CARET); + } + rust_error_at (rich_locus, ErrorCode::E0023, + "this pattern has %lu %s but the corresponding " + "tuple variant has %lu %s", + (unsigned long) patterns.size (), + patterns.size () == 1 ? "field" : "fields", + (unsigned long) variant->num_fields (), + variant->num_fields () == 1 ? "field" + : "fields"); + } // we continue on to try and setup the types as best we can for // type checking } // iterate the fields and set them up, I wish we had ZIP size_t i = 0; - for (auto &pattern : items_no_range.get_patterns ()) + for (auto &pattern : items_no_rest.get_patterns ()) { if (i >= variant->num_fields ()) break; @@ -277,7 +392,15 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) infered = pattern_ty; TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered); - rust_assert (adt->number_of_variants () > 0); + if (adt->number_of_variants () == 0) + { + HIR::PathInExpression &path = pattern.get_path (); + const AST::SimplePath &sp = path.as_simple_path (); + rust_error_at (pattern.get_locus (), ErrorCode::E0574, + "expected struct, variant or union type, found enum %qs", + sp.as_string ().c_str ()); + return; + } TyTy::VariantDef *variant = adt->get_variants ().at (0); if (adt->is_enum ()) @@ -285,7 +408,16 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) HirId variant_id = UNKNOWN_HIRID; bool ok = context->lookup_variant_definition ( pattern.get_path ().get_mappings ().get_hirid (), &variant_id); - rust_assert (ok); + if (!ok) + { + HIR::PathInExpression &path = pattern.get_path (); + const AST::SimplePath &sp = path.as_simple_path (); + rust_error_at ( + pattern.get_locus (), ErrorCode::E0574, + "expected struct, variant or union type, found enum %qs", + sp.as_string ().c_str ()); + return; + } ok = adt->lookup_variant_by_id (variant_id, &variant); rust_assert (ok); @@ -293,7 +425,30 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) // error[E0532]: expected tuple struct or tuple variant, found struct // variant `Foo::D` - if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT) + bool error_E0532 = false; + if (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE) + { + // Tuple structs can still be matched with struct patterns via index + // numbers e.g. Foo {0: a, .., 3: b}, so check whether the fields are of + // type TUPLE_PAT. Throw E0532 if not. + auto &struct_pattern_elems = pattern.get_struct_pattern_elems (); + for (auto &field : struct_pattern_elems.get_struct_pattern_fields ()) + { + if (field->get_item_type () + != HIR::StructPatternField::ItemType::TUPLE_PAT) + { + error_E0532 = true; + break; + } + } + } + else if (variant->get_variant_type () + != TyTy::VariantDef::VariantType::STRUCT) + { + error_E0532 = true; + } + + if (error_E0532) { std::string variant_type = TyTy::VariantDef::variant_type_string (variant->get_variant_type ()); @@ -316,13 +471,15 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO rust_unreachable (); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat &ident = static_cast<HIR::StructPatternFieldIdentPat &> (*field); @@ -341,7 +498,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) } break; - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { HIR::StructPatternFieldIdent &ident = static_cast<HIR::StructPatternFieldIdent &> (*field); @@ -380,7 +538,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) case HIR::StructPatternField::ItemType::IDENT: case HIR::StructPatternField::ItemType::IDENT_PAT: break; - default: { + default: + { auto first_elem = struct_pattern_elems.get_struct_pattern_fields () .at (0) @@ -397,7 +556,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) // Expects enum struct or struct struct. // error[E0027]: pattern does not mention fields `x`, `y` // error[E0026]: variant `Foo::D` does not have a field named `b` - if (named_fields.size () != variant->num_fields ()) + if (!pattern.get_struct_pattern_elems ().has_rest () + && named_fields.size () != variant->num_fields ()) { std::map<std::string, bool> missing_names; @@ -440,25 +600,27 @@ void TypeCheckPattern::visit (HIR::TuplePattern &pattern) { std::unique_ptr<HIR::TuplePatternItems> items; - switch (pattern.get_items ().get_item_type ()) + + // Check whether parent is tuple + auto resolved_parent = parent->destructure (); + if (resolved_parent->get_kind () != TyTy::TUPLE) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: { - auto &ref = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + rust_error_at (pattern.get_locus (), "expected %s, found tuple", + parent->as_string ().c_str ()); + return; + } + TyTy::TupleType &par = *static_cast<TyTy::TupleType *> (resolved_parent); - auto resolved_parent = parent->destructure (); - if (resolved_parent->get_kind () != TyTy::TUPLE) - { - rust_error_at (pattern.get_locus (), "expected %s, found tuple", - parent->as_string ().c_str ()); - break; - } + switch (pattern.get_items ().get_item_type ()) + { + case HIR::TuplePatternItems::ItemType::NO_REST: + { + auto &ref + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); const auto &patterns = ref.get_patterns (); size_t nitems_to_resolve = patterns.size (); - TyTy::TupleType &par - = *static_cast<TyTy::TupleType *> (resolved_parent); if (patterns.size () != par.get_fields ().size ()) { emit_pattern_size_error (pattern, par.get_fields ().size (), @@ -474,19 +636,70 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) TyTy::BaseType *par_type = par.get_field (i); TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type); - pattern_elems.push_back (TyTy::TyVar (elem->get_ref ())); + pattern_elems.emplace_back (elem->get_ref ()); } infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (), pattern.get_locus (), pattern_elems); } break; - case HIR::TuplePatternItems::ItemType::RANGED: { - // HIR::TuplePatternItemsRanged &ref - // = *static_cast<HIR::TuplePatternItemsRanged *> ( - // pattern.get_items ().get ()); - // TODO - rust_unreachable (); + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + HIR::TuplePatternItemsHasRest &ref + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); + + const auto &lower = ref.get_lower_patterns (); + const auto &upper = ref.get_upper_patterns (); + size_t min_size_required = lower.size () + upper.size (); + + // Ensure that size of lower and upper patterns <= parent size + if (min_size_required > par.get_fields ().size ()) + { + emit_pattern_size_error (pattern, par.get_fields ().size (), + min_size_required); + // continue and attempt to resolve individual items in the pattern + } + + // Resolve lower patterns + std::vector<TyTy::TyVar> pattern_elems; + size_t nlower_items_to_resolve + = std::min (lower.size (), par.get_fields ().size ()); + for (size_t i = 0; i < nlower_items_to_resolve; i++) + { + auto &p = lower[i]; + TyTy::BaseType *par_type = par.get_field (i); + + TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type); + pattern_elems.emplace_back (elem->get_ref ()); + } + + if (lower.size () > par.get_fields ().size ()) + break; + + // Pad pattern_elems until needing to resolve upper patterns + size_t rest_end + = std::max (par.get_fields ().size () - upper.size (), lower.size ()); + for (size_t i = lower.size (); i < rest_end; i++) + { + TyTy::BaseType *par_type = par.get_field (i); + pattern_elems.emplace_back (par_type->get_ref ()); + } + + size_t nupper_items_to_resolve + = std::min (upper.size (), + par.get_fields ().size () - pattern_elems.size ()); + // Resolve upper patterns + for (size_t i = 0; i < nupper_items_to_resolve; i++) + { + auto &p = upper[i]; + TyTy::BaseType *par_type = par.get_field (rest_end + i); + + TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type); + pattern_elems.emplace_back (elem->get_ref ()); + } + + infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (), + pattern.get_locus (), pattern_elems); } break; } @@ -495,8 +708,18 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) void TypeCheckPattern::visit (HIR::LiteralPattern &pattern) { - infered = resolve_literal (pattern.get_mappings (), pattern.get_literal (), - pattern.get_locus ()); + TyTy::BaseType *resolved + = resolve_literal (pattern.get_mappings (), pattern.get_literal (), + pattern.get_locus ()); + if (resolved->get_kind () == TyTy::TypeKind::ERROR) + { + infered = resolved; + return; + } + + infered = unify_site (pattern.get_mappings ().get_hirid (), + TyTy::TyWithLocation (parent), + TyTy::TyWithLocation (resolved), pattern.get_locus ()); } void @@ -521,6 +744,11 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern) void TypeCheckPattern::visit (HIR::IdentifierPattern &pattern) { + if (pattern.has_subpattern ()) + { + TypeCheckPattern::Resolve (pattern.get_subpattern (), parent); + } + if (!pattern.get_is_ref ()) { infered = parent; @@ -563,8 +791,150 @@ TypeCheckPattern::visit (HIR::ReferencePattern &pattern) void TypeCheckPattern::visit (HIR::SlicePattern &pattern) { - rust_sorry_at (pattern.get_locus (), - "type checking qualified path patterns not supported"); + auto resolved_parent = parent->destructure (); + TyTy::BaseType *parent_element_ty = nullptr; + switch (resolved_parent->get_kind ()) + { + case TyTy::ARRAY: + { + auto &array_ty_ty = static_cast<TyTy::ArrayType &> (*parent); + parent_element_ty = array_ty_ty.get_element_type (); + auto capacity = array_ty_ty.get_capacity (); + + tree cap = error_mark_node; + if (capacity->get_kind () != TyTy::TypeKind::CONST) + { + // Error case - capacity is not a const type + break; + } + + auto *capacity_const = capacity->as_const_type (); + switch (capacity_const->const_kind ()) + { + case TyTy::BaseConstType::ConstKind::Value: + { + const auto &const_value + = *static_cast<TyTy::ConstValueType *> (capacity); + cap = const_value.get_value (); + } + break; + + case TyTy::BaseConstType::ConstKind::Decl: + case TyTy::BaseConstType::ConstKind::Infer: + case TyTy::BaseConstType::ConstKind::Error: + cap = error_mark_node; + break; + } + + if (error_operand_p (cap)) + { + rust_error_at (parent->get_locus (), + "capacity of array %qs is not known at compile time", + array_ty_ty.get_name ().c_str ()); + break; + } + auto cap_wi = wi::to_wide (cap).to_uhwi (); + + // size check during compile time + switch (pattern.get_items ().get_item_type ()) + { + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &ref = static_cast<HIR::SlicePatternItemsNoRest &> ( + pattern.get_items ()); + if (cap_wi != ref.get_patterns ().size ()) + { + rust_error_at ( + pattern.get_locus (), ErrorCode::E0527, + "pattern requires %lu elements but array has %lu", + (unsigned long) ref.get_patterns ().size (), + (unsigned long) cap_wi); + break; + } + } + break; + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &ref = static_cast<HIR::SlicePatternItemsHasRest &> ( + pattern.get_items ()); + auto pattern_min_cap = ref.get_lower_patterns ().size () + + ref.get_upper_patterns ().size (); + + if (cap_wi < pattern_min_cap) + { + rust_error_at (pattern.get_locus (), ErrorCode::E0528, + "pattern requires at least %lu elements but " + "array has %lu", + (unsigned long) pattern_min_cap, + (unsigned long) cap_wi); + break; + } + } + break; + } + + break; + } + case TyTy::SLICE: + { + auto &slice_ty_ty = static_cast<TyTy::SliceType &> (*parent); + parent_element_ty = slice_ty_ty.get_element_type (); + break; + } + case TyTy::REF: + { + auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent); + const TyTy::SliceType *slice = nullptr; + if (!ref_ty_ty.is_dyn_slice_type (&slice)) + { + rust_error_at (pattern.get_locus (), "expected %s, found slice", + parent->as_string ().c_str ()); + return; + } + parent_element_ty = slice->get_element_type (); + break; + } + default: + { + rust_error_at (pattern.get_locus (), "expected %s, found slice", + parent->as_string ().c_str ()); + return; + } + } + + rust_assert (parent_element_ty != nullptr); + // infered inherits array/slice typing from parent + infered = parent->clone (); + infered->set_ref (pattern.get_mappings ().get_hirid ()); + + // Type check every item in the SlicePattern against parent's element ty + switch (pattern.get_items ().get_item_type ()) + { + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &ref + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (const auto &pattern_member : ref.get_patterns ()) + { + TypeCheckPattern::Resolve (*pattern_member, parent_element_ty); + } + break; + } + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &ref + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (const auto &pattern_member : ref.get_lower_patterns ()) + { + TypeCheckPattern::Resolve (*pattern_member, parent_element_ty); + } + for (const auto &pattern_member : ref.get_upper_patterns ()) + { + TypeCheckPattern::Resolve (*pattern_member, parent_element_ty); + } + break; + } + } } void @@ -591,7 +961,8 @@ TypeCheckPattern::typecheck_range_pattern_bound ( TyTy::BaseType *resolved_bound = nullptr; switch (bound.get_bound_type ()) { - case HIR::RangePatternBound::RangePatternBoundType::LITERAL: { + case HIR::RangePatternBound::RangePatternBoundType::LITERAL: + { auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound); HIR::Literal lit = ref.get_literal (); @@ -600,14 +971,16 @@ TypeCheckPattern::typecheck_range_pattern_bound ( } break; - case HIR::RangePatternBound::RangePatternBoundType::PATH: { + case HIR::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound); resolved_bound = TypeCheckExpr::Resolve (ref.get_path ()); } break; - case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: { + case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound); resolved_bound = TypeCheckExpr::Resolve (ref.get_qualified_path ()); @@ -677,6 +1050,11 @@ ClosureParamInfer::visit (HIR::WildcardPattern &pattern) void ClosureParamInfer::visit (HIR::IdentifierPattern &pattern) { + if (pattern.has_subpattern ()) + { + ClosureParamInfer::Resolve (pattern.get_subpattern ()); + } + HirId id = pattern.get_mappings ().get_hirid (); infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, TyTy::InferType::TypeHint::Default (), diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc index 4e53856..87141af 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc @@ -60,6 +60,12 @@ void TypeCheckStmt::visit (HIR::ConstantItem &constant) { TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); + if (!constant.has_expr ()) + { + infered = type; + return; + } + TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); infered = coercion_site ( diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 800f7ca..7e3a57a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -60,6 +60,9 @@ private: TyTy::BaseType *resolved_field_value_expr; std::set<std::string> fields_assigned; std::map<size_t, HIR::StructExprField *> adtFieldIndexToField; + + // parent + HIR::Expr &parent; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 40c42b2..eb44279 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -28,7 +28,7 @@ TypeCheckStructExpr::TypeCheckStructExpr (HIR::Expr &e) : TypeCheckBase (), resolved (new TyTy::ErrorType (e.get_mappings ().get_hirid ())), struct_path_resolved (nullptr), - variant (&TyTy::VariantDef::get_error_node ()) + variant (&TyTy::VariantDef::get_error_node ()), parent (e) {} TyTy::BaseType * @@ -65,7 +65,7 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) if (base_unify->get_kind () != struct_path_ty->get_kind ()) { - rust_fatal_error ( + rust_error_at ( struct_expr.get_struct_base ().get_base ().get_locus (), "incompatible types for base struct reference"); return; @@ -82,7 +82,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) bool ok = context->lookup_variant_definition ( struct_expr.get_struct_name ().get_mappings ().get_hirid (), &variant_id); - rust_assert (ok); + if (!ok) + { + rich_location r (line_table, struct_expr.get_locus ()); + r.add_range (struct_expr.get_struct_name ().get_locus ()); + rust_error_at ( + struct_expr.get_struct_name ().get_locus (), ErrorCode::E0574, + "expected a struct, variant or union type, found enum %qs", + struct_path_resolved->get_name ().c_str ()); + return; + } ok = struct_path_resolved->lookup_variant_by_id (variant_id, &variant); rust_assert (ok); @@ -118,29 +127,14 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) break; } - if (!ok) - { - return; - } - - if (resolved_field_value_expr == nullptr) - { - rust_fatal_error (field->get_locus (), - "failed to resolve type for field"); - ok = false; - break; - } - - context->insert_type (field->get_mappings (), resolved_field_value_expr); + if (ok) + context->insert_type (field->get_mappings (), + resolved_field_value_expr); } - // something failed setting up the fields + // something failed setting up the fields and error's emitted if (!ok) - { - rust_error_at (struct_expr.get_locus (), - "constructor type resolution failure"); - return; - } + return; // check the arguments are all assigned and fix up the ordering std::vector<std::string> missing_field_names; @@ -220,8 +214,7 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) rust_assert (ok); adtFieldIndexToField[field_index] = implicit_field; - struct_expr.get_fields ().push_back ( - std::unique_ptr<HIR::StructExprField> (implicit_field)); + struct_expr.get_fields ().emplace_back (implicit_field); } } } @@ -251,11 +244,11 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) field.release (); std::vector<std::unique_ptr<HIR::StructExprField> > ordered_fields; + ordered_fields.reserve (adtFieldIndexToField.size ()); + for (size_t i = 0; i < adtFieldIndexToField.size (); i++) - { - ordered_fields.push_back ( - std::unique_ptr<HIR::StructExprField> (adtFieldIndexToField[i])); - } + ordered_fields.emplace_back (adtFieldIndexToField[i]); + struct_expr.set_fields_as_owner (std::move (ordered_fields)); } @@ -271,8 +264,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) &field_index); if (!ok) { - rust_error_at (field.get_locus (), "unknown field"); - return true; + rich_location r (line_table, parent.get_locus ()); + r.add_range (field.get_locus ()); + rust_error_at (r, ErrorCode::E0560, "unknown field %qs", + field.field_name.as_string ().c_str ()); + return false; } auto it = adtFieldIndexToField.find (field_index); @@ -317,8 +313,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) bool ok = variant->lookup_field (field_name, &field_type, &field_index); if (!ok) { - rust_error_at (field.get_locus (), "unknown field"); - return true; + rich_location r (line_table, parent.get_locus ()); + r.add_range (field.get_locus ()); + rust_error_at (r, ErrorCode::E0560, "unknown field %qs", + field_name.c_str ()); + return false; } auto it = adtFieldIndexToField.find (field_index); @@ -329,8 +328,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) repeat_location.add_range (prev_field_locus); rust_error_at (repeat_location, ErrorCode::E0062, - "field %qs specified more than once", - field_name.c_str ()); + "field %qs specified more than once", field_name.c_str ()); return false; } @@ -363,7 +361,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) if (!ok) { rust_error_at (field.get_locus (), "unknown field"); - return true; + return false; } auto it = adtFieldIndexToField.find (field_index); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 54f50ec..ca7ef47 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -29,6 +29,7 @@ #include "rust-substitution-mapper.h" #include "rust-type-util.h" #include "rust-system.h" +#include "rust-compile-base.h" namespace Rust { namespace Resolver { @@ -96,15 +97,20 @@ TypeCheckType::visit (HIR::BareFunctionType &fntype) } std::vector<TyTy::TyVar> params; + params.reserve (fntype.get_function_params ().size ()); + for (auto ¶m : fntype.get_function_params ()) { TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ()); - params.push_back (TyTy::TyVar (ptype->get_ref ())); + params.emplace_back (ptype->get_ref ()); } - translated = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), - fntype.get_locus (), std::move (params), - TyTy::TyVar (return_type->get_ref ())); + translated + = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), fntype.get_locus (), + std::move (params), + TyTy::TyVar (return_type->get_ref ()), + fntype.get_function_qualifiers ().get_abi (), + fntype.get_function_qualifiers ().get_unsafety ()); } void @@ -117,10 +123,12 @@ TypeCheckType::visit (HIR::TupleType &tuple) } std::vector<TyTy::TyVar> fields; + fields.reserve (tuple.get_elems ().size ()); + for (auto &elem : tuple.get_elems ()) { auto field_ty = TypeCheckType::Resolve (*elem); - fields.push_back (TyTy::TyVar (field_ty->get_ref ())); + fields.emplace_back (field_ty->get_ref ()); } translated = new TyTy::TupleType (tuple.get_mappings ().get_hirid (), @@ -206,9 +214,9 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) // lookup the associated item from the specified bound HIR::TypePathSegment &item_seg = path.get_associated_segment (); HIR::PathIdentSegment item_seg_identifier = item_seg.get_ident_segment (); - TyTy::TypeBoundPredicateItem item + tl::optional<TyTy::TypeBoundPredicateItem> item = specified_bound.lookup_associated_item (item_seg_identifier.as_string ()); - if (item.is_error ()) + if (!item.has_value ()) { std::string item_seg_ident_name, rich_msg; item_seg_ident_name = qual_path_type.get_trait ().as_string (); @@ -260,7 +268,7 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) // and we dont need to worry if the trait item is actually implemented or // not because this will have already been validated as part of the trait // impl block - translated = item.get_tyty_for_receiver (root); + translated = item->get_tyty_for_receiver (root); } else { @@ -335,19 +343,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, seg->get_lang_item ()); else { - // FIXME: HACK: ARTHUR: Remove this - if (flag_name_resolution_2_0) - { - auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get () - .resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - // assign the ref_node_id if we've found something - nr_ctx.lookup (ast_node_id) - .map ( - [&ref_node_id] (NodeId resolved) { ref_node_id = resolved; }); - } - else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); + // assign the ref_node_id if we've found something + nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) { + ref_node_id = resolved; + }); } // ref_node_id is the NodeId that the segments refers to. @@ -417,8 +419,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, TyTy::BaseType *lookup = nullptr; if (!query_type (ref, &lookup)) { - if (is_root) - return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); + if (is_root || root_tyty == nullptr) + { + rust_error_at (seg->get_locus (), + "failed to resolve type path segment: %qs", + seg->as_string ().c_str ()); + return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); + } return root_tyty; } @@ -544,8 +551,7 @@ TypeCheckType::resolve_segments ( bool selfResolveOk = false; if (first_segment && tySegIsBigSelf - && context->block_context ().is_in_context () - && context->block_context ().peek ().is_impl_block ()) + && context->block_context ().is_in_context ()) { TypeCheckBlockContextItem ctx = context->block_context ().peek (); TyTy::BaseType *lookup = nullptr; @@ -573,6 +579,7 @@ TypeCheckType::resolve_segments ( ignore_mandatory_trait_items); if (candidates.size () == 0) { + prev_segment->debug (); rust_error_at ( seg->get_locus (), "failed to resolve path segment using an impl Probe"); @@ -689,6 +696,7 @@ TypeCheckType::visit (HIR::ParenthesisedType &type) void TypeCheckType::visit (HIR::ArrayType &type) { + auto element_type = TypeCheckType::Resolve (type.get_element_type ()); auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ()); if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) return; @@ -696,18 +704,48 @@ 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); - unify_site (type.get_size_expr ().get_mappings ().get_hirid (), - TyTy::TyWithLocation (expected_ty), - TyTy::TyWithLocation (capacity_type, - type.get_size_expr ().get_locus ()), - type.get_size_expr ().get_locus ()); + TyTy::BaseConstType *const_type = nullptr; + if (capacity_type->get_kind () == TyTy::TypeKind::CONST) + { + const_type = capacity_type->as_const_type (); - TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ()); - translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), - type.get_locus (), type.get_size_expr (), - TyTy::TyVar (base->get_ref ())); + unify_site (type.get_size_expr ().get_mappings ().get_hirid (), + TyTy::TyWithLocation (expected_ty), + TyTy::TyWithLocation (const_type->get_specified_type (), + type.get_size_expr ().get_locus ()), + type.get_size_expr ().get_locus ()); + } + else + { + HirId size_id = type.get_size_expr ().get_mappings ().get_hirid (); + TyTy::BaseType *result + = unify_site (size_id, TyTy::TyWithLocation (expected_ty), + TyTy::TyWithLocation (capacity_type, + type.get_size_expr ().get_locus ()), + type.get_size_expr ().get_locus ()); + + if (result->is<TyTy::ErrorType> ()) + const_type = new TyTy::ConstErrorType (expected_ty, size_id, size_id); + else + { + auto ctx = Compile::Context::get (); + tree capacity_expr + = Compile::HIRCompileBase::query_compile_const_expr ( + ctx, capacity_type, type.get_size_expr ()); + + const_type = new TyTy::ConstValueType (capacity_expr, expected_ty, + size_id, size_id); + context->insert_type (type.get_size_expr ().get_mappings (), + const_type->as_base_type ()); + } + } + + translated + = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (), + TyTy::TyVar ( + const_type->as_base_type ()->get_ref ()), + TyTy::TyVar (element_type->get_ref ())); } void @@ -797,9 +835,10 @@ TypeCheckType::visit (HIR::ImplTraitType &type) } TyTy::ParamType * -TypeResolveGenericParam::Resolve (HIR::GenericParam ¶m, bool apply_sized) +TypeResolveGenericParam::Resolve (HIR::GenericParam ¶m, + bool resolve_trait_bounds, bool apply_sized) { - TypeResolveGenericParam resolver (apply_sized); + TypeResolveGenericParam resolver (apply_sized, resolve_trait_bounds); switch (param.get_kind ()) { case HIR::GenericParam::GenericKind::TYPE: @@ -818,6 +857,14 @@ TypeResolveGenericParam::Resolve (HIR::GenericParam ¶m, bool apply_sized) } void +TypeResolveGenericParam::ApplyAnyTraitBounds (HIR::TypeParam ¶m, + TyTy::ParamType *pty) +{ + TypeResolveGenericParam resolver (true, true); + resolver.apply_trait_bounds (param, pty); +} + +void TypeResolveGenericParam::visit (HIR::LifetimeParam ¶m) { // nothing to do @@ -835,6 +882,18 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) if (param.has_type ()) TypeCheckType::Resolve (param.get_type ()); + resolved = new TyTy::ParamType (param.get_type_representation ().as_string (), + param.get_locus (), + param.get_mappings ().get_hirid (), {}); + + if (resolve_trait_bounds) + apply_trait_bounds (param, resolved); +} + +void +TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m, + TyTy::ParamType *pty) +{ std::unique_ptr<HIR::Type> implicit_self_bound = nullptr; if (param.has_type_param_bounds ()) { @@ -844,7 +903,7 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) HirId implicit_id = mappings.get_next_hir_id (); TyTy::ParamType *p = new TyTy::ParamType (param.get_type_representation ().as_string (), - param.get_locus (), implicit_id, param, + param.get_locus (), implicit_id, {} /*empty specified bounds*/); context->insert_implicit_type (implicit_id, p); @@ -865,8 +924,6 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) // // We can only do this when we are not resolving the implicit Self for Sized // itself - rust_debug_loc (param.get_locus (), "apply_sized: %s", - apply_sized ? "true" : "false"); if (apply_sized) { TyTy::TypeBoundPredicate sized_predicate @@ -882,7 +939,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) { switch (bound->get_bound_type ()) { - case HIR::TypeParamBound::BoundType::TRAITBOUND: { + case HIR::TypeParamBound::BoundType::TRAITBOUND: + { HIR::TraitBound &b = static_cast<HIR::TraitBound &> (*bound); TyTy::TypeBoundPredicate predicate = get_predicate_from_bound ( @@ -894,7 +952,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) { switch (predicate.get_polarity ()) { - case BoundPolarity::AntiBound: { + case BoundPolarity::AntiBound: + { bool found = predicates.find (predicate.get_id ()) != predicates.end (); if (found) @@ -911,7 +970,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) } break; - default: { + default: + { if (predicates.find (predicate.get_id ()) == predicates.end ()) { @@ -941,10 +1001,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) } } - resolved = new TyTy::ParamType (param.get_type_representation ().as_string (), - param.get_locus (), - param.get_mappings ().get_hirid (), param, - specified_bounds); + // inherit them + pty->inherit_bounds (specified_bounds); } void @@ -1009,7 +1067,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) { switch (bound->get_bound_type ()) { - case HIR::TypeParamBound::BoundType::TRAITBOUND: { + case HIR::TypeParamBound::BoundType::TRAITBOUND: + { auto *b = static_cast<HIR::TraitBound *> (bound.get ()); TyTy::TypeBoundPredicate predicate @@ -1018,7 +1077,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) specified_bounds.push_back (std::move (predicate)); } break; - case HIR::TypeParamBound::BoundType::LIFETIME: { + case HIR::TypeParamBound::BoundType::LIFETIME: + { if (auto param = binding->try_as<TyTy::ParamType> ()) { auto *b = static_cast<HIR::Lifetime *> (bound.get ()); @@ -1047,23 +1107,15 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id = nr_ctx.lookup (ast_node_id)) - ref_node_id = *id; - } - else - { - NodeId id = UNKNOWN_NODEID; + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (resolver->lookup_resolved_type (ast_node_id, &id)) - ref_node_id = id; + if (auto id = nr_ctx.lookup (ast_node_id)) + { + ref_node_id = *id; } - - if (ref_node_id == UNKNOWN_NODEID) + else { // FIXME rust_error_at (UNDEF_LOCATION, diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index fc272e6..cc991b6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -91,20 +91,27 @@ class TypeResolveGenericParam : public TypeCheckBase { public: static TyTy::ParamType *Resolve (HIR::GenericParam ¶m, + bool resolve_trait_bounds = true, bool apply_sized = true); + static void ApplyAnyTraitBounds (HIR::TypeParam ¶m, TyTy::ParamType *pty); + protected: void visit (HIR::TypeParam ¶m); void visit (HIR::LifetimeParam ¶m); void visit (HIR::ConstGenericParam ¶m); + void apply_trait_bounds (HIR::TypeParam ¶m, TyTy::ParamType *pty); + private: - TypeResolveGenericParam (bool apply_sized) - : TypeCheckBase (), resolved (nullptr), apply_sized (apply_sized) + TypeResolveGenericParam (bool apply_sized, bool resolve_trait_bounds) + : TypeCheckBase (), resolved (nullptr), apply_sized (apply_sized), + resolve_trait_bounds (resolve_trait_bounds) {} TyTy::ParamType *resolved; bool apply_sized; + bool resolve_trait_bounds; }; class ResolveWhereClauseItem : public TypeCheckBase diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index a198ad3..3215f434 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -26,11 +26,7 @@ #include "rust-hir-type-check-struct-field.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - -extern bool -saw_errors (void); +extern bool saw_errors (void); namespace Rust { namespace Resolver { @@ -165,36 +161,11 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const HIR::TraitFunctionDecl &function = fn.get_decl (); if (function.has_generics ()) { - for (auto &generic_param : function.get_generic_params ()) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: { - auto lifetime_param - = static_cast<HIR::LifetimeParam &> (*generic_param); - - context->intern_and_insert_lifetime ( - lifetime_param.get_lifetime ()); - // TODO: Handle lifetime bounds - } - break; - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - break; - - case HIR::GenericParam::GenericKind::TYPE: { - auto param_type - = TypeResolveGenericParam::Resolve (*generic_param); - context->insert_type (generic_param->get_mappings (), - param_type); - - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast<HIR::TypeParam &> (*generic_param), param_type)); - } - break; - } - } + TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::Function, + fn.get_locus (), + function.get_generic_params (), + substitutions, false /*is_foreign*/, + ABI::RUST); } if (function.has_where_clause ()) @@ -235,7 +206,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const // add the synthetic self param at the front, this is a placeholder // for compilation to know parameter names. The types are ignored // but we reuse the HIR identifier pattern which requires it - HIR::SelfParam &self_param = function.get_self (); + HIR::SelfParam &self_param = function.get_self_unchecked (); std::unique_ptr<HIR::Pattern> self_pattern = std::make_unique<HIR::IdentifierPattern> (HIR::IdentifierPattern ( mapping, {"self"}, self_param.get_locus (), self_param.is_ref (), @@ -258,26 +229,28 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const break; case HIR::SelfParam::IMM_REF: - case HIR::SelfParam::MUT_REF: { + case HIR::SelfParam::MUT_REF: + { auto mutability = self_param.get_self_kind () == HIR::SelfParam::IMM_REF ? Mutability::Imm : 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; @@ -288,7 +261,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const } context->insert_type (self_param.get_mappings (), self_type); - params.push_back (TyTy::FnParam (std::move (self_pattern), self_type)); + params.emplace_back (std::move (self_pattern), self_type); } for (auto ¶m : function.get_function_params ()) @@ -298,30 +271,17 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const context->insert_type (param.get_mappings (), param_tyty); TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); // FIXME: Should we take the name ? Use a shared pointer instead ? - params.push_back ( - TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty)); + params.emplace_back (param.get_param_name ().clone_pattern (), + param_tyty); } - auto &mappings = Analysis::Mappings::get (); - - tl::optional<CanonicalPath> canonical_path; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.values.to_canonical_path (fn.get_mappings ().get_nodeid ()); - } - else - { - canonical_path - = mappings.lookup_canonical_path (fn.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path); + CanonicalPath canonical_path + = nr_ctx.to_canonical_path (fn.get_mappings ().get_nodeid ()); - RustIdent ident{*canonical_path, fn.get_locus ()}; + RustIdent ident{canonical_path, fn.get_locus ()}; auto resolved = new TyTy::FnType ( fn.get_mappings ().get_hirid (), fn.get_mappings ().get_defid (), function.get_function_name ().as_string (), ident, diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 18a65fe..e5a6e9e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -20,6 +20,7 @@ #define RUST_HIR_TYPE_CHECK #include "rust-hir-map.h" +#include "rust-mapping-common.h" #include "rust-tyty.h" #include "rust-hir-trait-reference.h" #include "rust-stacked-contexts.h" @@ -157,6 +158,39 @@ public: WARN_UNUSED_RESULT Lifetime next () { return Lifetime (interner_index++); } }; +struct DeferredOpOverload +{ + HirId expr_id; + LangItem::Kind lang_item_type; + HIR::PathIdentSegment specified_segment; + TyTy::TypeBoundPredicate predicate; + HIR::OperatorExprMeta op; + + DeferredOpOverload (HirId expr_id, LangItem::Kind lang_item_type, + HIR::PathIdentSegment specified_segment, + TyTy::TypeBoundPredicate &predicate, + HIR::OperatorExprMeta op) + : expr_id (expr_id), lang_item_type (lang_item_type), + specified_segment (specified_segment), predicate (predicate), op (op) + {} + + DeferredOpOverload (const struct DeferredOpOverload &other) + : expr_id (other.expr_id), lang_item_type (other.lang_item_type), + specified_segment (other.specified_segment), predicate (other.predicate), + op (other.op) + {} + + DeferredOpOverload &operator= (struct DeferredOpOverload const &other) + { + expr_id = other.expr_id; + lang_item_type = other.lang_item_type; + specified_segment = other.specified_segment; + op = other.op; + + return *this; + } +}; + class TypeCheckContext { public: @@ -215,10 +249,10 @@ public: bool lookup_associated_type_mapping (HirId id, HirId *mapping); void insert_associated_impl_mapping (HirId trait_id, - const TyTy::BaseType *impl_type, + TyTy::BaseType *impl_type, HirId impl_id); bool lookup_associated_impl_mapping_for_self (HirId trait_id, - const TyTy::BaseType *self, + TyTy::BaseType *self, HirId *mapping); void insert_autoderef_mappings (HirId id, @@ -237,6 +271,13 @@ public: void insert_operator_overload (HirId id, TyTy::FnType *call_site); bool lookup_operator_overload (HirId id, TyTy::FnType **call); + void insert_deferred_operator_overload (DeferredOpOverload deferred); + bool lookup_deferred_operator_overload (HirId id, + DeferredOpOverload *deferred); + + void iterate_deferred_operator_overloads ( + std::function<bool (HirId, DeferredOpOverload &)> cb); + void insert_unconstrained_check_marker (HirId id, bool status); bool have_checked_for_unconstrained (HirId id, bool *result); @@ -263,13 +304,16 @@ public: WARN_UNUSED_RESULT std::vector<TyTy::Region> regions_from_generic_args (const HIR::GenericArgs &args) const; - void compute_inference_variables (bool error); + void compute_inference_variables (bool emit_error); TyTy::VarianceAnalysis::CrateCtx &get_variance_analysis_ctx (); private: TypeCheckContext (); + bool compute_infer_var (HirId id, TyTy::BaseType *ty, bool emit_error); + bool compute_ambigious_op_overload (HirId id, DeferredOpOverload &op); + std::map<NodeId, HirId> node_id_refs; std::map<HirId, TyTy::BaseType *> resolved; std::vector<std::unique_ptr<TyTy::BaseType>> builtins; @@ -281,7 +325,7 @@ private: std::map<HirId, AssociatedImplTrait> associated_impl_traits; // trait-id -> list of < self-tyty:impl-id> - std::map<HirId, std::vector<std::pair<const TyTy::BaseType *, HirId>>> + std::map<HirId, std::vector<std::pair<TyTy::BaseType *, HirId>>> associated_traits_to_impls; std::map<HirId, HirId> associated_type_mappings; @@ -306,6 +350,9 @@ private: std::set<HirId> querys_in_progress; std::set<DefId> trait_queries_in_progress; + // deferred operator overload + std::map<HirId, DeferredOpOverload> deferred_operator_overloads; + // variance analysis TyTy::VarianceAnalysis::CrateCtx variance_analysis_ctx; diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc index 212ab3f..238ede4 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.cc +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -34,6 +34,15 @@ SubstMapper::Resolve (TyTy::BaseType *base, location_t locus, HIR::GenericArgs *generics, const std::vector<TyTy::Region> ®ions) { + if (!valid_type (base)) + { + rich_location r (line_table, locus); + r.add_fixit_remove (generics->get_locus ()); + rust_error_at (r, ErrorCode::E0109, + "generic arguments are not allowed for this type"); + return base; + } + SubstMapper mapper (base->get_ref (), generics, regions, locus); base->accept_vis (mapper); rust_assert (mapper.resolved != nullptr); @@ -47,6 +56,17 @@ SubstMapper::InferSubst (TyTy::BaseType *base, location_t locus) } bool +SubstMapper::valid_type (TyTy::BaseType *base) +{ + bool is_fn = base->is<TyTy::FnType> (); + bool is_adt = base->is<TyTy::ADTType> (); + bool is_placeholder = base->is<TyTy::PlaceholderType> (); + bool is_projection = base->is<TyTy::ProjectionType> (); + + return is_fn || is_adt || is_placeholder || is_projection; +} + +bool SubstMapper::have_generic_args () const { return generics != nullptr; @@ -103,7 +123,12 @@ SubstMapper::visit (TyTy::ADTType &type) void SubstMapper::visit (TyTy::PlaceholderType &type) { - rust_assert (type.can_resolve ()); + if (!type.can_resolve ()) + { + resolved = &type; + return; + } + resolved = SubstMapper::Resolve (type.resolve (), locus, generics, regions); } @@ -243,6 +268,30 @@ SubstMapperInternal::visit (TyTy::ParamType &type) } void +SubstMapperInternal::visit (TyTy::ConstParamType &type) +{ + resolved = type.handle_substitions (mappings); +} + +void +SubstMapperInternal::visit (TyTy::ConstValueType &type) +{ + resolved = type.clone (); +} + +void +SubstMapperInternal::visit (TyTy::ConstInferType &type) +{ + resolved = type.clone (); +} + +void +SubstMapperInternal::visit (TyTy::ConstErrorType &type) +{ + resolved = type.clone (); +} + +void SubstMapperInternal::visit (TyTy::PlaceholderType &type) { rust_assert (type.can_resolve ()); @@ -279,15 +328,15 @@ SubstMapperInternal::visit (TyTy::SliceType &type) { resolved = type.handle_substitions (mappings); } - -// nothing to do for these void -SubstMapperInternal::visit (TyTy::InferType &type) +SubstMapperInternal::visit (TyTy::FnPtr &type) { - resolved = type.clone (); + resolved = type.handle_substitions (mappings); } + +// nothing to do for these void -SubstMapperInternal::visit (TyTy::FnPtr &type) +SubstMapperInternal::visit (TyTy::InferType &type) { resolved = type.clone (); } @@ -349,7 +398,7 @@ SubstMapperInternal::visit (TyTy::DynamicObjectType &type) void SubstMapperInternal::visit (TyTy::OpaqueType &type) { - resolved = type.handle_substitions (mappings); + resolved = type.clone (); } // SubstMapperFromExisting diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index bc54f56..98f9e72 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -37,6 +37,8 @@ public: bool have_generic_args () const; + static bool valid_type (TyTy::BaseType *base); + void visit (TyTy::FnType &type) override; void visit (TyTy::ADTType &type) override; void visit (TyTy::PlaceholderType &type) override; @@ -59,6 +61,10 @@ public: void visit (TyTy::ReferenceType &) override { rust_unreachable (); } void visit (TyTy::PointerType &) override { rust_unreachable (); } void visit (TyTy::ParamType &) override { rust_unreachable (); } + void visit (TyTy::ConstParamType &) override { rust_unreachable (); } + void visit (TyTy::ConstValueType &) override { rust_unreachable (); } + void visit (TyTy::ConstInferType &) override { rust_unreachable (); } + void visit (TyTy::ConstErrorType &) override { rust_unreachable (); } void visit (TyTy::StrType &) override { rust_unreachable (); } void visit (TyTy::NeverType &) override { rust_unreachable (); } void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); } @@ -90,6 +96,10 @@ public: void visit (TyTy::ReferenceType &type) override; void visit (TyTy::PointerType &type) override; void visit (TyTy::ParamType &type) override; + void visit (TyTy::ConstParamType &type) override; + void visit (TyTy::ConstValueType &type) override; + void visit (TyTy::ConstInferType &type) override; + void visit (TyTy::ConstErrorType &type) override; void visit (TyTy::PlaceholderType &type) override; void visit (TyTy::ProjectionType &type) override; void visit (TyTy::ClosureType &type) override; @@ -143,12 +153,16 @@ public: void visit (TyTy::ReferenceType &) override { rust_unreachable (); } void visit (TyTy::PointerType &) override { rust_unreachable (); } void visit (TyTy::ParamType &) override { rust_unreachable (); } + void visit (TyTy::ConstParamType &) override { rust_unreachable (); } + void visit (TyTy::ConstValueType &) override { rust_unreachable (); } + void visit (TyTy::ConstInferType &) override { rust_unreachable (); } + void visit (TyTy::ConstErrorType &) override { rust_unreachable (); } void visit (TyTy::StrType &) override { rust_unreachable (); } void visit (TyTy::NeverType &) override { rust_unreachable (); } void visit (TyTy::PlaceholderType &) override { rust_unreachable (); } void visit (TyTy::ProjectionType &) override { rust_unreachable (); } void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); } - void visit (TyTy::OpaqueType &type) override { rust_unreachable (); } + void visit (TyTy::OpaqueType &) override { rust_unreachable (); } private: SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver); @@ -183,12 +197,16 @@ public: void visit (const TyTy::ReferenceType &) override {} void visit (const TyTy::PointerType &) override {} void visit (const TyTy::ParamType &) override {} + void visit (const TyTy::ConstParamType &) override {} + void visit (const TyTy::ConstValueType &) override {} + void visit (const TyTy::ConstInferType &) override {} + void visit (const TyTy::ConstErrorType &) override {} void visit (const TyTy::StrType &) override {} void visit (const TyTy::NeverType &) override {} void visit (const TyTy::PlaceholderType &) override {} void visit (const TyTy::ProjectionType &) override {} void visit (const TyTy::DynamicObjectType &) override {} - void visit (const TyTy::OpaqueType &type) override {} + void visit (const TyTy::OpaqueType &) override {} private: GetUsedSubstArgs (); diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index 4abfbae..a6b9966 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -22,10 +22,14 @@ #include "rust-hir-type-check-implitem.h" #include "rust-hir-type-check-item.h" #include "rust-hir-type-check.h" +#include "rust-hir-type-check-type.h" #include "rust-casts.h" +#include "rust-mapping-common.h" #include "rust-unify.h" #include "rust-coercion.h" #include "rust-hir-type-bounds.h" +#include "rust-immutable-name-resolution-context.h" +#include "options.h" namespace Rust { namespace Resolver { @@ -36,12 +40,12 @@ query_type (HirId reference, TyTy::BaseType **result) auto &mappings = Analysis::Mappings::get (); TypeCheckContext *context = TypeCheckContext::get (); - if (context->query_in_progress (reference)) - return false; - if (context->lookup_type (reference, result)) return true; + if (context->query_in_progress (reference)) + return false; + context->insert_query (reference); std::pair<HIR::Enum *, HIR::EnumItem *> enum_candidiate @@ -91,6 +95,34 @@ query_type (HirId reference, TyTy::BaseType **result) HIR::ImplBlock *impl = impl_block_by_type.value (); rust_debug_loc (impl->get_locus (), "resolved impl block type {%u} to", reference); + + // this could be recursive to the root type + if (impl->has_type ()) + { + HIR::Type &ty = impl->get_type (); + NodeId ref_node_id = UNKNOWN_NODEID; + NodeId ast_node_id = ty.get_mappings ().get_nodeid (); + + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + // assign the ref_node_id if we've found something + nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) { + ref_node_id = resolved; + }); + + if (ref_node_id != UNKNOWN_NODEID) + { + tl::optional<HirId> hid + = mappings.lookup_node_to_hir (ref_node_id); + if (hid.has_value () && context->query_in_progress (hid.value ())) + { + context->query_completed (reference); + return false; + } + } + } + *result = TypeCheckItem::ResolveImplBlockSelf (*impl); context->query_completed (reference); return true; @@ -120,11 +152,12 @@ query_type (HirId reference, TyTy::BaseType **result) bool types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors) + location_t unify_locus, bool emit_errors, bool check_bounds) { TyTy::BaseType *result = unify_site_and (UNKNOWN_HIRID, lhs, rhs, unify_locus, emit_errors, - false /*commit*/, true /*infer*/, true /*cleanup*/); + false /*commit*/, true /*infer*/, true /*cleanup*/, + check_bounds); return result->get_kind () != TyTy::TypeKind::ERROR; } @@ -141,31 +174,44 @@ unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, std::vector<UnifyRules::CommitSite> commits; std::vector<UnifyRules::InferenceSite> infers; return UnifyRules::Resolve (lhs, rhs, unify_locus, true /*commit*/, - true /*emit_error*/, false /*infer*/, commits, - infers); + true /*emit_error*/, false /*infer*/, + true /*check_bounds*/, commits, infers); } TyTy::BaseType * unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t unify_locus, bool emit_errors, bool commit_if_ok, - bool implicit_infer_vars, bool cleanup) + bool implicit_infer_vars, bool cleanup, bool check_bounds) { TypeCheckContext &context = *TypeCheckContext::get (); TyTy::BaseType *expected = lhs.get_ty (); TyTy::BaseType *expr = rhs.get_ty (); - rust_debug ( - "unify_site_and commit %s infer %s id={%u} expected={%s} expr={%s}", - commit_if_ok ? "true" : "false", implicit_infer_vars ? "true" : "false", id, - expected->debug_str ().c_str (), expr->debug_str ().c_str ()); + rust_debug_loc (unify_locus, + "begin unify_site_and commit %s infer %s check_bounds %s " + "id={%u} expected={%s} expr={%s}", + commit_if_ok ? "true" : "false", + implicit_infer_vars ? "true" : "false", + check_bounds ? "true" : "false", id == UNKNOWN_HIRID ? 0 : id, + expected->debug_str ().c_str (), expr->debug_str ().c_str ()); std::vector<UnifyRules::CommitSite> commits; std::vector<UnifyRules::InferenceSite> infers; TyTy::BaseType *result = UnifyRules::Resolve (lhs, rhs, unify_locus, false /*commit inline*/, - emit_errors, implicit_infer_vars, commits, infers); + emit_errors, implicit_infer_vars, check_bounds, + commits, infers); bool ok = result->get_kind () != TyTy::TypeKind::ERROR; + + rust_debug_loc (unify_locus, + "unify_site_and done ok=%s commit %s infer %s id={%u} " + "expected={%s} expr={%s}", + ok ? "true" : "false", commit_if_ok ? "true" : "false", + implicit_infer_vars ? "true" : "false", + id == UNKNOWN_HIRID ? 0 : id, expected->debug_str ().c_str (), + expr->debug_str ().c_str ()); + if (ok && commit_if_ok) { for (auto &c : commits) @@ -175,17 +221,18 @@ 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); - delete i.infer; + // FIXME: Don't delete - result might point to this + // delete i.infer; } } return result; @@ -282,7 +329,7 @@ cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to, AssociatedImplTrait * lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound, - const TyTy::BaseType *binding, bool *ambigious) + TyTy::BaseType *binding, bool *ambigious) { auto context = TypeCheckContext::get (); diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h index 03874a4..7f4a94e 100644 --- a/gcc/rust/typecheck/rust-type-util.h +++ b/gcc/rust/typecheck/rust-type-util.h @@ -25,37 +25,35 @@ namespace Rust { namespace Resolver { -bool -query_type (HirId reference, TyTy::BaseType **result); +bool query_type (HirId reference, TyTy::BaseType **result); -bool -types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors); +bool types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, + location_t unify_locus, bool emit_errors, + bool check_bounds = true); -TyTy::BaseType * -unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus); +TyTy::BaseType *unify_site (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, location_t unify_locus); -TyTy::BaseType * -unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors, bool commit_if_ok, - bool implicit_infer_vars, bool cleanup); +TyTy::BaseType *unify_site_and (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t unify_locus, bool emit_errors, + bool commit_if_ok, bool implicit_infer_vars, + bool cleanup, bool check_bounds = true); -TyTy::BaseType * -coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t coercion_locus); +TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t coercion_locus); -TyTy::BaseType * -try_coercion (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t coercion_locus); +TyTy::BaseType *try_coercion (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t coercion_locus); -TyTy::BaseType * -cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to, - location_t cast_locus); +TyTy::BaseType *cast_site (HirId id, TyTy::TyWithLocation from, + TyTy::TyWithLocation to, location_t cast_locus); AssociatedImplTrait * lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound, - const TyTy::BaseType *binding, + TyTy::BaseType *binding, bool *ambigious = nullptr); } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc index f02e484..3419ef6 100644 --- a/gcc/rust/typecheck/rust-typecheck-context.cc +++ b/gcc/rust/typecheck/rust-typecheck-context.cc @@ -18,6 +18,7 @@ #include "rust-hir-type-check.h" #include "rust-type-util.h" +#include "rust-hir-type-check-expr.h" namespace Rust { namespace Resolver { @@ -153,7 +154,7 @@ void TypeCheckContext::push_return_type (TypeCheckContextItem item, TyTy::BaseType *return_type) { - return_type_stack.push_back ({std::move (item), return_type}); + return_type_stack.emplace_back (std::move (item), return_type); } void @@ -299,8 +300,9 @@ TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping) } void -TypeCheckContext::insert_associated_impl_mapping ( - HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id) +TypeCheckContext::insert_associated_impl_mapping (HirId trait_id, + TyTy::BaseType *impl_type, + HirId impl_id) { auto it = associated_traits_to_impls.find (trait_id); if (it == associated_traits_to_impls.end ()) @@ -308,12 +310,13 @@ TypeCheckContext::insert_associated_impl_mapping ( associated_traits_to_impls[trait_id] = {}; } - associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id}); + associated_traits_to_impls[trait_id].emplace_back (impl_type, impl_id); } bool -TypeCheckContext::lookup_associated_impl_mapping_for_self ( - HirId trait_id, const TyTy::BaseType *self, HirId *mapping) +TypeCheckContext::lookup_associated_impl_mapping_for_self (HirId trait_id, + TyTy::BaseType *self, + HirId *mapping) { auto it = associated_traits_to_impls.find (trait_id); if (it == associated_traits_to_impls.end ()) @@ -321,7 +324,9 @@ TypeCheckContext::lookup_associated_impl_mapping_for_self ( for (auto &item : it->second) { - if (item.first->can_eq (self, false)) + if (types_compatable (TyTy::TyWithLocation (item.first), + TyTy::TyWithLocation (self), UNKNOWN_LOCATION, + false)) { *mapping = item.second; return true; @@ -409,6 +414,38 @@ TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call) } void +TypeCheckContext::insert_deferred_operator_overload ( + DeferredOpOverload deferred) +{ + HirId expr_id = deferred.expr_id; + deferred_operator_overloads.emplace (std::make_pair (expr_id, deferred)); +} + +bool +TypeCheckContext::lookup_deferred_operator_overload ( + HirId id, DeferredOpOverload *deferred) +{ + auto it = deferred_operator_overloads.find (id); + if (it == deferred_operator_overloads.end ()) + return false; + + *deferred = it->second; + return true; +} + +void +TypeCheckContext::iterate_deferred_operator_overloads ( + std::function<bool (HirId, DeferredOpOverload &)> cb) +{ + for (auto it = deferred_operator_overloads.begin (); + it != deferred_operator_overloads.end (); it++) + { + if (!cb (it->first, it->second)) + return; + } +} + +void TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status) { unconstrained[id] = status; @@ -514,7 +551,16 @@ TypeCheckContext::lookup_lifetime (const HIR::Lifetime &lifetime) const { if (lifetime.get_lifetime_type () == AST::Lifetime::NAMED) { - rust_assert (lifetime.get_name () != "static"); + if (lifetime.get_name () == "static") + { + rich_location r (line_table, lifetime.get_locus ()); + r.add_fixit_insert_after (lifetime.get_locus (), + "static is a reserved lifetime name"); + rust_error_at (r, ErrorCode::E0262, + "invalid lifetime parameter name: %qs", + lifetime.get_name ().c_str ()); + return tl::nullopt; + } const auto name = lifetime.get_name (); auto it = lifetime_name_interner.find (name); if (it == lifetime_name_interner.end ()) @@ -565,44 +611,77 @@ TypeCheckContext::regions_from_generic_args (const HIR::GenericArgs &args) const return regions; } +bool +TypeCheckContext::compute_ambigious_op_overload (HirId id, + DeferredOpOverload &op) +{ + rust_debug ("attempting resolution of op overload: %s", + op.predicate.as_string ().c_str ()); + + TyTy::BaseType *lhs = nullptr; + bool ok = lookup_type (op.op.get_lvalue_mappings ().get_hirid (), &lhs); + rust_assert (ok); + + TyTy::BaseType *rhs = nullptr; + if (op.op.has_rvalue_mappings ()) + { + bool ok = lookup_type (op.op.get_rvalue_mappings ().get_hirid (), &rhs); + rust_assert (ok); + } + + TypeCheckExpr::ResolveOpOverload (op.lang_item_type, op.op, lhs, rhs, + op.specified_segment); + + return true; +} + void -TypeCheckContext::compute_inference_variables (bool error) +TypeCheckContext::compute_inference_variables (bool emit_error) { - auto &mappings = Analysis::Mappings::get (); + iterate_deferred_operator_overloads ( + [&] (HirId id, DeferredOpOverload &op) mutable -> bool { + return compute_ambigious_op_overload (id, op); + }); - // default inference variables if possible iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool { - // nothing to do - if (ty->get_kind () != TyTy::TypeKind::INFER) - return true; + return compute_infer_var (id, ty, emit_error); + }); +} - TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty); - TyTy::BaseType *default_type; - - rust_debug_loc (mappings.lookup_location (id), - "trying to default infer-var: %s", - infer_var->as_string ().c_str ()); - bool ok = infer_var->default_type (&default_type); - if (!ok) - { - if (error) - rust_error_at (mappings.lookup_location (id), ErrorCode::E0282, - "type annotations needed"); - return true; - } - - auto result - = unify_site (id, TyTy::TyWithLocation (ty), - TyTy::TyWithLocation (default_type), UNDEF_LOCATION); - rust_assert (result); - rust_assert (result->get_kind () != TyTy::TypeKind::ERROR); - result->set_ref (id); - insert_type (Analysis::NodeMapping (mappings.get_current_crate (), 0, id, - UNKNOWN_LOCAL_DEFID), - result); +bool +TypeCheckContext::compute_infer_var (HirId id, TyTy::BaseType *ty, + bool emit_error) +{ + auto &mappings = Analysis::Mappings::get (); + // nothing to do + if (ty->get_kind () != TyTy::TypeKind::INFER) return true; - }); + + TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty); + TyTy::BaseType *default_type; + + rust_debug_loc (mappings.lookup_location (id), + "trying to default infer-var: %s", + infer_var->as_string ().c_str ()); + bool ok = infer_var->default_type (&default_type); + if (!ok) + { + if (emit_error) + rust_error_at (mappings.lookup_location (id), ErrorCode::E0282, + "type annotations needed"); + return true; + } + + auto result + = unify_site (id, TyTy::TyWithLocation (ty), + TyTy::TyWithLocation (default_type), UNDEF_LOCATION); + rust_assert (result); + rust_assert (result->get_kind () != TyTy::TypeKind::ERROR); + result->set_ref (id); + insert_implicit_type (id, result); + + return true; } TyTy::VarianceAnalysis::CrateCtx & diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index e028a0a..a59de99 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -26,12 +26,12 @@ namespace Rust { namespace Resolver { -TypeBoundsProbe::TypeBoundsProbe (const TyTy::BaseType *receiver) +TypeBoundsProbe::TypeBoundsProbe (TyTy::BaseType *receiver) : TypeCheckBase (), receiver (receiver) {} std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> -TypeBoundsProbe::Probe (const TyTy::BaseType *receiver) +TypeBoundsProbe::Probe (TyTy::BaseType *receiver) { TypeBoundsProbe probe (receiver); probe.scan (); @@ -61,6 +61,35 @@ TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver, return false; } +bool +TypeBoundsProbe::process_impl_block ( + HirId id, HIR::ImplBlock *impl, + std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>> + &possible_trait_paths) +{ + // we are filtering for trait-impl-blocks + if (!impl->has_trait_ref ()) + return true; + + // can be recursive trait resolution + HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ()); + if (t == nullptr) + return true; + + HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid (); + TyTy::BaseType *impl_type = nullptr; + if (!query_type (impl_ty_id, &impl_type)) + return true; + + if (!types_compatable (TyTy::TyWithLocation (receiver), + TyTy::TyWithLocation (impl_type), impl->get_locus (), + false /*emit_errors*/, false /*check-bounds*/)) + return true; + + possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl); + return true; +} + void TypeBoundsProbe::scan () { @@ -68,31 +97,7 @@ TypeBoundsProbe::scan () possible_trait_paths; mappings.iterate_impl_blocks ( [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool { - // we are filtering for trait-impl-blocks - if (!impl->has_trait_ref ()) - return true; - - // can be recursive trait resolution - HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ()); - if (t == nullptr) - return true; - DefId trait_id = t->get_mappings ().get_defid (); - if (context->trait_query_in_progress (trait_id)) - return true; - - HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid (); - TyTy::BaseType *impl_type = nullptr; - if (!query_type (impl_ty_id, &impl_type)) - return true; - - if (!receiver->can_eq (impl_type, false)) - { - if (!impl_type->can_eq (receiver, false)) - return true; - } - - possible_trait_paths.push_back ({&impl->get_trait_ref (), impl}); - return true; + return process_impl_block (id, impl, possible_trait_paths); }); for (auto &path : possible_trait_paths) @@ -101,11 +106,11 @@ TypeBoundsProbe::scan () TraitReference *trait_ref = TraitResolver::Resolve (*trait_path); if (!trait_ref->is_error ()) - trait_references.push_back ({trait_ref, path.second}); + trait_references.emplace_back (trait_ref, path.second); } // marker traits... - assemble_sized_builtin (); + assemble_marker_builtins (); // add auto trait bounds for (auto *auto_trait : mappings.get_auto_traits ()) @@ -113,7 +118,7 @@ TypeBoundsProbe::scan () } void -TypeBoundsProbe::assemble_sized_builtin () +TypeBoundsProbe::assemble_marker_builtins () { const TyTy::BaseType *raw = receiver->destructure (); @@ -132,7 +137,6 @@ TypeBoundsProbe::assemble_sized_builtin () case TyTy::POINTER: case TyTy::PARAM: case TyTy::FNDEF: - case TyTy::FNPTR: case TyTy::BOOL: case TyTy::CHAR: case TyTy::INT: @@ -140,7 +144,6 @@ TypeBoundsProbe::assemble_sized_builtin () case TyTy::FLOAT: case TyTy::USIZE: case TyTy::ISIZE: - case TyTy::CLOSURE: case TyTy::INFER: case TyTy::NEVER: case TyTy::PLACEHOLDER: @@ -149,6 +152,14 @@ TypeBoundsProbe::assemble_sized_builtin () assemble_builtin_candidate (LangItem::Kind::SIZED); break; + case TyTy::FNPTR: + case TyTy::CLOSURE: + assemble_builtin_candidate (LangItem::Kind::SIZED); + assemble_builtin_candidate (LangItem::Kind::FN_ONCE); + assemble_builtin_candidate (LangItem::Kind::FN); + assemble_builtin_candidate (LangItem::Kind::FN_MUT); + break; + // FIXME str and slice need to be moved and test cases updated case TyTy::SLICE: case TyTy::STR: @@ -158,6 +169,7 @@ TypeBoundsProbe::assemble_sized_builtin () assemble_builtin_candidate (LangItem::Kind::SIZED); break; + case TyTy::CONST: case TyTy::DYNAMIC: case TyTy::ERROR: break; @@ -169,7 +181,7 @@ TypeBoundsProbe::add_trait_bound (HIR::Trait *trait) { auto trait_ref = TraitResolver::Resolve (*trait); - trait_references.push_back ({trait_ref, mappings.lookup_builtin_marker ()}); + trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ()); } void @@ -206,7 +218,7 @@ TyTy::TypeBoundPredicate TypeCheckBase::get_predicate_from_bound ( HIR::TypePath &type_path, tl::optional<std::reference_wrapper<HIR::Type>> associated_self, - BoundPolarity polarity, bool is_qualified_type_path) + BoundPolarity polarity, bool is_qualified_type_path, bool is_super_trait) { TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error (); bool already_resolved @@ -226,7 +238,8 @@ TypeCheckBase::get_predicate_from_bound ( auto &final_seg = type_path.get_final_segment (); switch (final_seg.get_type ()) { - case HIR::TypePathSegment::SegmentType::GENERIC: { + case HIR::TypePathSegment::SegmentType::GENERIC: + { auto &final_generic_seg = static_cast<HIR::TypePathSegmentGeneric &> (final_seg); if (final_generic_seg.has_generic_args ()) @@ -251,7 +264,8 @@ TypeCheckBase::get_predicate_from_bound ( } break; - case HIR::TypePathSegment::SegmentType::FUNCTION: { + case HIR::TypePathSegment::SegmentType::FUNCTION: + { auto &final_function_seg = static_cast<HIR::TypePathSegmentFunction &> (final_seg); auto &fn = final_function_seg.get_function_path (); @@ -288,11 +302,9 @@ TypeCheckBase::get_predicate_from_bound ( std::vector<HIR::GenericArgsBinding> bindings; location_t output_locus = fn.get_return_type ().get_locus (); - HIR::GenericArgsBinding binding (Identifier ( - trait_item->trait_identifier ()), - fn.get_return_type ().clone_type (), - output_locus); - bindings.push_back (std::move (binding)); + bindings.emplace_back (Identifier (trait_item->trait_identifier ()), + fn.get_return_type ().clone_type (), + output_locus); args = HIR::GenericArgs ({} /* lifetimes */, std::move (inputs) /* type_args*/, @@ -327,7 +339,8 @@ TypeCheckBase::get_predicate_from_bound ( if (!args.is_empty () || predicate.requires_generic_args ()) { // this is applying generic arguments to a trait reference - predicate.apply_generic_arguments (&args, associated_self.has_value ()); + predicate.apply_generic_arguments (&args, associated_self.has_value (), + is_super_trait); } context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (), @@ -449,8 +462,8 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate &other) { TyTy::BaseType *argument = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone (); - SubstitutionArg c (&substitutions.at (i++), argument); - copied_arg_mappings.push_back (std::move (c)); + + copied_arg_mappings.emplace_back (&substitutions.at (i++), argument); } used_arguments @@ -508,7 +521,8 @@ TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const void TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args, - bool has_associated_self) + bool has_associated_self, + bool is_super_trait) { rust_assert (!substitutions.empty ()); if (has_associated_self) @@ -529,23 +543,26 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args, Resolver::TypeCheckContext::get ()->regions_from_generic_args ( *generic_args)); - apply_argument_mappings (args); + apply_argument_mappings (args, is_super_trait); } void TypeBoundPredicate::apply_argument_mappings ( - SubstitutionArgumentMappings &arguments) + SubstitutionArgumentMappings &arguments, bool is_super_trait) { used_arguments = arguments; error_flag |= used_arguments.is_error (); auto &subst_mappings = used_arguments; + + bool substs_need_bounds_check = !is_super_trait; for (auto &sub : get_substs ()) { SubstitutionArg arg = SubstitutionArg::error (); bool ok = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg); if (ok && arg.get_tyty () != nullptr) - sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ()); + sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (), + substs_need_bounds_check); } // associated argument mappings @@ -554,10 +571,13 @@ TypeBoundPredicate::apply_argument_mappings ( std::string identifier = it.first; TyTy::BaseType *type = it.second; - TypeBoundPredicateItem item = lookup_associated_item (identifier); - rust_assert (!item.is_error ()); + tl::optional<TypeBoundPredicateItem> item + = lookup_associated_item (identifier); + + if (!item.has_value ()) + continue; - const auto item_ref = item.get_raw_item (); + const auto item_ref = item->get_raw_item (); item_ref->associated_type_set (type); } @@ -566,7 +586,7 @@ TypeBoundPredicate::apply_argument_mappings ( auto adjusted = super_trait.adjust_mappings_for_this (used_arguments, true /*trait mode*/); - super_trait.apply_argument_mappings (adjusted); + super_trait.apply_argument_mappings (adjusted, is_super_trait); } } @@ -578,7 +598,7 @@ TypeBoundPredicate::contains_item (const std::string &search) const return trait_ref->lookup_trait_item (search, &trait_item_ref); } -TypeBoundPredicateItem +tl::optional<TypeBoundPredicateItem> TypeBoundPredicate::lookup_associated_item (const std::string &search) const { auto trait_ref = get (); @@ -590,11 +610,11 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const for (auto &super_trait : super_traits) { auto lookup = super_trait.lookup_associated_item (search); - if (!lookup.is_error ()) + if (lookup.has_value ()) return lookup; } - return TypeBoundPredicateItem::error (); + return tl::nullopt; } TypeBoundPredicateItem::TypeBoundPredicateItem ( @@ -635,7 +655,7 @@ TypeBoundPredicateItem::get_parent () const return &parent; } -TypeBoundPredicateItem +tl::optional<TypeBoundPredicateItem> TypeBoundPredicate::lookup_associated_item ( const Resolver::TraitItemReference *ref) const { @@ -668,8 +688,7 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver) TyTy::BaseType *argument = is_implicit_self ? receiver->clone () : mapping.get_tyty (); - SubstitutionArg arg (mapping.get_param_mapping (), argument); - adjusted_mappings.push_back (std::move (arg)); + adjusted_mappings.emplace_back (mapping.get_param_mapping (), argument); } SubstitutionArgumentMappings adjusted (adjusted_mappings, {}, @@ -699,7 +718,7 @@ TypeBoundPredicate::handle_substitions ( if (sub.get_param_ty () == nullptr) continue; - ParamType *p = sub.get_param_ty (); + auto p = sub.get_param_ty (); BaseType *r = p->resolve (); BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings); @@ -712,10 +731,11 @@ TypeBoundPredicate::handle_substitions ( std::string identifier = it.first; TyTy::BaseType *type = it.second; - TypeBoundPredicateItem item = lookup_associated_item (identifier); - if (!item.is_error ()) + tl::optional<TypeBoundPredicateItem> item + = lookup_associated_item (identifier); + if (item.has_value ()) { - const auto item_ref = item.get_raw_item (); + const auto item_ref = item->get_raw_item (); item_ref->associated_type_set (type); } } @@ -746,33 +766,51 @@ size_t TypeBoundPredicate::get_num_associated_bindings () const { size_t count = 0; + + get_trait_hierachy ([&count] (const Resolver::TraitReference &ref) { + for (const auto &trait_item : ref.get_trait_items ()) + { + bool is_associated_type + = trait_item.get_trait_item_type () + == Resolver::TraitItemReference::TraitItemType::TYPE; + if (is_associated_type) + count++; + } + }); + + return count; +} + +void +TypeBoundPredicate::get_trait_hierachy ( + std::function<void (const Resolver::TraitReference &)> callback) const +{ auto trait_ref = get (); - for (const auto &trait_item : trait_ref->get_trait_items ()) + callback (*trait_ref); + + for (auto &super : super_traits) { - bool is_associated_type - = trait_item.get_trait_item_type () - == Resolver::TraitItemReference::TraitItemType::TYPE; - if (is_associated_type) - count++; + const auto &super_trait_ref = *super.get (); + callback (super_trait_ref); + super.get_trait_hierachy (callback); } - return count; } TypeBoundPredicateItem TypeBoundPredicate::lookup_associated_type (const std::string &search) { - TypeBoundPredicateItem item = lookup_associated_item (search); + tl::optional<TypeBoundPredicateItem> item = lookup_associated_item (search); // only need to check that it is infact an associated type because other // wise if it was not found it will just be an error node anyway - if (!item.is_error ()) + if (item.has_value ()) { - const auto raw = item.get_raw_item (); + const auto raw = item->get_raw_item (); if (raw->get_trait_item_type () != Resolver::TraitItemReference::TraitItemType::TYPE) return TypeBoundPredicateItem::error (); } - return item; + return item.value (); } std::vector<TypeBoundPredicateItem> @@ -786,10 +824,7 @@ TypeBoundPredicate::get_associated_type_items () = trait_item.get_trait_item_type () == Resolver::TraitItemReference::TraitItemType::TYPE; if (is_associated_type) - { - TypeBoundPredicateItem item (*this, &trait_item); - items.push_back (std::move (item)); - } + items.emplace_back (*this, &trait_item); } return items; } @@ -808,21 +843,19 @@ TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const // then match the generics applied for (size_t i = 0; i < get_num_substitutions (); i++) { - const SubstitutionParamMapping &a = substitutions.at (i); - const SubstitutionParamMapping &b = other.substitutions.at (i); + SubstitutionParamMapping a = substitutions.at (i); + SubstitutionParamMapping b = other.substitutions.at (i); - const ParamType *ap = a.get_param_ty (); - const ParamType *bp = b.get_param_ty (); + auto ap = a.get_param_ty (); + auto bp = b.get_param_ty (); - const BaseType *apd = ap->destructure (); - const BaseType *bpd = bp->destructure (); + BaseType *apd = ap->destructure (); + BaseType *bpd = bp->destructure (); - // FIXME use the unify_and infer inteface or try coerce - if (!apd->can_eq (bpd, false /*emit_errors*/)) - { - if (!bpd->can_eq (apd, false /*emit_errors*/)) - return false; - } + if (!Resolver::types_compatable (TyTy::TyWithLocation (apd), + TyTy::TyWithLocation (bpd), + UNKNOWN_LOCATION, false)) + return false; } return true; 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-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 2e0830e..e82e618 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -59,7 +59,7 @@ TypeCheckCallExpr::visit (ADTType &type) if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE) { rust_error_at ( - call.get_locus (), ErrorCode::E0423, + call.get_locus (), ErrorCode::E0618, "expected function, tuple struct or tuple variant, found struct %qs", type.get_name ().c_str ()); return; @@ -171,7 +171,8 @@ TypeCheckCallExpr::visit (FnType &type) { case TyTy::TypeKind::ERROR: return; - case TyTy::TypeKind::INT: { + case TyTy::TypeKind::INT: + { auto &int_ty = static_cast<TyTy::IntType &> (*argument_expr_tyty); if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8) @@ -186,7 +187,8 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::UINT: { + case TyTy::TypeKind::UINT: + { auto &uint_ty = static_cast<TyTy::UintType &> (*argument_expr_tyty); if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8) @@ -202,7 +204,8 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::FLOAT: { + case TyTy::TypeKind::FLOAT: + { if (static_cast<TyTy::FloatType &> (*argument_expr_tyty) .get_float_kind () == TyTy::FloatType::FloatKind::F32) @@ -216,14 +219,16 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::BOOL: { + case TyTy::TypeKind::BOOL: + { rich_location richloc (line_table, arg_locus); richloc.add_fixit_replace ("cast the value to c_int: as c_int"); rust_error_at (arg_locus, ErrorCode::E0617, "expected %<c_int%> variadic argument"); return; } - case TyTy::TypeKind::FNDEF: { + case TyTy::TypeKind::FNDEF: + { rust_error_at ( arg_locus, ErrorCode::E0617, "unexpected function definition type as variadic " @@ -246,7 +251,7 @@ TypeCheckCallExpr::visit (FnType &type) } type.monomorphize (); - resolved = type.get_return_type ()->clone (); + resolved = type.get_return_type ()->monomorphized_clone (); } void @@ -322,8 +327,8 @@ TypeCheckMethodCallExpr::go (FnType *ref, HIR::MethodCallExpr &call, return new ErrorType (ref->get_ref ()); } - Argument a (arg->get_mappings (), argument_expr_tyty, arg->get_locus ()); - args.push_back (std::move (a)); + args.emplace_back (arg->get_mappings (), argument_expr_tyty, + arg->get_locus ()); } TypeCheckMethodCallExpr checker (call.get_mappings (), args, diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index c42fdcd..025a1ad 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -60,8 +60,12 @@ public: void visit (PlaceholderType &) override { rust_unreachable (); } void visit (ProjectionType &) override { rust_unreachable (); } void visit (DynamicObjectType &) override { rust_unreachable (); } - void visit (ClosureType &type) override { rust_unreachable (); } - void visit (OpaqueType &type) override { rust_unreachable (); } + void visit (ClosureType &) override { rust_unreachable (); } + void visit (OpaqueType &) override { rust_unreachable (); } + void visit (ConstParamType &) override { rust_unreachable (); } + void visit (ConstValueType &) override { rust_unreachable (); } + void visit (ConstInferType &) override { rust_unreachable (); } + void visit (ConstErrorType &) override { rust_unreachable (); } // tuple-structs void visit (ADTType &type) override; diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h deleted file mode 100644 index c897c13..0000000 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ /dev/null @@ -1,1610 +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_CMP_H -#define RUST_TYTY_CMP_H - -#include "rust-diagnostics.h" -#include "rust-tyty.h" -#include "rust-tyty-visitor.h" -#include "rust-hir-map.h" -#include "rust-hir-type-check.h" - -namespace Rust { -namespace TyTy { - -class BaseCmp : public TyConstVisitor -{ -public: - virtual bool can_eq (const BaseType *other) - { - if (other->get_kind () == TypeKind::PARAM) - { - const ParamType *p = static_cast<const ParamType *> (other); - other = p->resolve (); - } - if (other->get_kind () == TypeKind::PLACEHOLDER) - { - const PlaceholderType *p = static_cast<const PlaceholderType *> (other); - if (p->can_resolve ()) - { - other = p->resolve (); - } - } - if (other->get_kind () == TypeKind::PROJECTION) - { - const ProjectionType *p = static_cast<const ProjectionType *> (other); - other = p->get (); - } - - other->accept_vis (*this); - return ok; - } - - virtual void visit (const TupleType &type) override - { - ok = false; - - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ADTType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const InferType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const FnType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const FnPtr &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ArrayType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const SliceType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const BoolType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const IntType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const UintType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const USizeType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ISizeType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const FloatType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ErrorType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const CharType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ReferenceType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const PointerType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const StrType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const NeverType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ProjectionType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const PlaceholderType &type) override - { - // it is ok for types to can eq to a placeholder - ok = true; - } - - virtual void visit (const ParamType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const DynamicObjectType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ClosureType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const OpaqueType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - -protected: - BaseCmp (const BaseType *base, bool emit_errors) - : mappings (Analysis::Mappings::get ()), - context (Resolver::TypeCheckContext::get ()), ok (false), - emit_error_flag (emit_errors) - {} - - Analysis::Mappings &mappings; - Resolver::TypeCheckContext *context; - - bool ok; - bool emit_error_flag; - -private: - /* Returns a pointer to the ty that created this rule. */ - virtual const BaseType *get_base () const = 0; -}; - -class InferCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - InferCmp (const InferType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const BoolType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const IntType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const UintType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const USizeType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ISizeType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const FloatType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ArrayType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const SliceType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ADTType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const TupleType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const InferType &type) override - { - switch (base->get_infer_kind ()) - { - case InferType::InferTypeKind::GENERAL: - ok = true; - return; - - case InferType::InferTypeKind::INTEGRAL: { - if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) - { - ok = true; - return; - } - else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL) - { - ok = true; - return; - } - } - break; - - case InferType::InferTypeKind::FLOAT: { - if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) - { - ok = true; - return; - } - else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL) - { - ok = true; - return; - } - } - break; - } - - BaseCmp::visit (type); - } - - void visit (const CharType &type) override - { - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - } - - void visit (const ReferenceType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const PointerType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ParamType &) override { ok = true; } - - void visit (const DynamicObjectType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ClosureType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - -private: - const BaseType *get_base () const override { return base; } - const InferType *base; -}; - -class FnCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - FnCmp (const FnType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; - } - - void visit (const FnType &type) override - { - if (base->num_params () != type.num_params ()) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto a = base->param_at (i).get_type (); - auto b = type.param_at (i).get_type (); - - if (!a->can_eq (b, emit_error_flag)) - { - emit_error_flag = false; - BaseCmp::visit (type); - return; - } - } - - if (!base->get_return_type ()->can_eq (type.get_return_type (), - emit_error_flag)) - { - emit_error_flag = false; - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const FnType *base; -}; - -class FnptrCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - FnptrCmp (const FnPtr *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const FnPtr &type) override - { - if (base->num_params () != type.num_params ()) - { - BaseCmp::visit (type); - return; - } - - auto this_ret_type = base->get_return_type (); - auto other_ret_type = type.get_return_type (); - if (!this_ret_type->can_eq (other_ret_type, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto this_param = base->get_param_type_at (i); - auto other_param = type.get_param_type_at (i); - if (!this_param->can_eq (other_param, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - } - - ok = true; - } - - void visit (const FnType &type) override - { - if (base->num_params () != type.num_params ()) - { - BaseCmp::visit (type); - return; - } - - auto this_ret_type = base->get_return_type (); - auto other_ret_type = type.get_return_type (); - if (!this_ret_type->can_eq (other_ret_type, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto this_param = base->get_param_type_at (i); - auto other_param = type.param_at (i).get_type (); - if (!this_param->can_eq (other_param, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const FnPtr *base; -}; - -class ClosureCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ClosureCmp (const ClosureType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const ClosureType &type) override - { - if (base->get_def_id () != type.get_def_id ()) - { - BaseCmp::visit (type); - return; - } - - if (!base->get_parameters ().can_eq (&type.get_parameters (), false)) - { - BaseCmp::visit (type); - return; - } - - if (!base->get_result_type ().can_eq (&type.get_result_type (), false)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const ClosureType *base; -}; - -class ArrayCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ArrayCmp (const ArrayType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const ArrayType &type) override - { - // check base type - const BaseType *base_element = base->get_element_type (); - const BaseType *other_element = type.get_element_type (); - if (!base_element->can_eq (other_element, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const ArrayType *base; -}; - -class SliceCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - SliceCmp (const SliceType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const SliceType &type) override - { - // check base type - const BaseType *base_element = base->get_element_type (); - const BaseType *other_element = type.get_element_type (); - if (!base_element->can_eq (other_element, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const SliceType *base; -}; - -class BoolCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - BoolCmp (const BoolType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const BoolType &type) override { ok = true; } - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; - } - -private: - const BaseType *get_base () const override { return base; } - const BoolType *base; -}; - -class IntCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - IntCmp (const IntType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT; - } - - void visit (const IntType &type) override - { - ok = type.get_int_kind () == base->get_int_kind (); - } - -private: - const BaseType *get_base () const override { return base; } - const IntType *base; -}; - -class UintCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - UintCmp (const UintType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT; - } - - void visit (const UintType &type) override - { - ok = type.get_uint_kind () == base->get_uint_kind (); - } - -private: - const BaseType *get_base () const override { return base; } - const UintType *base; -}; - -class FloatCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - FloatCmp (const FloatType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::INTEGRAL; - } - - void visit (const FloatType &type) override - { - ok = type.get_float_kind () == base->get_float_kind (); - } - -private: - const BaseType *get_base () const override { return base; } - const FloatType *base; -}; - -class ADTCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ADTCmp (const ADTType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const ADTType &type) override - { - if (base->get_adt_kind () != type.get_adt_kind ()) - { - BaseCmp::visit (type); - return; - } - - if (base->get_identifier ().compare (type.get_identifier ()) != 0) - { - BaseCmp::visit (type); - return; - } - - if (base->number_of_variants () != type.number_of_variants ()) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < type.number_of_variants (); ++i) - { - TyTy::VariantDef *a = base->get_variants ().at (i); - TyTy::VariantDef *b = type.get_variants ().at (i); - - if (a->num_fields () != b->num_fields ()) - { - BaseCmp::visit (type); - return; - } - - for (size_t j = 0; j < a->num_fields (); j++) - { - TyTy::StructFieldType *base_field = a->get_field_at_index (j); - TyTy::StructFieldType *other_field = b->get_field_at_index (j); - - TyTy::BaseType *this_field_ty = base_field->get_field_type (); - TyTy::BaseType *other_field_ty = other_field->get_field_type (); - - if (!this_field_ty->can_eq (other_field_ty, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - } - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const ADTType *base; -}; - -class TupleCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - TupleCmp (const TupleType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const TupleType &type) override - { - if (base->num_fields () != type.num_fields ()) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < base->num_fields (); i++) - { - BaseType *bo = base->get_field (i); - BaseType *fo = type.get_field (i); - - if (!bo->can_eq (fo, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const TupleType *base; -}; - -class USizeCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - USizeCmp (const USizeType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT; - } - - void visit (const USizeType &type) override { ok = true; } - -private: - const BaseType *get_base () const override { return base; } - const USizeType *base; -}; - -class ISizeCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ISizeCmp (const ISizeType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT; - } - - void visit (const ISizeType &type) override { ok = true; } - -private: - const BaseType *get_base () const override { return base; } - const ISizeType *base; -}; - -class CharCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - CharCmp (const CharType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; - } - - void visit (const CharType &type) override { ok = true; } - -private: - const BaseType *get_base () const override { return base; } - const CharType *base; -}; - -class ReferenceCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ReferenceCmp (const ReferenceType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const ReferenceType &type) override - { - auto base_type = base->get_base (); - auto other_base_type = type.get_base (); - - bool mutability_ok = base->is_mutable () ? type.is_mutable () : true; - if (!mutability_ok) - { - BaseCmp::visit (type); - return; - } - - if (!base_type->can_eq (other_base_type, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const ReferenceType *base; -}; - -class PointerCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - PointerCmp (const PointerType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const PointerType &type) override - { - auto base_type = base->get_base (); - auto other_base_type = type.get_base (); - - bool mutability_ok = base->is_mutable () ? type.is_mutable () : true; - if (!mutability_ok) - { - BaseCmp::visit (type); - return; - } - - if (!base_type->can_eq (other_base_type, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const PointerType *base; -}; - -class ParamCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ParamCmp (const ParamType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - // param types are a placeholder we shouldn't have cases where we unify - // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either: - // - // foo<i32>{ a: 123 }. - // Then this enforces the i32 type to be referenced on the - // field via an hirid. - // - // rust also allows for a = foo{a:123}; Where we can use an Inference Variable - // to handle the typing of the struct - bool can_eq (const BaseType *other) override - { - if (!base->can_resolve ()) - return BaseCmp::can_eq (other); - - auto lookup = base->resolve (); - return lookup->can_eq (other, emit_error_flag); - } - - // imagine the case where we have: - // struct Foo<T>(T); - // Then we declare a generic impl block - // impl <X>Foo<X> { ... } - // both of these types are compatible so we mostly care about the number of - // generic arguments - void visit (const ParamType &) override { ok = true; } - - void visit (const TupleType &) override { ok = true; } - - void visit (const InferType &) override { ok = true; } - - void visit (const FnType &) override { ok = true; } - - void visit (const FnPtr &) override { ok = true; } - - void visit (const ADTType &) override { ok = true; } - - void visit (const ArrayType &) override { ok = true; } - - void visit (const SliceType &) override { ok = true; } - - void visit (const BoolType &) override { ok = true; } - - void visit (const IntType &) override { ok = true; } - - void visit (const UintType &) override { ok = true; } - - void visit (const USizeType &) override { ok = true; } - - void visit (const ISizeType &) override { ok = true; } - - void visit (const FloatType &) override { ok = true; } - - void visit (const CharType &) override { ok = true; } - - void visit (const ReferenceType &) override { ok = true; } - - void visit (const PointerType &) override { ok = true; } - - void visit (const StrType &) override { ok = true; } - - void visit (const NeverType &) override { ok = true; } - - void visit (const DynamicObjectType &) override { ok = true; } - - void visit (const PlaceholderType &type) override - { - ok = base->get_symbol ().compare (type.get_symbol ()) == 0; - } - -private: - const BaseType *get_base () const override { return base; } - const ParamType *base; -}; - -class StrCmp : public BaseCmp -{ - // FIXME we will need a enum for the StrType like ByteBuf etc.. - using Rust::TyTy::BaseCmp::visit; - -public: - StrCmp (const StrType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const StrType &type) override { ok = true; } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const StrType *base; -}; - -class NeverCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - NeverCmp (const NeverType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const NeverType &type) override { ok = true; } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const NeverType *base; -}; - -class PlaceholderCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - PlaceholderCmp (const PlaceholderType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - bool can_eq (const BaseType *other) override - { - if (!base->can_resolve ()) - return BaseCmp::can_eq (other); - - BaseType *lookup = base->resolve (); - return lookup->can_eq (other, emit_error_flag); - } - - void visit (const TupleType &) override { ok = true; } - - void visit (const ADTType &) override { ok = true; } - - void visit (const InferType &) override { ok = true; } - - void visit (const FnType &) override { ok = true; } - - void visit (const FnPtr &) override { ok = true; } - - void visit (const ArrayType &) override { ok = true; } - - void visit (const BoolType &) override { ok = true; } - - void visit (const IntType &) override { ok = true; } - - void visit (const UintType &) override { ok = true; } - - void visit (const USizeType &) override { ok = true; } - - void visit (const ISizeType &) override { ok = true; } - - void visit (const FloatType &) override { ok = true; } - - void visit (const ErrorType &) override { ok = true; } - - void visit (const CharType &) override { ok = true; } - - void visit (const ReferenceType &) override { ok = true; } - - void visit (const ParamType &) override { ok = true; } - - void visit (const StrType &) override { ok = true; } - - void visit (const NeverType &) override { ok = true; } - - void visit (const SliceType &) override { ok = true; } - -private: - const BaseType *get_base () const override { return base; } - - const PlaceholderType *base; -}; - -class DynamicCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - DynamicCmp (const DynamicObjectType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const DynamicObjectType &type) override - { - if (base->num_specified_bounds () != type.num_specified_bounds ()) - { - BaseCmp::visit (type); - return; - } - - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - ok = base->bounds_compatible (type, ref_locus, false); - } - -private: - const BaseType *get_base () const override { return base; } - - const DynamicObjectType *base; -}; - -class OpaqueCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - OpaqueCmp (const OpaqueType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - // TODO - -private: - const BaseType *get_base () const override { return base; } - - const OpaqueType *base; -}; - -} // namespace TyTy -} // namespace Rust - -#endif // RUST_TYTY_CMP_H diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 95f18b9..e82e8a3 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -18,18 +18,22 @@ #include "rust-tyty-subst.h" +#include "rust-hir-generic-param.h" #include "rust-system.h" #include "rust-tyty.h" #include "rust-hir-type-check.h" #include "rust-substitution-mapper.h" #include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" +#include "rust-compile-base.h" #include "rust-type-util.h" +#include "tree.h" namespace Rust { namespace TyTy { -SubstitutionParamMapping::SubstitutionParamMapping ( - const HIR::TypeParam &generic, ParamType *param) +SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic, + BaseGeneric *param) : generic (generic), param (param) {} @@ -50,23 +54,29 @@ SubstitutionParamMapping::as_string () const SubstitutionParamMapping SubstitutionParamMapping::clone () const { - return SubstitutionParamMapping (generic, - static_cast<ParamType *> (param->clone ())); + return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> ( + param->clone ())); } -ParamType * +BaseGeneric * SubstitutionParamMapping::get_param_ty () { return param; } -const ParamType * +const BaseGeneric * SubstitutionParamMapping::get_param_ty () const { return param; } -const HIR::TypeParam & +HIR::GenericParam & +SubstitutionParamMapping::get_generic_param () +{ + return generic; +} + +const HIR::GenericParam & SubstitutionParamMapping::get_generic_param () const { return generic; @@ -78,6 +88,12 @@ SubstitutionParamMapping::needs_substitution () const return !(get_param_ty ()->is_concrete ()); } +Identifier +SubstitutionParamMapping::get_type_representation () const +{ + return param->get_symbol (); +} + location_t SubstitutionParamMapping::get_param_locus () const { @@ -87,13 +103,35 @@ SubstitutionParamMapping::get_param_locus () const bool SubstitutionParamMapping::param_has_default_ty () const { - return generic.has_type (); + if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE) + { + const auto &type_param = static_cast<const HIR::TypeParam &> (generic); + return type_param.has_type (); + } + + rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST); + const auto &const_param + = static_cast<const HIR::ConstGenericParam &> (generic); + return const_param.has_default_expression (); } BaseType * SubstitutionParamMapping::get_default_ty () const { - TyVar var (generic.get_type_mappings ().get_hirid ()); + if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE) + { + const auto &type_param = static_cast<const HIR::TypeParam &> (generic); + TyVar var (type_param.get_type_mappings ().get_hirid ()); + return var.get_tyty (); + } + + rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST); + const auto &const_param + = static_cast<const HIR::ConstGenericParam &> (generic); + rust_assert (const_param.has_default_expression ()); + + const auto &expr = const_param.get_default_expression (); + TyVar var (expr.get_mappings ().get_hirid ()); return var.get_tyty (); } @@ -109,7 +147,8 @@ SubstitutionParamMapping::need_substitution () const bool SubstitutionParamMapping::fill_param_ty ( - SubstitutionArgumentMappings &subst_mappings, location_t locus) + SubstitutionArgumentMappings &subst_mappings, location_t locus, + bool needs_bounds_check) { SubstitutionArg arg = SubstitutionArg::error (); bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg); @@ -124,17 +163,26 @@ SubstitutionParamMapping::fill_param_ty ( if (type.get_kind () == TypeKind::PARAM) { - // delete param; - param = static_cast<ParamType *> (type.clone ()); + param = static_cast<BaseGeneric *> (type.clone ()); } - else + else if (type.get_kind () == TyTy::TypeKind::CONST) { + rust_assert (param->get_kind () == TyTy::TypeKind::CONST); + auto *const_type = type.as_const_type (); + if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl) + param = static_cast<BaseGeneric *> (type.clone ()); + else + param->set_ty_ref (type.get_ref ()); + } + else if (param->get_kind () == TypeKind::PARAM) + { + auto &p = *static_cast<TyTy::ParamType *> (param); + // check the substitution is compatible with bounds rust_debug_loc (locus, "fill_param_ty bounds_compatible: param %s type %s", param->get_name ().c_str (), type.get_name ().c_str ()); - - if (!param->is_implicit_self_trait ()) + if (needs_bounds_check && !p.is_implicit_self_trait ()) { if (!param->bounds_compatible (type, locus, true)) return false; @@ -145,7 +193,7 @@ SubstitutionParamMapping::fill_param_ty ( bound.handle_substitions (subst_mappings); param->set_ty_ref (type.get_ref ()); - subst_mappings.on_param_subst (*param, arg); + subst_mappings.on_param_subst (p, arg); } return true; @@ -191,12 +239,6 @@ SubstitutionArg::operator= (const SubstitutionArg &other) } BaseType * -SubstitutionArg::get_tyty () -{ - return argument; -} - -const BaseType * SubstitutionArg::get_tyty () const { return argument; @@ -208,7 +250,7 @@ SubstitutionArg::get_param_mapping () const return param; } -const ParamType * +const BaseGeneric * SubstitutionArg::get_param_ty () const { return original_param; @@ -313,11 +355,11 @@ SubstitutionArgumentMappings::is_error () const bool SubstitutionArgumentMappings::get_argument_for_symbol ( - const ParamType *param_to_find, SubstitutionArg *argument) const + const BaseGeneric *param_to_find, SubstitutionArg *argument) const { for (const auto &mapping : mappings) { - const ParamType *p = mapping.get_param_ty (); + const auto *p = mapping.get_param_ty (); if (p->get_symbol () == param_to_find->get_symbol ()) { *argument = mapping; @@ -517,6 +559,7 @@ std::vector<SubstitutionParamMapping> SubstitutionRef::clone_substs () const { std::vector<SubstitutionParamMapping> clone; + clone.reserve (substitutions.size ()); for (auto &sub : substitutions) clone.push_back (sub.clone ()); @@ -618,7 +661,6 @@ SubstitutionRef::get_mappings_from_generic_args ( if (args.get_binding_args ().size () > get_num_associated_bindings ()) { rich_location r (line_table, args.get_locus ()); - rust_error_at (r, "generic item takes at most %lu type binding " "arguments but %lu were supplied", @@ -666,11 +708,17 @@ SubstitutionRef::get_mappings_from_generic_args ( // for inherited arguments size_t offs = used_arguments.size (); - if (args.get_type_args ().size () + offs > substitutions.size ()) + size_t total_arguments + = args.get_type_args ().size () + args.get_const_args ().size () + offs; + if (total_arguments > substitutions.size ()) { rich_location r (line_table, args.get_locus ()); if (!substitutions.empty ()) - r.add_range (substitutions.front ().get_param_locus ()); + { + const auto &subst = substitutions.front (); + const auto &generic = subst.get_generic_param (); + r.add_range (generic.get_locus ()); + } rust_error_at ( r, @@ -680,10 +728,15 @@ SubstitutionRef::get_mappings_from_generic_args ( return SubstitutionArgumentMappings::error (); } - if (args.get_type_args ().size () + offs < min_required_substitutions ()) + if (total_arguments < min_required_substitutions ()) { rich_location r (line_table, args.get_locus ()); - r.add_range (substitutions.front ().get_param_locus ()); + if (!substitutions.empty ()) + { + const auto &subst = substitutions.front (); + const auto &generic = subst.get_generic_param (); + r.add_range (generic.get_locus ()); + } rust_error_at ( r, ErrorCode::E0107, @@ -702,9 +755,125 @@ SubstitutionRef::get_mappings_from_generic_args ( return SubstitutionArgumentMappings::error (); } - SubstitutionArg subst_arg (&substitutions.at (offs), resolved); + const auto ¶m_mapping = substitutions.at (offs); + const auto &generic = param_mapping.get_generic_param (); + if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE) + { + const auto &type_param + = static_cast<const HIR::TypeParam &> (generic); + if (type_param.from_impl_trait ()) + { + rich_location r (line_table, arg->get_locus ()); + r.add_fixit_remove (arg->get_locus ()); + rust_error_at (r, ErrorCode::E0632, + "cannot provide explicit generic arguments when " + "%<impl Trait%> is used in argument position"); + return SubstitutionArgumentMappings::error (); + } + } + else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST) + { + if (resolved->get_kind () != TyTy::TypeKind::CONST) + { + rich_location r (line_table, arg->get_locus ()); + r.add_fixit_remove (arg->get_locus ()); + rust_error_at (r, ErrorCode::E0747, + "type provided when a constant was expected"); + return SubstitutionArgumentMappings::error (); + } + } + + mappings.emplace_back (¶m_mapping, resolved); + offs++; + } + + for (auto &arg : args.get_const_args ()) + { + auto &expr = *arg.get_expression ().get (); + BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr); + if (expr_type == nullptr || expr_type->is<ErrorType> ()) + return SubstitutionArgumentMappings::error (); + + // validate this param is really a const generic + const auto ¶m_mapping = substitutions.at (offs); + const auto &generic = param_mapping.get_generic_param (); + if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST) + { + rich_location r (line_table, arg.get_locus ()); + r.add_fixit_remove (expr.get_locus ()); + rust_error_at (r, "invalid position for a const generic argument"); + return SubstitutionArgumentMappings::error (); + } + + // get the const generic specified type + const auto base_generic = param_mapping.get_param_ty (); + rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST); + const auto const_param + = static_cast<const TyTy::ConstParamType *> (base_generic); + auto specified_type = const_param->get_specified_type (); + + // validate this const generic is of the correct type + TyTy::BaseType *coereced_type = nullptr; + if (expr_type->get_kind () == TyTy::TypeKind::CONST) + { + auto const_expr_type = expr_type->as_const_type (); + auto const_value_type = const_expr_type->get_specified_type (); + coereced_type + = Resolver::coercion_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (specified_type), + TyTy::TyWithLocation (const_value_type, + expr.get_locus ()), + arg.get_locus ()); + } + else + { + coereced_type + = Resolver::coercion_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (specified_type), + TyTy::TyWithLocation (expr_type, + expr.get_locus ()), + arg.get_locus ()); + } + + if (coereced_type == nullptr || coereced_type->is<ErrorType> ()) + return SubstitutionArgumentMappings::error (); + + TyTy::BaseType *const_value_ty = nullptr; + if (expr_type->get_kind () == TyTy::TypeKind::CONST) + const_value_ty = expr_type; + else + { + // const fold it if available + auto ctx = Compile::Context::get (); + tree folded + = Compile::HIRCompileBase::query_compile_const_expr (ctx, + coereced_type, + expr); + + if (folded == error_mark_node) + { + rich_location r (line_table, arg.get_locus ()); + r.add_range (expr.get_locus ()); + rust_error_at (r, "failed to resolve const expression"); + return SubstitutionArgumentMappings::error (); + } + + // Use a fresh HirId to avoid conflicts with the expr's type + auto &global_mappings = Analysis::Mappings::get (); + HirId const_value_id = global_mappings.get_next_hir_id (); + const_value_ty + = new TyTy::ConstValueType (folded, coereced_type, const_value_id, + const_value_id, {}); + + // Insert the ConstValueType into the context so it can be looked up + auto context = Resolver::TypeCheckContext::get (); + context->insert_type ( + Analysis::NodeMapping (0, 0, const_value_ty->get_ref (), 0), + const_value_ty); + } + + mappings.emplace_back (¶m_mapping, const_value_ty); offs++; - mappings.push_back (std::move (subst_arg)); } // we must need to fill out defaults @@ -734,8 +903,7 @@ SubstitutionRef::get_mappings_from_generic_args ( return SubstitutionArgumentMappings::error (); } - SubstitutionArg subst_arg (¶m, resolved); - mappings.push_back (std::move (subst_arg)); + mappings.emplace_back (¶m, resolved); } } @@ -754,24 +922,31 @@ SubstitutionRef::infer_substitions (location_t locus) { if (p.needs_substitution ()) { + const HIR::GenericParam &generic = p.get_generic_param (); const std::string &symbol = p.get_param_ty ()->get_symbol (); auto it = argument_mappings.find (symbol); bool have_mapping = it != argument_mappings.end (); if (have_mapping) { - args.push_back (SubstitutionArg (&p, it->second)); + args.emplace_back (&p, it->second); } - else + else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE) { TyVar infer_var = TyVar::get_implicit_infer_var (locus); - args.push_back (SubstitutionArg (&p, infer_var.get_tyty ())); + args.emplace_back (&p, infer_var.get_tyty ()); + argument_mappings[symbol] = infer_var.get_tyty (); + } + else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST) + { + TyVar infer_var = TyVar::get_implicit_const_infer_var (locus); + args.emplace_back (&p, infer_var.get_tyty ()); argument_mappings[symbol] = infer_var.get_tyty (); } } else { - args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ())); + args.emplace_back (&p, p.get_param_ty ()->resolve ()); } } @@ -817,10 +992,7 @@ SubstitutionRef::adjust_mappings_for_this ( bool ok = !arg.is_error (); if (ok || (trait_mode && i == 0)) - { - SubstitutionArg adjusted (&subst, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } + resolved_mappings.emplace_back (&subst, arg.get_tyty ()); } if (resolved_mappings.empty ()) @@ -864,10 +1036,7 @@ SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings) bool ok = !arg.is_error (); if (ok) - { - SubstitutionArg adjusted (&subst, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } + resolved_mappings.emplace_back (&subst, arg.get_tyty ()); } return !resolved_mappings.empty (); @@ -888,10 +1057,7 @@ SubstitutionRef::solve_mappings_from_receiver_for_self ( SubstitutionArg &arg = mappings.get_mappings ().at (i); if (param_mapping.needs_substitution ()) - { - SubstitutionArg adjusted (¶m_mapping, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } + resolved_mappings.emplace_back (¶m_mapping, arg.get_tyty ()); } return SubstitutionArgumentMappings (resolved_mappings, @@ -905,7 +1071,7 @@ SubstitutionRef::prepare_higher_ranked_bounds () { for (const auto &subst : get_substs ()) { - const TyTy::ParamType *pty = subst.get_param_ty (); + const auto pty = subst.get_param_ty (); for (const auto &bound : pty->get_specified_bounds ()) { const auto ref = bound.get (); @@ -919,12 +1085,11 @@ SubstitutionRef::monomorphize () { for (const auto &subst : get_substs ()) { - const TyTy::ParamType *pty = subst.get_param_ty (); - + const auto pty = subst.get_param_ty (); if (!pty->can_resolve ()) continue; - const TyTy::BaseType *binding = pty->resolve (); + TyTy::BaseType *binding = pty->resolve (); if (binding->get_kind () == TyTy::TypeKind::PARAM) continue; diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h index 3f0b912..d09e180 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.h +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -22,14 +22,15 @@ #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" namespace Rust { namespace TyTy { class ParamType; +class BaseGeneric; struct RegionConstraints { @@ -44,22 +45,24 @@ class SubstitutionArgumentMappings; class SubstitutionParamMapping { public: - SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param); + SubstitutionParamMapping (HIR::GenericParam &generic, BaseGeneric *param); SubstitutionParamMapping (const SubstitutionParamMapping &other); std::string as_string () const; bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings, - location_t locus); + location_t locus, bool needs_bounds_check = true); SubstitutionParamMapping clone () const; - ParamType *get_param_ty (); + BaseGeneric *get_param_ty (); + const BaseGeneric *get_param_ty () const; - const ParamType *get_param_ty () const; + HIR::GenericParam &get_generic_param (); + const HIR::GenericParam &get_generic_param () const; - const HIR::TypeParam &get_generic_param () const; + Identifier get_type_representation () const; // this is used for the backend to override the HirId ref of the param to // what the concrete type is for the rest of the context @@ -76,8 +79,8 @@ public: bool need_substitution () const; private: - const HIR::TypeParam &generic; - ParamType *param; + HIR::GenericParam &generic; + BaseGeneric *param; }; /** @@ -147,13 +150,11 @@ public: SubstitutionArg &operator= (const SubstitutionArg &other); - BaseType *get_tyty (); - - const BaseType *get_tyty () const; + BaseType *get_tyty () const; const SubstitutionParamMapping *get_param_mapping () const; - const ParamType *get_param_ty () const; + const BaseGeneric *get_param_ty () const; static SubstitutionArg error (); @@ -165,7 +166,7 @@ public: private: const SubstitutionParamMapping *param; - const ParamType *original_param; + const BaseGeneric *original_param; BaseType *argument; }; @@ -205,7 +206,7 @@ public: bool is_error () const; - bool get_argument_for_symbol (const ParamType *param_to_find, + bool get_argument_for_symbol (const BaseGeneric *param_to_find, SubstitutionArg *argument) const; /** Return type parameter index for symbol */ diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc index ff210ce..b780eaa 100644 --- a/gcc/rust/typecheck/rust-tyty-util.cc +++ b/gcc/rust/typecheck/rust-tyty-util.cc @@ -17,6 +17,8 @@ // <http://www.gnu.org/licenses/>. #include "rust-hir-type-check.h" +#include "rust-mapping-common.h" +#include "rust-system.h" #include "rust-tyty.h" namespace Rust { @@ -28,7 +30,8 @@ TyVar::TyVar (HirId ref) : ref (ref) auto context = Resolver::TypeCheckContext::get (); BaseType *lookup = nullptr; bool ok = context->lookup_type (ref, &lookup); - rust_assert (ok); + if (!ok || lookup == nullptr || lookup->get_kind () == TypeKind::ERROR) + return; } BaseType * @@ -37,7 +40,8 @@ TyVar::get_tyty () const auto context = Resolver::TypeCheckContext::get (); BaseType *lookup = nullptr; bool ok = context->lookup_type (ref, &lookup); - rust_assert (ok); + if (!ok || lookup == nullptr) + return nullptr; return lookup; } @@ -47,14 +51,28 @@ TyVar::get_implicit_infer_var (location_t locus) auto &mappings = Analysis::Mappings::get (); auto context = Resolver::TypeCheckContext::get (); - InferType *infer = new InferType (mappings.get_next_hir_id (), - InferType::InferTypeKind::GENERAL, - InferType::TypeHint::Default (), locus); - context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (), - UNKNOWN_NODEID, - infer->get_ref (), - UNKNOWN_LOCAL_DEFID), - infer); + HirId next = mappings.get_next_hir_id (); + auto infer = new InferType (next, InferType::InferTypeKind::GENERAL, + InferType::TypeHint::Default (), locus); + + context->insert_implicit_type (infer->get_ref (), infer); + mappings.insert_location (infer->get_ref (), locus); + + return TyVar (infer->get_ref ()); +} + +TyVar +TyVar::get_implicit_const_infer_var (location_t locus, TyVar *implicit_type) +{ + auto &mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); + + TyVar it = (implicit_type != nullptr) ? *implicit_type + : get_implicit_infer_var (locus); + HirId next = mappings.get_next_hir_id (); + auto infer = new ConstInferType (it.get_tyty (), next, next, {}); + + context->insert_implicit_type (infer->get_ref (), infer); mappings.insert_location (infer->get_ref (), locus); return TyVar (infer->get_ref ()); @@ -80,7 +98,10 @@ TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst) TyVar TyVar::clone () const { - TyTy::BaseType *c = get_tyty ()->clone (); + TyTy::BaseType *base = get_tyty (); + if (base == nullptr || base->get_kind () == TypeKind::ERROR) + return TyVar::get_implicit_infer_var (UNKNOWN_LOCATION); + TyTy::BaseType *c = base->clone (); return TyVar (c->get_ref ()); } @@ -90,6 +111,10 @@ TyVar::monomorphized_clone () const auto &mappings = Analysis::Mappings::get (); auto context = Resolver::TypeCheckContext::get (); + TyTy::BaseType *base = get_tyty (); + if (base == nullptr || base->get_kind () == TypeKind::ERROR) + return TyVar::get_implicit_infer_var (UNKNOWN_LOCATION); + // this needs a new hirid TyTy::BaseType *c = get_tyty ()->monomorphized_clone (); c->set_ref (mappings.get_next_hir_id ()); diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h index cbb3e8e..b132487 100644 --- a/gcc/rust/typecheck/rust-tyty-util.h +++ b/gcc/rust/typecheck/rust-tyty-util.h @@ -25,6 +25,7 @@ namespace Rust { namespace TyTy { class BaseType; +class ConstType; // this is a placeholder for types that can change like inference variables class TyVar @@ -42,6 +43,9 @@ public: static TyVar get_implicit_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-variance-analysis-private.h b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h index d36afc8..b7ca5e1 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h @@ -47,6 +47,10 @@ struct Term /** Variance constraint of a type parameter. */ struct Constraint { + Constraint (SolutionIndex target_index, Term *term) + : target_index (target_index), term (term) + {} + SolutionIndex target_index; Term *term; }; @@ -170,6 +174,11 @@ public: } void visit (OpaqueType &type) override {} + + void visit (TyTy::ConstParamType &) override {} + void visit (TyTy::ConstValueType &) override {} + void visit (TyTy::ConstInferType &) override {} + void visit (TyTy::ConstErrorType &) override {} }; /** Per crate context for generic type variance analysis. */ diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc index 1aba576..d640d55 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc @@ -199,9 +199,7 @@ GenericTyPerCrateCtx::debug_print_solutions () { if (i > solution_index) result += ", "; - result += param.get_generic_param () - .get_type_representation () - .as_string (); + result += param.get_type_representation ().as_string (); result += "="; result += solutions[i].as_string (); i++; @@ -238,9 +236,8 @@ GenericTyVisitorCtx::process_type (ADTType &ty) first_lifetime = lookup_or_add_type (ty.get_orig_ref ()); first_type = first_lifetime + ty.get_used_arguments ().get_regions ().size (); - for (const auto ¶m : ty.get_substs ()) - param_names.push_back ( - param.get_generic_param ().get_type_representation ().as_string ()); + for (auto ¶m : ty.get_substs ()) + param_names.push_back (param.get_type_representation ().as_string ()); for (const auto &variant : ty.get_variants ()) { @@ -324,6 +321,8 @@ GenericTyPerCrateCtx::query_generic_variance (const ADTType &type) auto num_types = type.get_num_type_params (); std::vector<Variance> result; + result.reserve (num_lifetimes + num_types); + for (size_t i = 0; i < num_lifetimes + num_types; ++i) { result.push_back (solutions[solution_index.value () + i]); @@ -413,7 +412,7 @@ GenericTyVisitorCtx::add_constraint (SolutionIndex index, Term term) } else { - ctx.constraints.push_back ({index, new Term (term)}); + ctx.constraints.emplace_back (index, new Term (term)); } } diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.h b/gcc/rust/typecheck/rust-tyty-variance-analysis.h index 9059a2f..282c6f3 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis.h +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.h @@ -41,9 +41,10 @@ private: std::unique_ptr<GenericTyPerCrateCtx> private_ctx; }; -std::vector<size_t> -query_field_regions (const ADTType *parent, size_t variant_index, - size_t field_index, const FreeRegions &parent_regions); +std::vector<size_t> query_field_regions (const ADTType *parent, + size_t variant_index, + size_t field_index, + const FreeRegions &parent_regions); /** Variance semilattice */ class Variance diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 4f8e7856..f7f3665e 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -45,6 +45,10 @@ public: virtual void visit (ReferenceType &type) = 0; virtual void visit (PointerType &type) = 0; virtual void visit (ParamType &type) = 0; + virtual void visit (ConstParamType &type) = 0; + virtual void visit (ConstValueType &type) = 0; + virtual void visit (ConstInferType &type) = 0; + virtual void visit (ConstErrorType &type) = 0; virtual void visit (StrType &type) = 0; virtual void visit (NeverType &type) = 0; virtual void visit (PlaceholderType &type) = 0; @@ -75,6 +79,10 @@ public: virtual void visit (const ReferenceType &type) = 0; virtual void visit (const PointerType &type) = 0; virtual void visit (const ParamType &type) = 0; + virtual void visit (const ConstParamType &type) = 0; + virtual void visit (const ConstValueType &type) = 0; + virtual void visit (const ConstInferType &type) = 0; + virtual void visit (const ConstErrorType &type) = 0; virtual void visit (const StrType &type) = 0; virtual void visit (const NeverType &type) = 0; virtual void visit (const PlaceholderType &type) = 0; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index efad5f6..5386b72 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -16,23 +16,23 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" #include "rust-tyty.h" - -#include "optional.h" +#include "rust-tyty-subst.h" #include "rust-tyty-visitor.h" #include "rust-hir-map.h" #include "rust-location.h" -#include "rust-linemap.h" - +#include "rust-type-util.h" +#include "rust-hir-type-bounds.h" #include "rust-substitution-mapper.h" #include "rust-hir-trait-reference.h" #include "rust-hir-trait-resolve.h" -#include "rust-tyty-cmp.h" -#include "rust-type-util.h" -#include "rust-hir-type-bounds.h" +#include "tree-pretty-print.h" +#include "optional.h" #include "options.h" -#include "rust-system.h" +#include "tree.h" +#include "fold-const.h" namespace Rust { namespace TyTy { @@ -114,6 +114,9 @@ TypeKindFormat::to_string (TypeKind kind) case TypeKind::OPAQUE: return "Opaque"; + case TypeKind::CONST: + return "Const"; + case TypeKind::ERROR: return "ERROR"; } @@ -223,6 +226,7 @@ BaseType::is_unit () const case OPAQUE: case STR: case DYNAMIC: + case CONST: case ERROR: return false; @@ -230,11 +234,13 @@ BaseType::is_unit () const case NEVER: return true; - case TUPLE: { + case TUPLE: + { return x->as<const TupleType> ()->num_fields () == 0; } - case ADT: { + case ADT: + { auto adt = x->as<const ADTType> (); if (adt->is_enum ()) return false; @@ -283,8 +289,7 @@ BaseType::get_locus () const // FIXME this is missing locus bool -BaseType::satisfies_bound (const TypeBoundPredicate &predicate, - bool emit_error) const +BaseType::satisfies_bound (const TypeBoundPredicate &predicate, bool emit_error) { const Resolver::TraitReference *query = predicate.get (); for (const auto &bound : specified_bounds) @@ -339,41 +344,20 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate, return false; std::string item_name = item->get_impl_item_name (); - TypeBoundPredicateItem lookup + tl::optional<TypeBoundPredicateItem> lookup = predicate.lookup_associated_item (item_name); - if (lookup.is_error ()) + if (!lookup.has_value ()) return false; - const auto *item_ref = lookup.get_raw_item (); + const auto *item_ref = lookup->get_raw_item (); TyTy::BaseType *bound_ty = item_ref->get_tyty (); - // compare the types - if (!bound_ty->can_eq (impl_item_ty, false)) - { - if (!impl_item_ty->can_eq (bound_ty, false)) - { - if (emit_error) - { - rich_location r (line_table, - mappings.lookup_location (get_ref ())); - r.add_range (predicate.get_locus ()); - r.add_range (mappings.lookup_location (i.get_hirid ())); - - std::string rich_msg - = "expected " + bound_ty->destructure ()->get_name () - + ", found " - + impl_item_ty->destructure ()->get_name (); - r.add_fixit_replace (rich_msg.c_str ()); - - rust_error_at ( - r, ErrorCode::E0271, - "type mismatch, expected %qs but got %qs", - bound_ty->destructure ()->get_name ().c_str (), - impl_item_ty->destructure ()->get_name ().c_str ()); - } - return false; - } - } + if (!Resolver::types_compatable ( + TyTy::TyWithLocation (bound_ty, predicate.get_locus ()), + TyTy::TyWithLocation (impl_item_ty, item->get_locus ()), + mappings.lookup_location (get_ref ()), false /*emit-error*/, + false /*check-bounds*/)) + return false; } return true; @@ -383,8 +367,7 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate, } bool -BaseType::bounds_compatible (const BaseType &other, location_t locus, - bool emit_error) const +BaseType::bounds_compatible (BaseType &other, location_t locus, bool emit_error) { std::vector<std::reference_wrapper<const TypeBoundPredicate>> unsatisfied_bounds; @@ -438,11 +421,10 @@ BaseType::inherit_bounds ( } } -const BaseType * -BaseType::get_root () const +BaseType * +BaseType::get_root () { - // FIXME this needs to be it its own visitor class with a vector adjustments - const TyTy::BaseType *root = this; + TyTy::BaseType *root = this; if (const auto r = root->try_as<const ReferenceType> ()) { @@ -490,6 +472,23 @@ BaseType::destructure () x = pr; } + else if (x->get_kind () == TypeKind::CONST) + { + auto p = x->as_const_type (); + if (p->const_kind () == BaseConstType::ConstKind::Decl) + { + auto decl = static_cast<ConstParamType *> (p); + auto pr = decl->resolve (); + if (pr == x) + return pr; + + x = pr; + } + else + { + return x; + } + } else if (auto p = x->try_as<PlaceholderType> ()) { if (!p->can_resolve ()) @@ -535,6 +534,23 @@ BaseType::destructure () const x = pr; } + else if (x->get_kind () == TypeKind::CONST) + { + auto p = x->as_const_type (); + if (p->const_kind () == BaseConstType::ConstKind::Decl) + { + auto decl = static_cast<const ConstParamType *> (p); + auto pr = decl->resolve (); + if (pr == x) + return pr; + + x = pr; + } + else + { + return x; + } + } else if (auto p = x->try_as<const PlaceholderType> ()) { if (!p->can_resolve ()) @@ -546,17 +562,14 @@ BaseType::destructure () const { x = p->get (); } - // else if (auto p = x->try_as<const OpaqueType> ()) - // { - // auto pr = p->resolve (); - - // rust_debug ("XXXXXX") - - // if (pr == x) - // return pr; + else if (auto p = x->try_as<const OpaqueType> ()) + { + auto pr = p->resolve (); + if (pr == x) + return pr; - // x = pr; - // } + x = pr; + } else { return x; @@ -575,7 +588,7 @@ BaseType::monomorphized_clone () const { TyVar elm = arr->get_var_element_type ().monomorphized_clone (); return new ArrayType (arr->get_ref (), arr->get_ty_ref (), ident.locus, - arr->get_capacity_expr (), elm, + arr->get_capacity_var (), elm, arr->get_combined_refs ()); } else if (auto slice = x->try_as<const SliceType> ()) @@ -629,8 +642,8 @@ BaseType::monomorphized_clone () const TyVar retty = fn->get_var_return_type ().monomorphized_clone (); return new FnPtr (fn->get_ref (), fn->get_ty_ref (), ident.locus, - std::move (cloned_params), retty, - fn->get_combined_refs ()); + std::move (cloned_params), retty, fn->get_abi (), + fn->get_unsafety (), fn->get_combined_refs ()); } else if (auto adt = x->try_as<const ADTType> ()) { @@ -682,6 +695,91 @@ BaseType::debug () const debug_str ().c_str ()); } +const TyTy::BaseType * +BaseType::contains_infer () const +{ + const TyTy::BaseType *x = destructure (); + + if (auto fn = x->try_as<const FnType> ()) + { + for (const auto ¶m : fn->get_params ()) + { + auto infer = param.get_type ()->contains_infer (); + if (infer) + return infer; + } + return fn->get_return_type ()->contains_infer (); + } + else if (auto fn = x->try_as<const FnPtr> ()) + { + for (const auto ¶m : fn->get_params ()) + { + auto infer = param.get_tyty ()->contains_infer (); + if (infer) + return infer; + } + return fn->get_return_type ()->contains_infer (); + } + else if (auto adt = x->try_as<const ADTType> ()) + { + for (auto &variant : adt->get_variants ()) + { + bool is_num_variant + = variant->get_variant_type () == VariantDef::VariantType::NUM; + if (is_num_variant) + continue; + + for (auto &field : variant->get_fields ()) + { + const BaseType *field_type = field->get_field_type (); + auto infer = (field_type->contains_infer ()); + if (infer) + return infer; + } + } + return nullptr; + } + else if (auto arr = x->try_as<const ArrayType> ()) + { + return arr->get_element_type ()->contains_infer (); + } + else if (auto slice = x->try_as<const SliceType> ()) + { + return slice->get_element_type ()->contains_infer (); + } + else if (auto ptr = x->try_as<const PointerType> ()) + { + return ptr->get_base ()->contains_infer (); + } + else if (auto ref = x->try_as<const ReferenceType> ()) + { + return ref->get_base ()->contains_infer (); + } + else if (auto tuple = x->try_as<const TupleType> ()) + { + for (size_t i = 0; i < tuple->num_fields (); i++) + { + auto infer = (tuple->get_field (i)->contains_infer ()); + if (infer) + return infer; + } + return nullptr; + } + else if (auto closure = x->try_as<const ClosureType> ()) + { + auto infer = (closure->get_parameters ().contains_infer ()); + if (infer) + return infer; + return closure->get_result_type ().contains_infer (); + } + else if (x->is<InferType> ()) + { + return x; + } + + return nullptr; +} + bool BaseType::is_concrete () const { @@ -691,6 +789,14 @@ BaseType::is_concrete () const { 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 @@ -739,7 +845,8 @@ BaseType::is_concrete () const } else if (auto arr = x->try_as<const ArrayType> ()) { - return arr->get_element_type ()->is_concrete (); + return arr->get_element_type ()->is_concrete () + && arr->get_capacity ()->is_concrete (); } else if (auto slice = x->try_as<const SliceType> ()) { @@ -783,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: @@ -806,31 +913,36 @@ BaseType::has_substitutions_defined () const case TUPLE: case PARAM: case PLACEHOLDER: + case CONST: case OPAQUE: return false; - case PROJECTION: { + case PROJECTION: + { const ProjectionType &p = *static_cast<const ProjectionType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (p); return ref.has_substitutions (); } break; - case FNDEF: { + case FNDEF: + { const FnType &fn = *static_cast<const FnType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (fn); return ref.has_substitutions (); } break; - case ADT: { + case ADT: + { const ADTType &adt = *static_cast<const ADTType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (adt); return ref.has_substitutions (); } break; - case CLOSURE: { + case CLOSURE: + { const ClosureType &closure = *static_cast<const ClosureType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (closure); @@ -868,31 +980,36 @@ BaseType::needs_generic_substitutions () const case TUPLE: case PARAM: case PLACEHOLDER: + case CONST: case OPAQUE: return false; - case PROJECTION: { + case PROJECTION: + { const ProjectionType &p = *static_cast<const ProjectionType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (p); return ref.needs_substitution (); } break; - case FNDEF: { + case FNDEF: + { const FnType &fn = *static_cast<const FnType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (fn); return ref.needs_substitution (); } break; - case ADT: { + case ADT: + { const ADTType &adt = *static_cast<const ADTType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (adt); return ref.needs_substitution (); } break; - case CLOSURE: { + case CLOSURE: + { const ClosureType &closure = *static_cast<const ClosureType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (closure); @@ -911,28 +1028,32 @@ BaseType::get_subst_argument_mappings () const const TyTy::BaseType *x = destructure (); switch (x->get_kind ()) { - case PROJECTION: { + case PROJECTION: + { const auto &p = *static_cast<const ProjectionType *> (x); const auto &ref = static_cast<const SubstitutionRef &> (p); return ref.get_substitution_arguments (); } break; - case FNDEF: { + case FNDEF: + { const auto &fn = *static_cast<const FnType *> (x); const auto &ref = static_cast<const SubstitutionRef &> (fn); return ref.get_substitution_arguments (); } break; - case ADT: { + case ADT: + { const auto &adt = *static_cast<const ADTType *> (x); const auto &ref = static_cast<const SubstitutionRef &> (adt); return ref.get_substitution_arguments (); } break; - case CLOSURE: { + case CLOSURE: + { const auto &closure = *static_cast<const ClosureType *> (x); const auto &ref = static_cast<const SubstitutionRef &> (closure); return ref.get_substitution_arguments (); @@ -1001,13 +1122,6 @@ InferType::as_string () const return "<infer::error>"; } -bool -InferType::can_eq (const BaseType *other, bool emit_errors) const -{ - InferCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * InferType::clone () const { @@ -1055,13 +1169,15 @@ InferType::default_type (BaseType **type) const case GENERAL: return false; - case INTEGRAL: { + case INTEGRAL: + { ok = context->lookup_builtin ("i32", type); rust_assert (ok); return ok; } - case FLOAT: { + case FLOAT: + { ok = context->lookup_builtin ("f64", type); rust_assert (ok); return ok; @@ -1184,7 +1300,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) default_hint.kind = hint.get_kind (); break; - case INT: { + case INT: + { infer_kind = INTEGRAL; default_hint.kind = hint.get_kind (); default_hint.shint = TypeHint::SignedHint::SIGNED; @@ -1209,7 +1326,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) } break; - case UINT: { + case UINT: + { infer_kind = INTEGRAL; default_hint.kind = hint.get_kind (); default_hint.shint = TypeHint::SignedHint::UNSIGNED; @@ -1234,7 +1352,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) } break; - case TypeKind::FLOAT: { + case TypeKind::FLOAT: + { infer_kind = FLOAT; default_hint.shint = TypeHint::SignedHint::SIGNED; default_hint.kind = hint.get_kind (); @@ -1293,12 +1412,6 @@ ErrorType::as_string () const return "<tyty::error>"; } -bool -ErrorType::can_eq (const BaseType *other, bool emit_errors) const -{ - return get_kind () == other->get_kind (); -} - BaseType * ErrorType::clone () const { @@ -1683,13 +1796,6 @@ ADTType::as_string () const } bool -ADTType::can_eq (const BaseType *other, bool emit_errors) const -{ - ADTCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool ADTType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -1715,11 +1821,9 @@ ADTType::is_equal (const BaseType &other) const const SubstitutionParamMapping &a = substitutions.at (i); const SubstitutionParamMapping &b = other2->substitutions.at (i); - const ParamType *aa = a.get_param_ty (); - const ParamType *bb = b.get_param_ty (); - BaseType *aaa = aa->resolve (); - BaseType *bbb = bb->resolve (); - if (!aaa->is_equal (*bbb)) + const auto &aa = a.get_param_ty (); + const auto &bb = b.get_param_ty (); + if (!aa->is_equal (*bb)) return false; } } @@ -1907,7 +2011,7 @@ TupleType::get_name () const std::string fields_buffer; for (const TyVar &field : get_fields ()) { - fields_buffer += field.get_tyty ()->as_string (); + fields_buffer += field.get_tyty ()->get_name (); bool has_next = (i + 1) < get_fields ().size (); fields_buffer += has_next ? ", " : ""; i++; @@ -1922,13 +2026,6 @@ TupleType::get_field (size_t index) const } bool -TupleType::can_eq (const BaseType *other, bool emit_errors) const -{ - TupleCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool TupleType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -2011,13 +2108,6 @@ FnType::as_string () const } bool -FnType::can_eq (const BaseType *other, bool emit_errors) const -{ - FnCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool FnType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -2044,9 +2134,8 @@ FnType::is_equal (const BaseType &other) const const SubstitutionParamMapping &a = get_substs ().at (i); const SubstitutionParamMapping &b = ofn.get_substs ().at (i); - const ParamType *pa = a.get_param_ty (); - const ParamType *pb = b.get_param_ty (); - + const auto *pa = a.get_param_ty (); + const auto *pb = b.get_param_ty (); if (!pa->is_equal (*pb)) return false; } @@ -2217,14 +2306,13 @@ FnPtr::as_string () const params_str += p.get_tyty ()->as_string () + " ,"; } - return "fnptr (" + params_str + ") -> " + get_return_type ()->as_string (); -} + std::string unsafety = ""; + if (get_unsafety () == Unsafety::Unsafe) + unsafety = "unsafe "; -bool -FnPtr::can_eq (const BaseType *other, bool emit_errors) const -{ - FnptrCmp r (this, emit_errors); - return r.can_eq (other); + std::string abi = get_string_from_abi (get_abi ()); + return unsafety + "abi:" + abi + " " + "fnptr (" + params_str + ") -> " + + get_return_type ()->as_string (); } bool @@ -2254,12 +2342,48 @@ BaseType * FnPtr::clone () const { std::vector<TyVar> cloned_params; + cloned_params.reserve (params.size ()); + for (auto &p : params) - cloned_params.push_back (TyVar (p.get_ref ())); + cloned_params.emplace_back (p.get_ref ()); return new FnPtr (get_ref (), get_ty_ref (), ident.locus, - std::move (cloned_params), result_type, - get_combined_refs ()); + std::move (cloned_params), result_type, get_abi (), + get_unsafety (), get_combined_refs ()); +} + +FnPtr * +FnPtr::handle_substitions (SubstitutionArgumentMappings &mappings) +{ + auto &mappings_table = Analysis::Mappings::get (); + + auto fn = clone ()->as<FnPtr> (); + fn->set_ref (mappings_table.get_next_hir_id ()); + fn->set_ty_ref (mappings_table.get_next_hir_id ()); + + if (!fn->result_type.get_tyty ()->is_concrete ()) + { + BaseType *concrete + = Resolver::SubstMapperInternal::Resolve (fn->result_type.get_tyty (), + mappings); + fn->result_type + = TyVar::subst_covariant_var (fn->result_type.get_tyty (), concrete); + } + + for (size_t i = 0; i < fn->params.size (); i++) + { + TyVar &field = fn->params.at (i); + if (!field.get_tyty ()->is_concrete ()) + { + BaseType *concrete + = Resolver::SubstMapperInternal::Resolve (field.get_tyty (), + mappings); + fn->params[i] + = TyVar::subst_covariant_var (field.get_tyty (), concrete); + } + } + + return fn; } void @@ -2282,13 +2406,6 @@ ClosureType::as_string () const } bool -ClosureType::can_eq (const BaseType *other, bool emit_errors) const -{ - ClosureCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool ClosureType::is_equal (const BaseType &other) const { if (other.get_kind () != TypeKind::CLOSURE) @@ -2385,14 +2502,10 @@ ArrayType::accept_vis (TyConstVisitor &vis) const std::string ArrayType::as_string () const { - return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]"; -} + auto cap = get_capacity (); + std::string capacity_str = cap->as_string (); -bool -ArrayType::can_eq (const BaseType *other, bool emit_errors) const -{ - ArrayCmp r (this, emit_errors); - return r.can_eq (other); + return "[" + get_element_type ()->as_string () + "; " + capacity_str + "]"; } bool @@ -2422,9 +2535,15 @@ ArrayType::get_var_element_type () const } BaseType * +ArrayType::get_capacity () const +{ + return capacity.get_tyty (); +} + +BaseType * ArrayType::clone () const { - return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity_expr, + return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity, element_type, get_combined_refs ()); } @@ -2441,6 +2560,13 @@ ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings) BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings); ref->element_type = TyVar::subst_covariant_var (base, concrete); + // handle capacity type + auto cap = ref->get_capacity (); + BaseType *concrete_cap + = Resolver::SubstMapperInternal::Resolve (cap, mappings); + rust_assert (concrete_cap->get_kind () == TyTy::TypeKind::CONST); + ref->capacity = TyVar::subst_covariant_var (cap, concrete_cap); + return ref; } @@ -2463,13 +2589,6 @@ SliceType::as_string () const } bool -SliceType::can_eq (const BaseType *other, bool emit_errors) const -{ - SliceCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool SliceType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -2556,13 +2675,6 @@ BoolType::as_string () const return "bool"; } -bool -BoolType::can_eq (const BaseType *other, bool emit_errors) const -{ - BoolCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * BoolType::clone () const { @@ -2629,13 +2741,6 @@ IntType::as_string () const return "__unknown_int_type"; } -bool -IntType::can_eq (const BaseType *other, bool emit_errors) const -{ - IntCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * IntType::clone () const { @@ -2714,13 +2819,6 @@ UintType::as_string () const return "__unknown_uint_type"; } -bool -UintType::can_eq (const BaseType *other, bool emit_errors) const -{ - UintCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * UintType::clone () const { @@ -2793,13 +2891,6 @@ FloatType::as_string () const return "__unknown_float_type"; } -bool -FloatType::can_eq (const BaseType *other, bool emit_errors) const -{ - FloatCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * FloatType::clone () const { @@ -2855,13 +2946,6 @@ USizeType::as_string () const return "usize"; } -bool -USizeType::can_eq (const BaseType *other, bool emit_errors) const -{ - USizeCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * USizeType::clone () const { @@ -2906,13 +2990,6 @@ ISizeType::as_string () const return "isize"; } -bool -ISizeType::can_eq (const BaseType *other, bool emit_errors) const -{ - ISizeCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * ISizeType::clone () const { @@ -2957,13 +3034,6 @@ CharType::as_string () const return "char"; } -bool -CharType::can_eq (const BaseType *other, bool emit_errors) const -{ - CharCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * CharType::clone () const { @@ -3078,13 +3148,6 @@ ReferenceType::get_name () const } bool -ReferenceType::can_eq (const BaseType *other, bool emit_errors) const -{ - ReferenceCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool ReferenceType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -3240,13 +3303,6 @@ PointerType::get_name () const } bool -PointerType::can_eq (const BaseType *other, bool emit_errors) const -{ - PointerCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool PointerType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -3297,33 +3353,26 @@ PointerType::handle_substitions (SubstitutionArgumentMappings &mappings) // PARAM Type ParamType::ParamType (std::string symbol, location_t locus, HirId ref, - HIR::GenericParam ¶m, std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs) - : BaseType (ref, ref, KIND, - {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), - locus}, - specified_bounds, refs), - is_trait_self (false), symbol (symbol), param (param) + : BaseGeneric (ref, ref, KIND, + {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), + locus}, + specified_bounds, refs), + is_trait_self (false), symbol (symbol) {} ParamType::ParamType (bool is_trait_self, std::string symbol, location_t locus, - HirId ref, HirId ty_ref, HIR::GenericParam ¶m, + HirId ref, HirId ty_ref, std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs) - : BaseType (ref, ty_ref, KIND, - {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), - locus}, - specified_bounds, refs), - is_trait_self (is_trait_self), symbol (symbol), param (param) + : BaseGeneric (ref, ty_ref, KIND, + {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), + locus}, + specified_bounds, refs), + is_trait_self (is_trait_self), symbol (symbol) {} -HIR::GenericParam & -ParamType::get_generic_param () -{ - return param; -} - bool ParamType::can_resolve () const { @@ -3363,18 +3412,11 @@ ParamType::get_name () const return destructure ()->get_name (); } -bool -ParamType::can_eq (const BaseType *other, bool emit_errors) const -{ - ParamCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * ParamType::clone () const { return new ParamType (is_trait_self, get_symbol (), ident.locus, get_ref (), - get_ty_ref (), param, get_specified_bounds (), + get_ty_ref (), get_specified_bounds (), get_combined_refs ()); } @@ -3428,7 +3470,9 @@ ParamType::is_equal (const BaseType &other) const return false; if (can_resolve ()) - return resolve ()->can_eq (other2.resolve (), false); + return Resolver::types_compatable (TyTy::TyWithLocation (resolve ()), + TyTy::TyWithLocation (other2.resolve ()), + UNKNOWN_LOCATION, false, false); return get_symbol ().compare (other2.get_symbol ()) == 0; } @@ -3444,12 +3488,12 @@ ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) ParamType *p = static_cast<ParamType *> (clone ()); subst_mappings.on_param_subst (*p, arg); - // there are two cases one where we substitute directly to a new PARAM and - // otherwise - if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM) + const BaseType *resolved = arg.get_tyty (); + if (resolved->get_kind () == TyTy::TypeKind::PARAM) { - p->set_ty_ref (arg.get_tyty ()->get_ref ()); - return p; + const ParamType &pp = *static_cast<const ParamType *> (resolved); + if (pp.can_resolve ()) + pp.resolve (); } // this is the new subst that this needs to pass @@ -3471,6 +3515,399 @@ ParamType::is_implicit_self_trait () const return is_trait_self; } +static std::string +generate_tree_str (tree value) +{ + char *buf = nullptr; + size_t size = 0; + + FILE *stream = open_memstream (&buf, &size); + if (!stream) + return "<error>"; + + print_generic_stmt (stream, value, TDF_NONE); + fclose (stream); + + std::string result = (buf ? std::string (buf, size) : "<error>"); + free (buf); + + if (!result.empty () && result.back () == '\n') + result.pop_back (); + + return result; +} + +// --- + +ConstParamType::ConstParamType (std::string symbol, location_t locus, + BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs) + : BaseConstType (type), + BaseGeneric (ref, ty_ref, KIND, + {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), + locus}, + {}, refs), + symbol (symbol) +{} + +BaseConstType::ConstKind +ConstParamType::const_kind () const +{ + return BaseConstType::ConstKind::Decl; +} + +std::string +ConstParamType::get_symbol () const +{ + return symbol; +} + +bool +ConstParamType::can_resolve () const +{ + return get_ref () != get_ty_ref (); +} + +BaseType * +ConstParamType::resolve () const +{ + TyVar var (get_ty_ref ()); + BaseType *r = var.get_tyty (); + + while (r->get_kind () == TypeKind::CONST) + { + TyVar v (r->get_ty_ref ()); + BaseType *n = v.get_tyty (); + + // fix infinite loop + if (r == n) + break; + + r = n; + } + + if (r->get_kind () == TypeKind::CONST && (r->get_ref () == r->get_ty_ref ())) + { + auto *const_type = r->as_const_type (); + if (const_type->const_kind () != BaseConstType::ConstKind::Value) + return TyVar (r->get_ty_ref ()).get_tyty (); + } + + return r; +} + +void +ConstParamType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstParamType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); +} + +std::string +ConstParamType::as_string () const +{ + if (!can_resolve ()) + { + return get_symbol () + " CONST_REF: " + std::to_string (get_ref ()); + } + + BaseType *lookup = resolve (); + // Avoid infinite recursion if resolve() returns this same type + if (lookup == this->as_base_type ()) + { + return get_symbol () + " CONST_REF: " + std::to_string (get_ref ()); + } + + return get_symbol () + "=" + lookup->as_string (); +} + +BaseType * +ConstParamType::clone () const +{ + return new ConstParamType (get_symbol (), ident.locus, specified_type, + get_ref (), get_ty_ref (), get_combined_refs ()); +} + +std::string +ConstParamType::get_name () const +{ + if (!can_resolve ()) + return get_symbol (); + + BaseType *lookup = resolve (); + if (lookup == this->as_base_type ()) + return get_symbol () + ":" + get_specified_type ()->get_name (); + + return lookup->get_name (); +} + +bool +ConstParamType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + { + if (!can_resolve ()) + return false; + + return resolve ()->is_equal (other); + } + + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Decl) + return false; + + auto &other2 = static_cast<const ConstParamType &> (*other_const); + if (can_resolve () != other2.can_resolve ()) + return false; + + if (can_resolve ()) + { + // 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; +} + +BaseType * +ConstParamType::handle_substitions ( + SubstitutionArgumentMappings &subst_mappings) +{ + SubstitutionArg arg = SubstitutionArg::error (); + bool ok = subst_mappings.get_argument_for_symbol (this, &arg); + if (!ok || arg.is_error ()) + return this; + + ConstParamType *p = static_cast<ConstParamType *> (clone ()); + const BaseType *resolved = arg.get_tyty (); + + // this is the new subst that this needs to pass + p->set_ref (mappings.get_next_hir_id ()); + p->set_ty_ref (resolved->get_ref ()); + + return p; +} + +// --- ConstValueType + +ConstValueType::ConstValueType (tree value, BaseType *type, HirId ref, + HirId ty_ref, std::set<HirId> refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type), folded_val (value) +{} + +BaseConstType::ConstKind +ConstValueType::const_kind () const +{ + return BaseConstType::ConstKind::Value; +} + +void +ConstValueType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstValueType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); +} + +std::string +ConstValueType::as_string () const +{ + return generate_tree_str (folded_val); +} + +BaseType * +ConstValueType::clone () const +{ + return new ConstValueType (folded_val, specified_type, get_ref (), + get_ty_ref (), get_combined_refs ()); +} + +std::string +ConstValueType::get_name () const +{ + return as_string (); +} + +bool +ConstValueType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + return false; + + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Value) + return false; + + auto &other2 = static_cast<const ConstValueType &> (*other_const); + return folded_val == other2.folded_val; +} + +tree +ConstValueType::get_value () const +{ + return folded_val; +} + +// --- ConstInferType + +ConstInferType::ConstInferType (BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type) +{} + +BaseConstType::ConstKind +ConstInferType::const_kind () const +{ + return BaseConstType::ConstKind::Infer; +} + +void +ConstInferType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstInferType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); +} + +std::string +ConstInferType::as_string () const +{ + return specified_type->get_name () + "-?"; +} + +BaseType * +ConstInferType::clone () const +{ + auto &mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); + + ConstInferType *clone + = new ConstInferType (specified_type, mappings.get_next_hir_id (), + get_ty_ref (), get_combined_refs ()); + + context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (), + UNKNOWN_NODEID, + clone->get_ref (), + UNKNOWN_LOCAL_DEFID), + clone); + mappings.insert_location (clone->get_ref (), + mappings.lookup_location (get_ref ())); + + clone->append_reference (get_ref ()); + + return clone; +} + +std::string +ConstInferType::get_name () const +{ + return as_string (); +} + +bool +ConstInferType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + return false; + + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Infer) + return false; + + return get_ref () == other.get_ref (); +} + +// --- ConstErrorType + +ConstErrorType::ConstErrorType (BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type) +{} + +BaseConstType::ConstKind +ConstErrorType::const_kind () const +{ + return BaseConstType::ConstKind::Error; +} + +void +ConstErrorType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstErrorType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); +} + +std::string +ConstErrorType::as_string () const +{ + return "<const_error>"; +} + +BaseType * +ConstErrorType::clone () const +{ + return new ConstErrorType (specified_type, get_ref (), get_ty_ref (), + get_combined_refs ()); +} + +std::string +ConstErrorType::get_name () const +{ + return as_string (); +} + +bool +ConstErrorType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + return false; + + auto other_const = other.as_const_type (); + return other_const->const_kind () == BaseConstType::ConstKind::Error; +} + // OpaqueType OpaqueType::OpaqueType (location_t locus, HirId ref, @@ -3521,13 +3958,6 @@ OpaqueType::get_name () const return "impl " + raw_bounds_as_name (); } -bool -OpaqueType::can_eq (const BaseType *other, bool emit_errors) const -{ - OpaqueCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * OpaqueType::clone () const { @@ -3539,28 +3969,7 @@ BaseType * OpaqueType::resolve () const { TyVar var (get_ty_ref ()); - BaseType *r = var.get_tyty (); - - while (r->get_kind () == TypeKind::OPAQUE) - { - OpaqueType *rr = static_cast<OpaqueType *> (r); - if (!rr->can_resolve ()) - break; - - TyVar v (rr->get_ty_ref ()); - BaseType *n = v.get_tyty (); - - // fix infinite loop - if (r == n) - break; - - r = n; - } - - if (r->get_kind () == TypeKind::OPAQUE && (r->get_ref () == r->get_ty_ref ())) - return TyVar (r->get_ty_ref ()).get_tyty (); - - return r; + return var.get_tyty (); } bool @@ -3570,39 +3979,24 @@ OpaqueType::is_equal (const BaseType &other) const if (can_resolve () != other2.can_resolve ()) return false; - if (can_resolve ()) - return resolve ()->can_eq (other2.resolve (), false); - - return bounds_compatible (other, UNDEF_LOCATION, false); -} - -OpaqueType * -OpaqueType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) -{ - // SubstitutionArg arg = SubstitutionArg::error (); - // bool ok = subst_mappings.get_argument_for_symbol (this, &arg); - // if (!ok || arg.is_error ()) - // return this; - - // OpaqueType *p = static_cast<OpaqueType *> (clone ()); - // subst_mappings.on_param_subst (*p, arg); - - // // there are two cases one where we substitute directly to a new PARAM and - // // otherwise - // if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM) - // { - // p->set_ty_ref (arg.get_tyty ()->get_ref ()); - // return p; - // } + if (num_specified_bounds () != other.num_specified_bounds ()) + return false; - // // this is the new subst that this needs to pass - // p->set_ref (mappings.get_next_hir_id ()); - // p->set_ty_ref (arg.get_tyty ()->get_ref ()); + for (const auto &pred : specified_bounds) + { + bool found = false; + for (const auto &opred : other.get_specified_bounds ()) + { + found = pred.is_equal (opred); + if (found) + break; + } - // return p; + if (!found) + return false; + } - rust_unreachable (); - return nullptr; + return true; } // StrType @@ -3650,13 +4044,6 @@ StrType::as_string () const } bool -StrType::can_eq (const BaseType *other, bool emit_errors) const -{ - StrCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool StrType::is_equal (const BaseType &other) const { return get_kind () == other.get_kind (); @@ -3700,13 +4087,6 @@ NeverType::as_string () const return "!"; } -bool -NeverType::can_eq (const BaseType *other, bool emit_errors) const -{ - NeverCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * NeverType::clone () const { @@ -3762,13 +4142,6 @@ PlaceholderType::as_string () const + ">"; } -bool -PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const -{ - PlaceholderCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * PlaceholderType::clone () const { @@ -3905,12 +4278,6 @@ ProjectionType::as_string () const return "<Projection=" + subst_as_string () + "::" + base->as_string () + ">"; } -bool -ProjectionType::can_eq (const BaseType *other, bool emit_errors) const -{ - return base->can_eq (other, emit_errors); -} - BaseType * ProjectionType::clone () const { @@ -4024,13 +4391,6 @@ DynamicObjectType::as_string () const return "dyn [" + raw_bounds_as_string () + "]"; } -bool -DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const -{ - DynamicCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * DynamicObjectType::clone () const { @@ -4053,7 +4413,21 @@ DynamicObjectType::is_equal (const BaseType &other) const if (num_specified_bounds () != other.num_specified_bounds ()) return false; - return bounds_compatible (other, UNDEF_LOCATION, false); + for (const auto &pred : specified_bounds) + { + bool found = false; + for (const auto &opred : other.get_specified_bounds ()) + { + found = pred.is_equal (opred); + if (found) + break; + } + + if (!found) + return false; + } + + return true; } const std::vector< @@ -4074,7 +4448,7 @@ DynamicObjectType::get_object_items () const if (item->get_trait_item_type () == Resolver::TraitItemReference::TraitItemType::FN && item->is_object_safe ()) - items.push_back ({item, &bound}); + items.emplace_back (item, &bound); } } return items; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index e814f07..50f6347 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -19,16 +19,17 @@ #ifndef RUST_TYTY #define RUST_TYTY +#include "optional.h" #include "rust-hir-map.h" #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" #include "rust-system.h" #include "rust-hir.h" +#include "tree.h" namespace Rust { @@ -56,6 +57,7 @@ enum TypeKind REF, POINTER, PARAM, + CONST, ARRAY, SLICE, FNDEF, @@ -78,8 +80,7 @@ enum TypeKind ERROR }; -extern bool -is_primitive_type_kind (TypeKind kind); +extern bool is_primitive_type_kind (TypeKind kind); class TypeKindFormat { @@ -89,6 +90,128 @@ 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: @@ -108,35 +231,24 @@ public: virtual std::string as_string () const = 0; virtual std::string get_name () const = 0; - // similar to unify but does not actually perform type unification but - // determines whether they are compatible. Consider the following - // - // fn foo<T>() -> T { ... } - // fn foo() -> i32 { ... } - // - // when the function has been substituted they can be considered equal. - // - // It can also be used to optional emit errors for trait item compatibility - // checks - virtual bool can_eq (const BaseType *other, bool emit_errors) const = 0; - // Check value equality between two ty. Type inference rules are ignored. Two // ty are considered equal if they're of the same kind, and // 1. (For ADTs, arrays, tuples, refs) have the same underlying ty // 2. (For functions) have the same signature virtual bool is_equal (const BaseType &other) const; - bool satisfies_bound (const TypeBoundPredicate &predicate, - bool emit_error) const; + bool satisfies_bound (const TypeBoundPredicate &predicate, bool emit_error); - bool bounds_compatible (const BaseType &other, location_t locus, - bool emit_error) const; + bool bounds_compatible (BaseType &other, location_t locus, bool emit_error); void inherit_bounds (const BaseType &other); void inherit_bounds ( const std::vector<TyTy::TypeBoundPredicate> &specified_bounds); + // contains_infer checks if there is an inference variable inside the type + const TyTy::BaseType *contains_infer () const; + // is_unit returns whether this is just a unit-struct bool is_unit () const; @@ -162,8 +274,7 @@ public: void debug () const; - // FIXME this will eventually go away - const BaseType *get_root () const; + BaseType *get_root (); // This will get the monomorphized type from Params, Placeholders or // Projections if available or error @@ -236,6 +347,11 @@ public: return static_cast<T *> (this); } + // Helper to get BaseConstType interface for CONST types + // Overridden by const types that also inherit from BaseConstType + virtual BaseConstType *as_const_type () { return nullptr; } + virtual const BaseConstType *as_const_type () const { return nullptr; } + protected: BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident, std::set<HirId> refs = std::set<HirId> ()); @@ -265,8 +381,8 @@ public: {} WARN_UNUSED_RESULT virtual size_t get_num_params () const = 0; - WARN_UNUSED_RESULT virtual BaseType * - get_param_type_at (size_t index) const = 0; + WARN_UNUSED_RESULT virtual BaseType *get_param_type_at (size_t index) const + = 0; WARN_UNUSED_RESULT virtual BaseType *get_return_type () const = 0; }; @@ -323,8 +439,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; InferTypeKind get_infer_kind () const; @@ -355,25 +469,39 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_name () const override final; }; -class ParamType : public BaseType +class BaseGeneric : public BaseType +{ +public: + virtual std::string get_symbol () const = 0; + + virtual bool can_resolve () const = 0; + + virtual BaseType *resolve () const = 0; + +protected: + BaseGeneric (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident, + std::vector<TypeBoundPredicate> specified_bounds, + std::set<HirId> refs = std::set<HirId> ()) + : BaseType (ref, ty_ref, kind, ident, specified_bounds, refs) + {} +}; + +class ParamType : public BaseGeneric { public: static constexpr auto KIND = TypeKind::PARAM; ParamType (std::string symbol, location_t locus, HirId ref, - HIR::GenericParam ¶m, std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs = std::set<HirId> ()); ParamType (bool is_trait_self, std::string symbol, location_t locus, - HirId ref, HirId ty_ref, HIR::GenericParam ¶m, + HirId ref, HirId ty_ref, std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs = std::set<HirId> ()); @@ -382,17 +510,13 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; - std::string get_symbol () const; + std::string get_symbol () const override final; - HIR::GenericParam &get_generic_param (); + bool can_resolve () const override final; - bool can_resolve () const; - - BaseType *resolve () const; + BaseType *resolve () const override final; std::string get_name () const override final; @@ -406,7 +530,170 @@ public: private: bool is_trait_self; std::string symbol; - HIR::GenericParam ¶m; +}; + +class BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + enum ConstKind + { + Decl, + Value, + Infer, + Error + }; + + virtual ConstKind const_kind () const = 0; + + BaseType *get_specified_type () const { return specified_type; } + + // Helper to get BaseType interface (all const types also inherit BaseType) + // This must be implemented by concrete classes since BaseConstType doesn't + // inherit from BaseType, but all concrete const types do. + virtual BaseType *as_base_type () = 0; + virtual const BaseType *as_base_type () const = 0; + +protected: + BaseConstType (BaseType *type) : specified_type (type) {} + + BaseType *specified_type; +}; + +class ConstParamType : public BaseConstType, public BaseGeneric +{ +public: + ConstParamType (std::string symbol, location_t locus, BaseType *type, + HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()); + + ConstKind const_kind () const override final; + + std::string get_symbol () const override final; + + bool can_resolve () const override final; + + BaseType *resolve () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + BaseType *handle_substitions (SubstitutionArgumentMappings &mappings); + + BaseType *as_base_type () override { return static_cast<BaseType *> (this); } + const BaseType *as_base_type () const override + { + return static_cast<const BaseType *> (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } + +private: + std::string symbol; +}; + +class ConstValueType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstValueType (tree value, BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + tree get_value () const; + + BaseType *as_base_type () override { return static_cast<BaseType *> (this); } + const BaseType *as_base_type () const override + { + return static_cast<const BaseType *> (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } + +private: + tree folded_val; +}; + +class ConstInferType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstInferType (BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + BaseType *as_base_type () override { return static_cast<BaseType *> (this); } + const BaseType *as_base_type () const override + { + return static_cast<const BaseType *> (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } +}; + +class ConstErrorType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstErrorType (BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + BaseType *as_base_type () override { return static_cast<BaseType *> (this); } + const BaseType *as_base_type () const override + { + return static_cast<const BaseType *> (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } }; class OpaqueType : public BaseType @@ -427,8 +714,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; bool can_resolve () const; @@ -438,8 +723,6 @@ public: std::string get_name () const override final; bool is_equal (const BaseType &other) const override; - - OpaqueType *handle_substitions (SubstitutionArgumentMappings &mappings); }; class StructFieldType @@ -490,8 +773,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; size_t num_fields () const; @@ -510,96 +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 predicate 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); - - void apply_argument_mappings (SubstitutionArgumentMappings &arguments); - - bool contains_item (const std::string &search) const; - - TypeBoundPredicateItem - lookup_associated_item (const std::string &search) const; - - 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); - - DefId reference; - location_t locus; - bool error_flag; - BoundPolarity polarity; - std::vector<TyTy::TypeBoundPredicate> super_traits; -}; - class TypeBoundPredicateItem { public: @@ -711,12 +902,22 @@ public: ENUM }; + enum ReprKind + { + RUST, + C, + INT, + ALIGN, + PACKED, + // TRANSPARENT, + // SIMD, + // ... + }; + // Representation options, specified via attributes e.g. #[repr(packed)] struct ReprOptions { - // bool is_c; - // bool is_transparent; - //... + ReprKind repr_kind = ReprKind::RUST; // For align and pack: 0 = unspecified. Nonzero = byte alignment. // It is an error for both to be nonzero, this should be caught when @@ -770,8 +971,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; std::string get_identifier () const { return identifier; } @@ -877,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, @@ -922,8 +1122,6 @@ public: std::string get_identifier () const { return identifier; } - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; size_t num_params () const { return params.size (); } @@ -940,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 @@ -995,19 +1198,22 @@ public: static constexpr auto KIND = TypeKind::FNPTR; FnPtr (HirId ref, location_t locus, std::vector<TyVar> params, - TyVar result_type, std::set<HirId> refs = std::set<HirId> ()) + TyVar result_type, ABI abi, Unsafety unsafety, + std::set<HirId> refs = std::set<HirId> ()) : CallableTypeInterface (ref, ref, TypeKind::FNPTR, {Resolver::CanonicalPath::create_empty (), locus}, refs), - params (std::move (params)), result_type (result_type) + params (std::move (params)), result_type (result_type), abi (abi), + unsafety (unsafety) {} FnPtr (HirId ref, HirId ty_ref, location_t locus, std::vector<TyVar> params, - TyVar result_type, std::set<HirId> refs = std::set<HirId> ()) + TyVar result_type, ABI abi, Unsafety unsafety, + std::set<HirId> refs = std::set<HirId> ()) : CallableTypeInterface (ref, ty_ref, TypeKind::FNPTR, {Resolver::CanonicalPath::create_empty (), locus}, refs), - params (params), result_type (result_type) + params (params), result_type (result_type), abi (abi), unsafety (unsafety) {} std::string get_name () const override final { return as_string (); } @@ -1036,8 +1242,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1045,9 +1249,17 @@ public: std::vector<TyVar> &get_params () { return params; } const std::vector<TyVar> &get_params () const { return params; } + ABI get_abi () const { return abi; } + + Unsafety get_unsafety () const { return unsafety; } + + FnPtr *handle_substitions (SubstitutionArgumentMappings &mappings); + private: std::vector<TyVar> params; TyVar result_type; + ABI abi; + Unsafety unsafety; }; class ClosureType : public CallableTypeInterface, public SubstitutionRef @@ -1113,8 +1325,6 @@ public: std::string as_string () const override; std::string get_name () const override final { return as_string (); } - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1143,19 +1353,18 @@ class ArrayType : public BaseType public: static constexpr auto KIND = TypeKind::ARRAY; - ArrayType (HirId ref, location_t locus, HIR::Expr &capacity_expr, TyVar base, + ArrayType (HirId ref, location_t locus, TyVar capacity, TyVar base, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ref, TypeKind::ARRAY, {Resolver::CanonicalPath::create_empty (), locus}, refs), - element_type (base), capacity_expr (capacity_expr) + element_type (base), capacity (capacity) {} - ArrayType (HirId ref, HirId ty_ref, location_t locus, - HIR::Expr &capacity_expr, TyVar base, - std::set<HirId> refs = std::set<HirId> ()) + ArrayType (HirId ref, HirId ty_ref, location_t locus, TyVar capacity, + TyVar base, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ty_ref, TypeKind::ARRAY, {Resolver::CanonicalPath::create_empty (), locus}, refs), - element_type (base), capacity_expr (capacity_expr) + element_type (base), capacity (capacity) {} void accept_vis (TyVisitor &vis) override; @@ -1165,8 +1374,6 @@ public: std::string get_name () const override final { return as_string (); } - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *get_element_type () const; @@ -1174,15 +1381,14 @@ public: BaseType *clone () const final override; - HIR::Expr &get_capacity_expr () const { return capacity_expr; } + BaseType *get_capacity () const; + const TyVar &get_capacity_var () const { return capacity; } ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings); private: TyVar element_type; - // FIXME: I dont think this should be in tyty - tyty should already be const - // evaluated - HIR::Expr &capacity_expr; + TyVar capacity; }; class SliceType : public BaseType @@ -1211,8 +1417,6 @@ public: std::string get_name () const override final { return as_string (); } - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *get_element_type () const; @@ -1241,8 +1445,6 @@ public: std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; }; @@ -1271,8 +1473,6 @@ public: std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - IntKind get_int_kind () const; BaseType *clone () const final override; @@ -1309,8 +1509,6 @@ public: std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - UintKind get_uint_kind () const; BaseType *clone () const final override; @@ -1343,8 +1541,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - FloatKind get_float_kind () const; BaseType *clone () const final override; @@ -1370,8 +1566,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; }; @@ -1390,8 +1584,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; }; @@ -1409,8 +1601,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; }; @@ -1429,8 +1619,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1454,8 +1642,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1490,8 +1676,6 @@ public: std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1534,8 +1718,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1581,8 +1763,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_name () const override final; @@ -1605,8 +1785,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_name () const override final; @@ -1656,8 +1834,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_name () const override final; diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 294b677..36dbc0e 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -17,35 +17,53 @@ // <http://www.gnu.org/licenses/>. #include "rust-unify.h" +#include "fold-const.h" +#include "rust-tyty-util.h" +#include "rust-tyty.h" namespace Rust { namespace Resolver { +static TyTy::BaseType * +unify_error_type_node () +{ + static TyTy::BaseType *error = nullptr; + if (error == nullptr) + error = new TyTy::ErrorType (0); + return error; +} + UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus, bool commit_flag, bool emit_error, - bool infer, std::vector<CommitSite> &commits, + bool check_bounds, bool infer, + std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers) : lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag), - emit_error (emit_error), infer_flag (infer), commits (commits), - infers (infers), mappings (Analysis::Mappings::get ()), - context (*TypeCheckContext::get ()) + emit_error (emit_error), infer_flag (infer), + check_bounds_flag (check_bounds), commits (commits), infers (infers), + mappings (Analysis::Mappings::get ()), context (*TypeCheckContext::get ()) {} TyTy::BaseType * UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus, bool commit_flag, bool emit_error, - bool infer, std::vector<CommitSite> &commits, + bool check_bounds, bool infer, + std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers) { - UnifyRules r (lhs, rhs, locus, commit_flag, emit_error, infer, commits, - infers); + UnifyRules r (lhs, rhs, locus, commit_flag, emit_error, infer, check_bounds, + commits, infers); TyTy::BaseType *result = r.go (); - commits.push_back ({lhs.get_ty (), rhs.get_ty (), result}); - if (r.commit_flag) - UnifyRules::commit (lhs.get_ty (), rhs.get_ty (), result); - bool failed = result->get_kind () == TyTy::TypeKind::ERROR; + + commits.emplace_back (lhs.get_ty (), rhs.get_ty (), result); + if (r.commit_flag && !failed) + { + result = result->clone (); + UnifyRules::commit (lhs.get_ty (), rhs.get_ty (), result); + } + if (failed && r.emit_error) r.emit_type_mismatch (); @@ -53,6 +71,22 @@ UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, } TyTy::BaseType * +UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs) +{ + TyTy::BaseType *result + = UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error, infer_flag, + check_bounds_flag, commits, infers); + + // If the recursive call resulted in an error and would have emitted an error + // message, disable error emission for the current level to avoid duplicate + // errors + if (result->get_kind () == TyTy::TypeKind::ERROR && emit_error) + emit_error = false; + + return result; +} + +TyTy::BaseType * UnifyRules::get_base () { return lhs.get_ty ()->destructure (); @@ -69,7 +103,6 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other, TyTy::BaseType *resolved) { TypeCheckContext &context = *TypeCheckContext::get (); - Analysis::Mappings &mappings = Analysis::Mappings::get (); TyTy::BaseType *b = base->destructure (); TyTy::BaseType *o = other->destructure (); @@ -86,28 +119,58 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other, b->append_reference (resolved->get_ref ()); b->append_reference (o->get_ref ()); - bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER; - bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER; - bool results_is_non_general_infer_var - = (result_is_infer_var - && (static_cast<TyTy::InferType *> (resolved))->get_infer_kind () - != TyTy::InferType::GENERAL); - if (result_resolved || results_is_non_general_infer_var) + if (resolved->get_kind () != TyTy::TypeKind::CONST) { - for (auto &ref : resolved->get_combined_refs ()) + bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER; + bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER; + bool results_is_non_general_infer_var + = (result_is_infer_var + && (static_cast<TyTy::InferType *> (resolved))->get_infer_kind () + != TyTy::InferType::GENERAL); + if (result_resolved || results_is_non_general_infer_var) { - TyTy::BaseType *ref_tyty = nullptr; - bool ok = context.lookup_type (ref, &ref_tyty); - if (!ok) - continue; + for (auto &ref : resolved->get_combined_refs ()) + { + TyTy::BaseType *ref_tyty = nullptr; + bool ok = context.lookup_type (ref, &ref_tyty); + if (!ok) + continue; + + // if any of the types are inference variables lets fix them + if (ref_tyty->is<TyTy::InferType> ()) + context.insert_implicit_type (ref, resolved); + } + } + } + else + { + auto base_const = resolved->as_const_type (); + if (base_const->const_kind () == TyTy::BaseConstType::ConstKind::Value) + { + rust_debug ("UnifyRules::commit const value, resolved_ref=%u " + "resolved_ty_ref=%u combined_refs.size=%zu", + resolved->get_ref (), resolved->get_ty_ref (), + resolved->get_combined_refs ().size ()); - // if any of the types are inference variables lets fix them - if (ref_tyty->get_kind () == TyTy::TypeKind::INFER) + for (auto &ref : resolved->get_combined_refs ()) { - auto node = Analysis::NodeMapping (mappings.get_current_crate (), - UNKNOWN_NODEID, ref, - UNKNOWN_LOCAL_DEFID); - context.insert_type (node, resolved->clone ()); + TyTy::BaseType *ref_tyty = nullptr; + bool ok = context.lookup_type (ref, &ref_tyty); + if (!ok) + continue; + if (ref_tyty->get_kind () != TyTy::TypeKind::CONST) + continue; + + auto ref_base_const = ref_tyty->as_const_type (); + if (ref_base_const->const_kind () + == TyTy::BaseConstType::ConstKind::Infer + || ref_base_const->const_kind () + == TyTy::BaseConstType::ConstKind::Decl) + { + rust_debug (" committing to ref=%u kind=%d", ref, + (int) ref_base_const->const_kind ()); + context.insert_implicit_type (ref, resolved); + } } } } @@ -142,39 +205,40 @@ UnifyRules::emit_abi_mismatch (const TyTy::FnType &expected, TyTy::BaseType * UnifyRules::go () { - TyTy::BaseType *ltype = lhs.get_ty (); - TyTy::BaseType *rtype = rhs.get_ty (); - - ltype = lhs.get_ty ()->destructure (); - rtype = rhs.get_ty ()->destructure (); + TyTy::BaseType *ltype = lhs.get_ty ()->destructure (); + TyTy::BaseType *rtype = rhs.get_ty ()->destructure (); rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (), rtype->debug_str ().c_str ()); - // check bounds - bool ltype_is_placeholder = ltype->get_kind () == TyTy::TypeKind::PLACEHOLDER; - bool rtype_is_placeholder = rtype->get_kind () == TyTy::TypeKind::PLACEHOLDER; - bool types_equal = ltype->is_equal (*rtype); - bool should_check_bounds - = !types_equal && !(ltype_is_placeholder || rtype_is_placeholder); - if (should_check_bounds) + if (check_bounds_flag) { - if (ltype->num_specified_bounds () > 0) + bool ltype_is_placeholder + = ltype->get_kind () == TyTy::TypeKind::PLACEHOLDER; + bool rtype_is_placeholder + = rtype->get_kind () == TyTy::TypeKind::PLACEHOLDER; + bool types_equal = ltype->is_equal (*rtype); + bool should_check_bounds + = !types_equal && !(ltype_is_placeholder || rtype_is_placeholder); + if (should_check_bounds) { - if (!ltype->bounds_compatible (*rtype, locus, emit_error)) + if (ltype->num_specified_bounds () > 0) { - // already emitted an error - emit_error = false; - return new TyTy::ErrorType (0); + if (!ltype->bounds_compatible (*rtype, locus, emit_error)) + { + // already emitted an error + emit_error = false; + return unify_error_type_node (); + } } - } - else if (rtype->num_specified_bounds () > 0) - { - if (!rtype->bounds_compatible (*ltype, locus, emit_error)) + else if (rtype->num_specified_bounds () > 0) { - // already emitted an error - emit_error = false; - return new TyTy::ErrorType (0); + if (!rtype->bounds_compatible (*ltype, locus, emit_error)) + { + // already emitted an error + emit_error = false; + return unify_error_type_node (); + } } } } @@ -209,7 +273,7 @@ UnifyRules::go () rust_assert (iv.get_tyty ()->get_kind () == TyTy::TypeKind::INFER); TyTy::InferType *i = static_cast<TyTy::InferType *> (iv.get_tyty ()); - infers.push_back ({p->get_ref (), p->get_ty_ref (), p, i}); + infers.emplace_back (p->get_ref (), p->get_ty_ref (), p, i); // FIXME // this is hacky to set the implicit param lets make this a function @@ -226,7 +290,7 @@ UnifyRules::go () rust_assert (iv.get_tyty ()->get_kind () == TyTy::TypeKind::INFER); TyTy::InferType *i = static_cast<TyTy::InferType *> (iv.get_tyty ()); - infers.push_back ({p->get_ref (), p->get_ty_ref (), p, i}); + infers.emplace_back (p->get_ref (), p->get_ty_ref (), p, i); // FIXME // this is hacky to set the implicit param lets make this a function @@ -235,6 +299,68 @@ UnifyRules::go () // set the rtype now to the new inference var ltype = i; } + else if (ltype->get_kind () == TyTy::TypeKind::CONST + && rtype->get_kind () == TyTy::TypeKind::CONST) + { + 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; + bool have_decls + = 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) + { + 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 () + == TyTy::BaseConstType::ConstKind::Decl) + { + 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 ()) @@ -315,11 +441,14 @@ UnifyRules::go () case TyTy::OPAQUE: return expect_opaque (static_cast<TyTy::OpaqueType *> (ltype), rtype); + case TyTy::CONST: + return expect_const (ltype->as_const_type (), rtype); + case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -328,30 +457,33 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); switch (ltype->get_infer_kind ()) { case TyTy::InferType::InferTypeKind::GENERAL: - return rtype->clone (); + return rtype; - case TyTy::InferType::InferTypeKind::INTEGRAL: { + case TyTy::InferType::InferTypeKind::INTEGRAL: + { bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL || r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return rtype->clone (); + return rtype; } break; - case TyTy::InferType::InferTypeKind::FLOAT: { + case TyTy::InferType::InferTypeKind::FLOAT: + { bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT || r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return rtype->clone (); + return rtype; } break; } @@ -361,28 +493,32 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, case TyTy::INT: case TyTy::UINT: case TyTy::USIZE: - case TyTy::ISIZE: { + case TyTy::ISIZE: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) || (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL); if (is_valid) { - ltype->apply_primitive_type_hint (*rtype); - return rtype->clone (); + if (commit_flag) + ltype->apply_primitive_type_hint (*rtype); + return rtype; } } break; - case TyTy::FLOAT: { + case TyTy::FLOAT: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) || (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT); if (is_valid) { - ltype->apply_primitive_type_hint (*rtype); - return rtype->clone (); + if (commit_flag) + ltype->apply_primitive_type_hint (*rtype); + return rtype; } } break; @@ -404,19 +540,21 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, case TyTy::PROJECTION: case TyTy::DYNAMIC: case TyTy::CLOSURE: - case TyTy::OPAQUE: { + case TyTy::CONST: + case TyTy::OPAQUE: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); if (is_valid) - return rtype->clone (); + return rtype; } break; case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -424,30 +562,32 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::ADT: { + case TyTy::ADT: + { TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype); if (ltype->get_adt_kind () != type.get_adt_kind ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (ltype->get_identifier ().compare (type.get_identifier ()) != 0) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (ltype->number_of_variants () != type.number_of_variants ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < type.number_of_variants (); ++i) @@ -457,7 +597,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) if (a->num_fields () != b->num_fields ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t j = 0; j < a->num_fields (); j++) @@ -469,14 +609,11 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) TyTy::BaseType *other_field_ty = other_field->get_field_type (); TyTy::BaseType *unified_ty - = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty), - TyTy::TyWithLocation (other_field_ty), - locus, commit_flag, - false /* emit_error */, infer_flag, - commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_field_ty), + TyTy::TyWithLocation (other_field_ty)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } } @@ -495,19 +632,16 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) auto pa = a.get_param_ty (); auto pb = b.get_param_ty (); - auto res - = UnifyRules::Resolve (TyTy::TyWithLocation (pa), - TyTy::TyWithLocation (pb), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + auto res = resolve_subtype (TyTy::TyWithLocation (pa), + TyTy::TyWithLocation (pb)); if (res->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } } - return type.clone (); + return ltype; } break; @@ -533,10 +667,11 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -544,17 +679,18 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; case TyTy::STR: - return rtype->clone (); + return rtype; case TyTy::ADT: case TyTy::REF: @@ -578,10 +714,11 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -589,28 +726,28 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::REF: { + case TyTy::REF: + { TyTy::ReferenceType &type = *static_cast<TyTy::ReferenceType *> (rtype); auto base_type = ltype->get_base (); auto other_base_type = type.get_base (); TyTy::BaseType *base_resolved - = UnifyRules::Resolve (TyTy::TyWithLocation (base_type), - TyTy::TyWithLocation (other_base_type), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (base_type), + TyTy::TyWithLocation (other_base_type)); if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } // rust is permissive about mutablity here you can always go from @@ -618,12 +755,10 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true; if (!mutability_ok) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ReferenceType (ltype->get_ref (), ltype->get_ty_ref (), - TyTy::TyVar (base_resolved->get_ref ()), - ltype->mutability ()); + return ltype; } break; @@ -649,10 +784,11 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -660,28 +796,28 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::POINTER: { + case TyTy::POINTER: + { TyTy::PointerType &type = *static_cast<TyTy::PointerType *> (rtype); auto base_type = ltype->get_base (); auto other_base_type = type.get_base (); TyTy::BaseType *base_resolved - = UnifyRules::Resolve (TyTy::TyWithLocation (base_type), - TyTy::TyWithLocation (other_base_type), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (base_type), + TyTy::TyWithLocation (other_base_type)); if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } // rust is permissive about mutablity here you can always go from @@ -689,12 +825,10 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true; if (!mutability_ok) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::PointerType (ltype->get_ref (), ltype->get_ty_ref (), - TyTy::TyVar (base_resolved->get_ref ()), - ltype->mutability ()); + return ltype; } break; @@ -720,10 +854,11 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -731,16 +866,18 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::PARAM: { + case TyTy::PARAM: + { TyTy::ParamType &type = *static_cast<TyTy::ParamType *> (rtype); // bool symbol_matches // = ltype->get_symbol ().compare (type.get_symbol ()) == 0; @@ -782,10 +919,11 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -793,30 +931,53 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::ARRAY: { + case TyTy::ARRAY: + { TyTy::ArrayType &type = *static_cast<TyTy::ArrayType *> (rtype); - TyTy::BaseType *element_unify = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_element_type ()), - TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag, - false /* emit_error*/, infer_flag, commits, infers); - - if (element_unify->get_kind () != TyTy::TypeKind::ERROR) - { - return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, - type.get_capacity_expr (), - TyTy::TyVar ( - element_unify->get_ref ())); - } + TyTy::BaseType *element_unify + = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()), + TyTy::TyWithLocation (type.get_element_type ())); + + if (element_unify->get_kind () == TyTy::TypeKind::ERROR) + return unify_error_type_node (); + + auto ltype_cap = ltype->get_capacity (); + auto rtype_cap = type.get_capacity (); + + // If either capacity is not a const type, return error + if (ltype_cap->get_kind () != TyTy::TypeKind::CONST + || rtype_cap->get_kind () != TyTy::TypeKind::CONST) + return unify_error_type_node (); + + bool save_emit_error = emit_error; + emit_error = false; + TyTy::BaseType *capacity_unify + = resolve_subtype (TyTy::TyWithLocation (ltype_cap), + TyTy::TyWithLocation (rtype_cap)); + emit_error = save_emit_error; + + if (capacity_unify->get_kind () != TyTy::TypeKind::CONST) + return unify_error_type_node (); + + auto capacity_type_unify = capacity_unify->as_const_type (); + if (capacity_type_unify->const_kind () + == TyTy::BaseConstType::ConstKind::Error) + return unify_error_type_node (); + + return new TyTy::ArrayType ( + type.get_ref (), type.get_ty_ref (), type.get_ident ().locus, + TyTy::TyVar (capacity_type_unify->as_base_type ()->get_ref ()), + TyTy::TyVar (element_unify->get_ref ())); } break; @@ -842,10 +1003,11 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -853,29 +1015,25 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::SLICE: { + case TyTy::SLICE: + { TyTy::SliceType &type = *static_cast<TyTy::SliceType *> (rtype); - TyTy::BaseType *element_unify = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_element_type ()), - TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag, - false /* emit_error*/, infer_flag, commits, infers); + TyTy::BaseType *element_unify + = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()), + TyTy::TyWithLocation (type.get_element_type ())); if (element_unify->get_kind () != TyTy::TypeKind::ERROR) - { - return new TyTy::SliceType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, - TyTy::TyVar ( - element_unify->get_ref ())); - } + return ltype; } break; @@ -901,10 +1059,11 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -912,20 +1071,22 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::FNDEF: { + case TyTy::FNDEF: + { TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype); if (ltype->num_params () != type.num_params ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < ltype->num_params (); i++) @@ -933,24 +1094,20 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) auto a = ltype->param_at (i).get_type (); auto b = type.param_at (i).get_type (); - auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (a), - TyTy::TyWithLocation (b), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + auto unified_param = resolve_subtype (TyTy::TyWithLocation (a), + TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } - auto unified_return = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_return_type ()), - TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag, - false /* emit_errors */, infer_flag, commits, infers); + auto unified_return + = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()), + TyTy::TyWithLocation (type.get_return_type ())); if (unified_return->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } // ABI match? see @@ -961,12 +1118,12 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) { emit_abi_mismatch (*ltype, type); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } // DEF Id match? see https://github.com/Rust-GCC/gccrs/issues/2053 - return ltype->clone (); + return ltype; } break; @@ -992,10 +1149,11 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1003,20 +1161,22 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::FNPTR: { + case TyTy::FNPTR: + { TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype); if (ltype->num_params () != type.num_params ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < ltype->num_params (); i++) @@ -1024,48 +1184,53 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) auto a = ltype->get_param_type_at (i); auto b = type.get_param_type_at (i); - auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (a), - TyTy::TyWithLocation (b), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + auto unified_param = resolve_subtype (TyTy::TyWithLocation (a), + TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } - auto unified_return = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_return_type ()), - TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag, - false /* emit_errors */, infer_flag, commits, infers); + auto unified_return + = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()), + TyTy::TyWithLocation (type.get_return_type ())); if (unified_return->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return ltype->clone (); + if (ltype->get_abi () != type.get_abi ()) + { + return unify_error_type_node (); + } + + if (ltype->get_unsafety () != type.get_unsafety ()) + { + return unify_error_type_node (); + } + + return ltype; } break; - case TyTy::FNDEF: { + case TyTy::FNDEF: + { TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype); auto this_ret_type = ltype->get_return_type (); auto other_ret_type = type.get_return_type (); auto unified_result - = UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type), - TyTy::TyWithLocation (other_ret_type), locus, - commit_flag, false /*emit_errors*/, infer_flag, - commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_ret_type), + TyTy::TyWithLocation (other_ret_type)); if (unified_result->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (ltype->num_params () != type.num_params ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < ltype->num_params (); i++) @@ -1074,17 +1239,71 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) auto other_param = type.param_at (i).get_type (); auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (this_param), - TyTy::TyWithLocation (other_param), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_param), + TyTy::TyWithLocation (other_param)); + if (unified_param->get_kind () == TyTy::TypeKind::ERROR) + { + return unify_error_type_node (); + } + } + + // FIXME + // + // there is a bug in: + // testsuite/rust/compile/try-catch-unwind-{new,old}.rs I think the test + // + // case is wrong because it should be taking an FnOnce which probably + // didnt exist at the time in gccrs + // + // if (ltype->get_abi () != type.get_abi ()) + // { + // return unify_error_type_node (); + // } + + // FIXME fntype needs to track unsafe or not + // if (ltype->get_unsafety () != type.get_unsafety ()) + // { + // return unify_error_type_node (); + // } + + return ltype; + } + break; + + case TyTy::CLOSURE: + { + TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype); + auto this_ret_type = ltype->get_return_type (); + auto other_ret_type = type.get_return_type (); + + auto unified_result + = resolve_subtype (TyTy::TyWithLocation (this_ret_type), + TyTy::TyWithLocation (other_ret_type)); + if (unified_result->get_kind () == TyTy::TypeKind::ERROR) + { + return unify_error_type_node (); + } + + if (ltype->num_params () != type.get_num_params ()) + { + return unify_error_type_node (); + } + + for (size_t i = 0; i < ltype->num_params (); i++) + { + auto this_param = ltype->get_param_type_at (i); + auto other_param = type.get_param_type_at (i); + + auto unified_param + = resolve_subtype (TyTy::TyWithLocation (this_param), + TyTy::TyWithLocation (other_param)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } - return ltype->clone (); + return ltype; } break; @@ -1107,12 +1326,12 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) case TyTy::PLACEHOLDER: case TyTy::PROJECTION: case TyTy::DYNAMIC: - case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1120,20 +1339,22 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::TUPLE: { + case TyTy::TUPLE: + { TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype); if (ltype->num_fields () != type.num_fields ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } std::vector<TyTy::TyVar> fields; @@ -1143,18 +1364,15 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) TyTy::BaseType *fo = type.get_field (i); TyTy::BaseType *unified_ty - = UnifyRules::Resolve (TyTy::TyWithLocation (bo), - TyTy::TyWithLocation (fo), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (bo), + TyTy::TyWithLocation (fo)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + return unify_error_type_node (); - fields.push_back (TyTy::TyVar (unified_ty->get_ref ())); + fields.emplace_back (unified_ty->get_ref ()); } - return new TyTy::TupleType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, fields); + return ltype; } break; @@ -1180,10 +1398,11 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1191,20 +1410,22 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; case TyTy::BOOL: - return rtype->clone (); + return rtype; case TyTy::CHAR: case TyTy::INT: @@ -1228,10 +1449,11 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1239,20 +1461,22 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; case TyTy::CHAR: - return rtype->clone (); + return rtype; case TyTy::INT: case TyTy::FLOAT: @@ -1276,10 +1500,11 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1287,25 +1512,27 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; - case TyTy::INT: { + case TyTy::INT: + { TyTy::IntType &type = *static_cast<TyTy::IntType *> (rtype); bool is_valid = ltype->get_int_kind () == type.get_int_kind (); if (is_valid) - return new TyTy::IntType (type.get_ref (), type.get_ty_ref (), - type.get_int_kind ()); + return ltype; } break; @@ -1331,10 +1558,11 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1342,25 +1570,27 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; - case TyTy::UINT: { + case TyTy::UINT: + { TyTy::UintType &type = *static_cast<TyTy::UintType *> (rtype); bool is_valid = ltype->get_uint_kind () == type.get_uint_kind (); if (is_valid) - return new TyTy::UintType (type.get_ref (), type.get_ty_ref (), - type.get_uint_kind ()); + return ltype; } break; @@ -1386,10 +1616,11 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1397,25 +1628,27 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL || r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; - case TyTy::FLOAT: { + case TyTy::FLOAT: + { TyTy::FloatType &type = *static_cast<TyTy::FloatType *> (rtype); bool is_valid = ltype->get_float_kind () == type.get_float_kind (); if (is_valid) - return new TyTy::FloatType (type.get_ref (), type.get_ty_ref (), - type.get_float_kind ()); + return ltype; } break; @@ -1441,10 +1674,11 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1452,20 +1686,22 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; case TyTy::ISIZE: - return rtype->clone (); + return rtype; case TyTy::ADT: case TyTy::STR: @@ -1489,10 +1725,11 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1500,20 +1737,22 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; case TyTy::USIZE: - return rtype->clone (); + return rtype; case TyTy::ADT: case TyTy::STR: @@ -1537,10 +1776,11 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) case TyTy::DYNAMIC: case TyTy::CLOSURE: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1548,19 +1788,20 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; default: - return rtype->clone (); + return rtype; } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1569,17 +1810,18 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; case TyTy::PLACEHOLDER: - return ltype->clone (); + return ltype; case TyTy::PROJECTION: case TyTy::DYNAMIC: @@ -1604,13 +1846,14 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype, case TyTy::NEVER: case TyTy::OPAQUE: if (infer_flag) - return rtype->clone (); + return rtype; gcc_fallthrough (); + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1619,12 +1862,13 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1655,10 +1899,11 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype, case TyTy::NEVER: case TyTy::PLACEHOLDER: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1666,29 +1911,31 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::DYNAMIC: { + case TyTy::DYNAMIC: + { TyTy::DynamicObjectType &type = *static_cast<TyTy::DynamicObjectType *> (rtype); if (ltype->num_specified_bounds () != type.num_specified_bounds ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (!ltype->bounds_compatible (type, locus, true)) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return ltype->clone (); + return ltype; } break; @@ -1714,10 +1961,11 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) case TyTy::PLACEHOLDER: case TyTy::PROJECTION: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1725,41 +1973,41 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; - case TyTy::CLOSURE: { + case TyTy::CLOSURE: + { TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype); if (ltype->get_def_id () != type.get_def_id ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - TyTy::BaseType *args_res = UnifyRules::Resolve ( - TyTy::TyWithLocation (<ype->get_parameters ()), - TyTy::TyWithLocation (&type.get_parameters ()), locus, commit_flag, - false /* emit_error */, infer_flag, commits, infers); + TyTy::BaseType *args_res + = resolve_subtype (TyTy::TyWithLocation (<ype->get_parameters ()), + TyTy::TyWithLocation (&type.get_parameters ())); if (args_res->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - TyTy::BaseType *res = UnifyRules::Resolve ( - TyTy::TyWithLocation (<ype->get_result_type ()), - TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag, - false /* emit_error */, infer_flag, commits, infers); + TyTy::BaseType *res + = resolve_subtype (TyTy::TyWithLocation (<ype->get_result_type ()), + TyTy::TyWithLocation (&type.get_result_type ())); if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return ltype->clone (); + return ltype; } break; @@ -1785,68 +2033,162 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) case TyTy::PROJECTION: case TyTy::DYNAMIC: case TyTy::OPAQUE: + case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) { - switch (rtype->get_kind ()) + if (rtype->is<TyTy::OpaqueType> ()) { - case TyTy::INFER: { - TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); - bool is_valid - = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; - if (is_valid) - return ltype->clone (); - } - break; + TyTy::OpaqueType *ro = rtype->as<TyTy::OpaqueType> (); + if (!ltype->is_equal (*ro)) + return unify_error_type_node (); - case TyTy::OPAQUE: { - auto &type = *static_cast<TyTy::OpaqueType *> (rtype); - if (ltype->num_specified_bounds () != type.num_specified_bounds ()) - { - return new TyTy::ErrorType (0); - } + if (ltype->can_resolve () && ro->can_resolve ()) + { + auto lr = ltype->resolve (); + auto rr = ro->resolve (); - if (!ltype->bounds_compatible (type, locus, true)) - { - return new TyTy::ErrorType (0); - } + auto res = resolve_subtype (TyTy::TyWithLocation (lr), + TyTy::TyWithLocation (rr)); + if (res->get_kind () == TyTy::TypeKind::ERROR) + return unify_error_type_node (); + } + else if (ltype->can_resolve ()) + { + auto lr = ltype->resolve (); + ro->set_ty_ref (lr->get_ref ()); + } + else if (ro->can_resolve ()) + { + auto rr = ro->resolve (); + ltype->set_ty_ref (rr->get_ref ()); + } + } + else if (ltype->can_resolve ()) + { + auto underly = ltype->resolve (); + auto res = resolve_subtype (TyTy::TyWithLocation (underly), + TyTy::TyWithLocation (rtype)); + if (res->get_kind () == TyTy::TypeKind::ERROR) + return unify_error_type_node (); + } + else + { + ltype->set_ty_ref (rtype->get_ref ()); + } - return ltype->clone (); - } - break; + return ltype; +} - case TyTy::CLOSURE: - case TyTy::SLICE: - case TyTy::PARAM: - case TyTy::POINTER: - case TyTy::STR: - case TyTy::ADT: - case TyTy::REF: - case TyTy::ARRAY: - case TyTy::FNDEF: - case TyTy::FNPTR: - case TyTy::TUPLE: - case TyTy::BOOL: - case TyTy::CHAR: - case TyTy::INT: - case TyTy::UINT: - case TyTy::FLOAT: - case TyTy::USIZE: - case TyTy::ISIZE: - case TyTy::NEVER: - case TyTy::PLACEHOLDER: - case TyTy::PROJECTION: - case TyTy::DYNAMIC: - case TyTy::ERROR: - return new TyTy::ErrorType (0); +TyTy::BaseType * +UnifyRules::expect_const (TyTy::BaseConstType *ltype, TyTy::BaseType *rtype) +{ + if (rtype->get_kind () != TyTy::TypeKind::CONST) + return unify_error_type_node (); + + auto &lhs = *ltype; + auto &rhs = *rtype->as_const_type (); + + // Handle error types early + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Error + || rhs.const_kind () == TyTy::BaseConstType::ConstKind::Error) + { + auto lhs_base = ltype->as_base_type (); + return new TyTy::ConstErrorType (lhs.get_specified_type (), + lhs_base->get_ref (), + lhs_base->get_ty_ref (), + lhs_base->get_combined_refs ()); } - return new TyTy::ErrorType (0); + + // Try to resolve Decl types (ConstParamType) + TyTy::BaseConstType *resolved_lhs = &lhs; + TyTy::BaseConstType *resolved_rhs = &rhs; + + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) + { + auto *param = static_cast<TyTy::ConstParamType *> (&lhs); + if (param->can_resolve ()) + { + auto *resolved = param->resolve (); + if (resolved->get_kind () == TyTy::TypeKind::CONST) + resolved_lhs = resolved->as_const_type (); + } + } + + if (rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) + { + auto *param = static_cast<TyTy::ConstParamType *> (&rhs); + if (param->can_resolve ()) + { + auto *resolved = param->resolve (); + if (resolved->get_kind () == TyTy::TypeKind::CONST) + resolved_rhs = resolved->as_const_type (); + } + } + + auto res = resolve_subtype ( + TyTy::TyWithLocation (resolved_lhs->get_specified_type ()), + TyTy::TyWithLocation (resolved_rhs->get_specified_type ())); + if (res->get_kind () == TyTy::TypeKind::ERROR) + return unify_error_type_node (); + + if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Value + && resolved_rhs->const_kind () == TyTy::BaseConstType::ConstKind::Value) + { + auto vlhs = static_cast<TyTy::ConstValueType &> (*resolved_lhs); + auto vrhs = static_cast<TyTy::ConstValueType &> (*resolved_rhs); + tree lv = vlhs.get_value (); + tree rv = vrhs.get_value (); + + bool ok = operand_equal_p (lv, rv, 0); + if (!ok) + return unify_error_type_node (); + else + { + auto lhs_base = resolved_lhs->as_base_type (); + return new TyTy::ConstValueType (lv, res, lhs_base->get_ref (), + lhs_base->get_ty_ref (), + lhs_base->get_combined_refs ()); + } + } + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Value) + return resolved_rhs->as_base_type (); + else if (resolved_rhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_lhs->const_kind () + == TyTy::BaseConstType::ConstKind::Value) + return resolved_lhs->as_base_type (); + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Infer) + return resolved_lhs->as_base_type (); + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl + || resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Decl) + { + // If we still have unresolved Decl after trying to resolve, unify with it + // This allows const inference to work + if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl + && resolved_rhs->const_kind () + != TyTy::BaseConstType::ConstKind::Decl) + return resolved_rhs->as_base_type (); + else if (resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Decl + && resolved_lhs->const_kind () + != TyTy::BaseConstType::ConstKind::Decl) + return resolved_lhs->as_base_type (); + // Both are Decl - return lhs + return resolved_lhs->as_base_type (); + } + + return unify_error_type_node (); } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h index 5ff3b7c..2b772fe 100644 --- a/gcc/rust/typecheck/rust-unify.h +++ b/gcc/rust/typecheck/rust-unify.h @@ -30,13 +30,23 @@ class UnifyRules public: struct InferenceSite { + 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 { + CommitSite (TyTy::BaseType *lhs, TyTy::BaseType *rhs, + TyTy::BaseType *resolved) + : lhs (lhs), rhs (rhs), resolved (resolved) + {} + TyTy::BaseType *lhs; TyTy::BaseType *rhs; TyTy::BaseType *resolved; @@ -45,6 +55,7 @@ public: static TyTy::BaseType *Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus, bool commit_flag, bool emit_error, bool infer, + bool check_bounds, std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers); @@ -84,13 +95,18 @@ protected: TyTy::BaseType *rtype); TyTy::BaseType *expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_const (TyTy::BaseConstType *ltype, + TyTy::BaseType *rtype); private: UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus, bool commit_flag, bool emit_error, bool infer, - std::vector<CommitSite> &commits, + bool check_bounds, std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers); + TyTy::BaseType *resolve_subtype (TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs); + void emit_type_mismatch () const; void emit_abi_mismatch (const TyTy::FnType &expected, const TyTy::FnType &got) const; @@ -106,6 +122,7 @@ private: bool commit_flag; bool emit_error; bool infer_flag; + bool check_bounds_flag; std::vector<CommitSite> &commits; std::vector<InferenceSite> &infers; diff --git a/gcc/rust/util/bi-map.h b/gcc/rust/util/bi-map.h index 54870f7..4af157f 100644 --- a/gcc/rust/util/bi-map.h +++ b/gcc/rust/util/bi-map.h @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-system.h" +#include "optional.h" #ifndef BIMAP_H #define BIMAP_H diff --git a/gcc/rust/util/expected.h b/gcc/rust/util/expected.h index a9e3bc2..07ba877 100644 --- a/gcc/rust/util/expected.h +++ b/gcc/rust/util/expected.h @@ -212,10 +212,8 @@ template <typename E> throw std::forward<E>(e); #else (void)e; -#ifdef _MSC_VER gcc_unreachable(); #endif -#endif } #ifndef TL_TRAITS_MUTEX @@ -2437,4 +2435,4 @@ void swap(expected<T, E> &lhs, } } // namespace tl -#endif
\ No newline at end of file +#endif diff --git a/gcc/rust/util/fnv-hash.h b/gcc/rust/util/fnv-hash.h index 6d2ec01..e51b66a 100644 --- a/gcc/rust/util/fnv-hash.h +++ b/gcc/rust/util/fnv-hash.h @@ -15,6 +15,7 @@ // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" #ifndef RUST_FNV_HASH_H #define RUST_FNV_HASH_H diff --git a/gcc/rust/util/optional.h b/gcc/rust/util/optional.h index 2c59459..9d2cd97 100644 --- a/gcc/rust/util/optional.h +++ b/gcc/rust/util/optional.h @@ -1364,7 +1364,7 @@ public: this->m_has_value = false; } } -}; // namespace tl +}; /// Compares two optional objects template <class T, class U> @@ -2110,7 +2110,7 @@ public: private: T *m_value; -}; // namespace tl +}; @@ -2128,4 +2128,4 @@ template <class T> struct hash<tl::optional<T>> { }; } // namespace std -#endif
\ No newline at end of file +#endif diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h index a0180ed..357a5db 100644 --- a/gcc/rust/util/rust-abi.h +++ b/gcc/rust/util/rust-abi.h @@ -34,11 +34,9 @@ enum ABI SYSV64 }; -extern Rust::ABI -get_abi_from_string (const std::string &abi); +extern Rust::ABI get_abi_from_string (const std::string &abi); -extern std::string -get_string_from_abi (Rust::ABI abi); +extern std::string get_string_from_abi (Rust::ABI abi); } // namespace Rust diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h index 9ef5cc5..0f35f56 100644 --- a/gcc/rust/util/rust-attribute-values.h +++ b/gcc/rust/util/rust-attribute-values.h @@ -36,16 +36,19 @@ public: static constexpr auto &DOC = "doc"; static constexpr auto &MUST_USE = "must_use"; static constexpr auto &LANG = "lang"; + static constexpr auto &LINK_NAME = "link_name"; static constexpr auto &LINK_SECTION = "link_section"; static constexpr auto &NO_MANGLE = "no_mangle"; static constexpr auto &REPR = "repr"; static constexpr auto &RUSTC_BUILTIN_MACRO = "rustc_builtin_macro"; + static constexpr auto &RUSTC_MACRO_TRANSPARENCY = "rustc_macro_transparency"; static constexpr auto &PATH = "path"; static constexpr auto &MACRO_USE = "macro_use"; static constexpr auto &MACRO_EXPORT = "macro_export"; static constexpr auto &PROC_MACRO = "proc_macro"; static constexpr auto &PROC_MACRO_DERIVE = "proc_macro_derive"; static constexpr auto &PROC_MACRO_ATTRIBUTE = "proc_macro_attribute"; + static constexpr auto &TARGET_FEATURE = "target_feature"; // From now on, these are reserved by the compiler and gated through // #![feature(rustc_attrs)] @@ -54,10 +57,42 @@ public: = "rustc_inherit_overflow_checks"; static constexpr auto &STABLE = "stable"; static constexpr auto &UNSTABLE = "unstable"; + + static constexpr auto &RUSTC_PROMOTABLE = "rustc_promotable"; static constexpr auto &RUSTC_CONST_STABLE = "rustc_const_stable"; static constexpr auto &RUSTC_CONST_UNSTABLE = "rustc_const_unstable"; + static constexpr auto &RUSTC_ALLOW_CONST_FN_UNSTABLE + = "rustc_allow_const_fn_unstable"; + + static constexpr auto &RUSTC_SPECIALIZATION_TRAIT + = "rustc_specialization_trait"; + static constexpr auto &RUSTC_UNSAFE_SPECIALIZATION_MARKER + = "rustc_unsafe_specialization_marker"; + static constexpr auto &RUSTC_RESERVATION_IMPL = "rustc_reservation_impl"; + static constexpr auto &RUSTC_PAREN_SUGAR = "rustc_paren_sugar"; + static constexpr auto &RUSTC_NONNULL_OPTIMIZATION_GUARANTEED + = "rustc_nonnull_optimization_guaranteed"; + + static constexpr auto &RUSTC_LAYOUT_SCALAR_VALID_RANGE_START + = "rustc_layout_scalar_valid_range_start"; + static constexpr auto &MAY_DANGLE = "may_dangle"; static constexpr auto &PRELUDE_IMPORT = "prelude_import"; + static constexpr auto &TRACK_CALLER = "track_caller"; + + static constexpr auto &RUSTC_DIAGNOSTIC_ITEM = "rustc_diagnostic_item"; + static constexpr auto &RUSTC_ON_UNIMPLEMENTED = "rustc_on_unimplemented"; + + static constexpr auto &FUNDAMENTAL = "fundamental"; + + static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive"; + + static constexpr auto &RUSTFMT = "rustfmt"; + + static constexpr auto &TEST = "test"; + + static constexpr auto &RUSTC_ARGS_REQUIRED_CONST + = "rustc_args_required_const"; }; } // namespace Values } // namespace Rust diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index 03452c7..70f26e7 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -38,6 +38,31 @@ Attributes::is_known (const std::string &attribute_path) return !lookup.is_error (); } +tl::optional<std::string> +Attributes::extract_string_literal (const AST::Attribute &attr) +{ + if (!attr.has_attr_input ()) + return tl::nullopt; + + auto &attr_input = attr.get_attr_input (); + + if (attr_input.get_attr_input_type () + != AST::AttrInput::AttrInputType::LITERAL) + return tl::nullopt; + + auto &literal_expr + = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal (); + + auto lit_type = literal_expr.get_lit_type (); + + // TODO: bring escape sequence handling out of lexing? + if (lit_type != AST::Literal::LitType::STRING + && lit_type != AST::Literal::LitType::RAW_STRING) + return tl::nullopt; + + return literal_expr.as_string (); +} + using Attrs = Values::Attributes; // https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248 @@ -53,10 +78,12 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::DOC, HIR_LOWERING}, {Attrs::MUST_USE, STATIC_ANALYSIS}, {Attrs::LANG, HIR_LOWERING}, + {Attrs::LINK_NAME, CODE_GENERATION}, {Attrs::LINK_SECTION, CODE_GENERATION}, {Attrs::NO_MANGLE, CODE_GENERATION}, {Attrs::REPR, CODE_GENERATION}, {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION}, + {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION}, {Attrs::PATH, EXPANSION}, {Attrs::MACRO_USE, NAME_RESOLUTION}, {Attrs::MACRO_EXPORT, NAME_RESOLUTION}, @@ -73,9 +100,32 @@ static const BuiltinAttrDefinition __definitions[] {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}, {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS}, - {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}}; + {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS}, + {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}, + {Attrs::TRACK_CALLER, CODE_GENERATION}, + {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK}, + {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK}, + {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 () @@ -118,6 +168,7 @@ AttributeChecker::go (AST::Crate &crate) void AttributeChecker::visit (AST::Crate &crate) { + check_inner_attributes (crate.get_inner_attrs ()); check_attributes (crate.get_inner_attrs ()); for (auto &item : crate.items) @@ -188,8 +239,8 @@ check_doc_attribute (const AST::Attribute &attribute) { rust_error_at ( attribute.get_locus (), - // FIXME: Improve error message here. Rustc has a very good one - "%<#[doc]%> cannot be an empty attribute"); + "valid forms for the attribute are " + "%<#[doc(hidden|inline|...)]%> and %<#[doc = \" string \"]%>"); return; } @@ -201,7 +252,8 @@ check_doc_attribute (const AST::Attribute &attribute) break; // FIXME: Handle them as well - case AST::AttrInput::TOKEN_TREE: { + case AST::AttrInput::TOKEN_TREE: + { // FIXME: This doesn't check for #[doc(alias(...))] const auto &option = static_cast<const AST::DelimTokenTree &> ( attribute.get_attr_input ()); @@ -271,8 +323,42 @@ 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 ()) + { + const auto &attr_input = attribute.get_attr_input (); + auto type = attr_input.get_attr_input_type (); + if (type == AST::AttrInput::AttrInputType::TOKEN_TREE) + { + const auto &option = static_cast<const AST::DelimTokenTree &> ( + attribute.get_attr_input ()); + std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item ( + option.parse_to_meta_item ()); + AST::DefaultASTVisitor::visit (meta_item); + } + } + BuiltinAttrDefinition result; // This checker does not check non-builtin attributes @@ -302,10 +388,6 @@ AttributeChecker::visit (AST::DelimTokenTree &) {} void -AttributeChecker::visit (AST::AttrInputMetaItemContainer &) -{} - -void AttributeChecker::visit (AST::IdentifierExpr &) {} @@ -368,8 +450,16 @@ AttributeChecker::visit (AST::MetaItemLitExpr &) {} void -AttributeChecker::visit (AST::MetaItemPathLit &) -{} +AttributeChecker::visit (AST::MetaItemPathExpr &attribute) +{ + if (!attribute.get_expr ().is_literal ()) + { + rust_error_at (attribute.get_expr ().get_locus (), + "malformed %<path%> attribute input"); + rust_inform (attribute.get_expr ().get_locus (), + "must be of the form: %<#[path = \"file\"]%>"); + } +} void AttributeChecker::visit (AST::BorrowExpr &) @@ -595,6 +685,7 @@ AttributeChecker::visit (AST::TypeBoundWhereClauseItem &) void AttributeChecker::visit (AST::Module &module) { + check_attributes (module.get_outer_attrs ()); check_proc_macro_non_function (module.get_outer_attrs ()); for (auto &item : module.get_items ()) { @@ -747,10 +838,6 @@ AttributeChecker::visit (AST::StaticItem &item) } void -AttributeChecker::visit (AST::TraitItemConst &) -{} - -void AttributeChecker::visit (AST::TraitItemType &) {} @@ -758,6 +845,7 @@ void AttributeChecker::visit (AST::Trait &trait) { check_proc_macro_non_function (trait.get_outer_attrs ()); + check_attributes (trait.get_outer_attrs ()); } void @@ -814,10 +902,6 @@ AttributeChecker::visit (AST::MetaItemPath &) {} void -AttributeChecker::visit (AST::MetaItemSeq &) -{} - -void AttributeChecker::visit (AST::MetaWord &) {} @@ -893,11 +977,11 @@ AttributeChecker::visit (AST::StructPattern &) // void AttributeChecker::visit(TupleStructItems& ){} void -AttributeChecker::visit (AST::TupleStructItemsNoRange &) +AttributeChecker::visit (AST::TupleStructItemsNoRest &) {} void -AttributeChecker::visit (AST::TupleStructItemsRange &) +AttributeChecker::visit (AST::TupleStructItemsHasRest &) {} void @@ -907,11 +991,11 @@ AttributeChecker::visit (AST::TupleStructPattern &) // void AttributeChecker::visit(TuplePatternItems& ){} void -AttributeChecker::visit (AST::TuplePatternItemsMultiple &) +AttributeChecker::visit (AST::TuplePatternItemsNoRest &) {} void -AttributeChecker::visit (AST::TuplePatternItemsRanged &) +AttributeChecker::visit (AST::TuplePatternItemsHasRest &) {} void diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h index c928c8e..f4a2d38 100644 --- a/gcc/rust/util/rust-attributes.h +++ b/gcc/rust/util/rust-attributes.h @@ -29,6 +29,8 @@ class Attributes { public: static bool is_known (const std::string &attribute_path); + static tl::optional<std::string> + extract_string_literal (const AST::Attribute &attr); }; enum CompilerPass @@ -40,7 +42,12 @@ enum CompilerPass HIR_LOWERING, TYPE_CHECK, STATIC_ANALYSIS, - CODE_GENERATION + CODE_GENERATION, + + // External Rust tooling attributes, like #[rustfmt::skip] + EXTERNAL, + + // Do we need to add something here for const fns? }; struct BuiltinAttrDefinition @@ -95,9 +102,13 @@ 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_attributes (const AST::AttrVec &attributes); @@ -105,7 +116,6 @@ private: void visit (AST::Crate &crate) override; void visit (AST::Token &tok) override; void visit (AST::DelimTokenTree &delim_tok_tree) override; - void visit (AST::AttrInputMetaItemContainer &input) override; void visit (AST::IdentifierExpr &ident_expr) override; void visit (AST::Lifetime &lifetime) override; void visit (AST::LifetimeParam &lifetime_param) override; @@ -125,7 +135,7 @@ private: void visit (AST::AttrInputLiteral &attr_input) override; void visit (AST::AttrInputMacro &attr_input) override; void visit (AST::MetaItemLitExpr &meta_item) override; - void visit (AST::MetaItemPathLit &meta_item) override; + void visit (AST::MetaItemPathExpr &meta_item) override; void visit (AST::BorrowExpr &expr) override; void visit (AST::DereferenceExpr &expr) override; void visit (AST::ErrorPropagationExpr &expr) override; @@ -198,7 +208,6 @@ private: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemConst &item) override; void visit (AST::TraitItemType &item) override; void visit (AST::Trait &trait) override; void visit (AST::InherentImpl &impl) override; @@ -214,7 +223,6 @@ private: void visit (AST::MacroRulesDefinition &rules_def) override; void visit (AST::MacroInvocation ¯o_invoc) override; void visit (AST::MetaItemPath &meta_item) override; - void visit (AST::MetaItemSeq &meta_item) override; void visit (AST::MetaWord &meta_item) override; void visit (AST::MetaNameValueStr &meta_item) override; void visit (AST::MetaListPaths &meta_item) override; @@ -237,12 +245,12 @@ private: void visit (AST::StructPatternFieldIdent &field) override; void visit (AST::StructPattern &pattern) override; // void visit(TupleStructItems& tuple_items) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; + void visit (AST::TupleStructItemsNoRest &tuple_items) override; + void visit (AST::TupleStructItemsHasRest &tuple_items) override; void visit (AST::TupleStructPattern &pattern) override; // void visit(TuplePatternItems& tuple_items) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; + void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + void visit (AST::TuplePatternItemsHasRest &tuple_items) override; void visit (AST::TuplePattern &pattern) override; void visit (AST::GroupedPattern &pattern) override; void visit (AST::SlicePattern &pattern) override; diff --git a/gcc/rust/util/rust-base62.h b/gcc/rust/util/rust-base62.h index e751c95..5fd7a37 100644 --- a/gcc/rust/util/rust-base62.h +++ b/gcc/rust/util/rust-base62.h @@ -26,8 +26,7 @@ namespace Rust { /** * Get the Base62 representation of an integer */ -std::string -base62_integer (uint64_t value); +std::string base62_integer (uint64_t value); } // namespace Rust diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h index 4d8f954..4c4d9df 100644 --- a/gcc/rust/util/rust-canonical-path.h +++ b/gcc/rust/util/rust-canonical-path.h @@ -57,10 +57,11 @@ public: return *this; } - static CanonicalPath new_seg (NodeId id, const std::string &path) + static CanonicalPath new_seg (NodeId id, std::string path) { rust_assert (!path.empty ()); - return CanonicalPath ({std::pair<NodeId, std::string> (id, path)}, + return CanonicalPath ({std::pair<NodeId, std::string> (id, + std::move (path))}, UNKNOWN_CRATENUM); } @@ -68,14 +69,18 @@ public: trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg, const CanonicalPath &impl_type_seg) { - return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as " + // https://doc.rust-lang.org/reference/paths.html#canonical-paths + // should be "<X>"? + return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + " as " + trait_seg.get () + ">"); } static CanonicalPath inherent_impl_seg (NodeId id, const CanonicalPath &impl_type_seg) { - return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + ">"); + // https://doc.rust-lang.org/reference/paths.html#canonical-paths + // should be "<X as Y>"? + return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">"); } std::string get () const @@ -109,6 +114,8 @@ public: return CanonicalPath (other.segs, crate_num); std::vector<std::pair<NodeId, std::string>> copy (segs); + copy.reserve (other.segs.size ()); + for (auto &s : other.segs) copy.push_back (s); diff --git a/gcc/rust/util/rust-dir-owner.h b/gcc/rust/util/rust-dir-owner.h index dcb45d8..fb72bb1 100644 --- a/gcc/rust/util/rust-dir-owner.h +++ b/gcc/rust/util/rust-dir-owner.h @@ -26,8 +26,7 @@ namespace Rust { // extracts the owned subdirectory name from a file name -bool -get_file_subdir (const std::string &filename, std::string &subdir); +bool get_file_subdir (const std::string &filename, std::string &subdir); } // namespace Rust diff --git a/gcc/rust/util/rust-dump.h b/gcc/rust/util/rust-dump.h index c2d9c4d..111174b 100644 --- a/gcc/rust/util/rust-dump.h +++ b/gcc/rust/util/rust-dump.h @@ -16,6 +16,8 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" + // Common definitions useful for textual dump of IRs (AST and HIR). #ifndef RUST_DUMP_H diff --git a/gcc/rust/util/rust-edition.h b/gcc/rust/util/rust-edition.h index d034ea0..532fedb 100644 --- a/gcc/rust/util/rust-edition.h +++ b/gcc/rust/util/rust-edition.h @@ -33,8 +33,7 @@ enum class Edition E2021 }; -Edition -get_rust_edition (); +Edition get_rust_edition (); } // namespace Rust diff --git a/gcc/rust/util/rust-ggc.cc b/gcc/rust/util/rust-ggc.cc new file mode 100644 index 0000000..46220a2 --- /dev/null +++ b/gcc/rust/util/rust-ggc.cc @@ -0,0 +1,44 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-ggc.h" +#include "rust-ast.h" +#include "stringpool.h" + +namespace Rust { + +namespace GGC { + +Ident::Ident (const char *str) : inner (get_identifier (str)) {} + +Ident::Ident (const std::string &str) + : inner (get_identifier_with_length (str.c_str (), str.length ())) +{} + +Ident::Ident (const Rust::Identifier &ident) : Ident (ident.as_string ()) {} + +bool +Ident::operator== (const std::string &other) const +{ + // maybe_get_identifier_with_length doesn't seem to exist + return maybe_get_identifier (other.c_str ()) == inner; +} + +} // namespace GGC + +} // namespace Rust diff --git a/gcc/rust/util/rust-ggc.h b/gcc/rust/util/rust-ggc.h new file mode 100644 index 0000000..da4ede1 --- /dev/null +++ b/gcc/rust/util/rust-ggc.h @@ -0,0 +1,67 @@ +// 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/>. + +#ifndef RUST_GGC_H +#define RUST_GGC_H + +#include "rust-system.h" +#include "tree.h" + +namespace Rust { + +// forward declare +class Identifier; + +namespace GGC { + +class Ident +{ + tree inner; + +public: + Ident (const char *str); + Ident (const std::string &str); + Ident (const Rust::Identifier &ident); + + bool operator== (const Ident &other) const { return inner == other.inner; } + bool operator== (const std::string &other) const; + + const char *c_str () const { return IDENTIFIER_POINTER (inner); } + size_t size () const { return IDENTIFIER_LENGTH (inner); } + + bool empty () const { return !size (); } + + std::string as_string () const + { + return std::string (c_str (), c_str () + size ()); + } + + tree as_tree () const { return inner; } +}; + +static inline bool +operator== (const std::string &a, const Ident &b) +{ + return b == a; +} + +} // namespace GGC + +} // namespace Rust + +#endif // RUST_GGC_H diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index eaa640c..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; @@ -1148,17 +1148,19 @@ Mappings::lookup_module_children (NodeId module) } void -Mappings::insert_ast_module (AST::Module *module) +Mappings::insert_glob_container (AST::Item *container) { - rust_assert (modules.find (module->get_node_id ()) == modules.end ()); - modules[module->get_node_id ()] = module; + rust_assert (glob_containers.find (container->get_node_id ()) + == glob_containers.end ()); + + glob_containers[container->get_node_id ()] = container; } -tl::optional<AST::Module *> -Mappings::lookup_ast_module (NodeId id) +tl::optional<AST::Item *> +Mappings::lookup_glob_container (NodeId id) { - auto it = modules.find (id); - if (it == modules.end ()) + auto it = glob_containers.find (id); + if (it == glob_containers.end ()) return tl::nullopt; return {it->second}; @@ -1356,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 b523a36..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); @@ -321,8 +321,8 @@ public: void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility); tl::optional<Privacy::ModuleVisibility &> lookup_visibility (NodeId id); - void insert_ast_module (AST::Module *); - tl::optional<AST::Module *> lookup_ast_module (NodeId id); + void insert_glob_container (AST::Item *); + tl::optional<AST::Item *> lookup_glob_container (NodeId id); void insert_module_child (NodeId module, NodeId child); tl::optional<std::vector<NodeId> &> lookup_module_children (NodeId module); @@ -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>> @@ -436,13 +439,15 @@ private: std::map<NodeId, std::vector<NodeId>> module_child_map; std::map<NodeId, std::vector<Resolver::CanonicalPath>> module_child_items; std::map<NodeId, NodeId> child_to_parent_module_map; - std::map<NodeId, AST::Module *> modules; + std::map<NodeId, AST::Item *> glob_containers; // AST mappings std::map<NodeId, AST::Item *> ast_item_mappings; // Closure AST NodeId -> vector of Definition node ids std::unordered_map<NodeId, std::vector<NodeId>> captures; + + std::set<NodeId> derived_nodes; }; } // namespace Analysis diff --git a/gcc/rust/util/rust-inline-visitor.h b/gcc/rust/util/rust-inline-visitor.h index 2a35aa6..a00cd2c 100644 --- a/gcc/rust/util/rust-inline-visitor.h +++ b/gcc/rust/util/rust-inline-visitor.h @@ -15,6 +15,7 @@ // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" // An improved implementation of the inline visitor. // Original idea from https://members.accu.org/index.php/articles/2021 diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc index a76cc7f..9aff31b 100644 --- a/gcc/rust/util/rust-lang-item.cc +++ b/gcc/rust/util/rust-lang-item.cc @@ -118,6 +118,7 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{ {"discriminant_kind", Kind::DISCRIMINANT_KIND}, {"discriminant_type", Kind::DISCRIMINANT_TYPE}, + {"manually_drop", Kind::MANUALLY_DROP}, }}; tl::optional<LangItem::Kind> diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h index 8f3af36..7b9f498 100644 --- a/gcc/rust/util/rust-lang-item.h +++ b/gcc/rust/util/rust-lang-item.h @@ -21,6 +21,9 @@ #include "optional.h" #include "bi-map.h" +#ifndef RUST_LANG_ITEM_H +#define RUST_LANG_ITEM_H + namespace Rust { class LangItem @@ -150,6 +153,8 @@ public: DISCRIMINANT_TYPE, DISCRIMINANT_KIND, + + MANUALLY_DROP, }; static const BiMap<std::string, Kind> lang_items; @@ -183,3 +188,5 @@ template <> struct hash<Rust::LangItem::Kind> } }; } // namespace std + +#endif // RUST_LANG_ITEM_H diff --git a/gcc/rust/util/rust-punycode.h b/gcc/rust/util/rust-punycode.h index a939f05..75260ce 100644 --- a/gcc/rust/util/rust-punycode.h +++ b/gcc/rust/util/rust-punycode.h @@ -27,8 +27,7 @@ namespace Rust { /* Encode a string as punycode. Returns a string if encoding is successful. * Returns nullopt otherwise. Note that a returned string contains only ASCII * characters and does not start with `xn--`. */ -tl::optional<std::string> -encode_punycode (const Utf8String &src); +tl::optional<std::string> encode_punycode (const Utf8String &src); } // namespace Rust @@ -36,8 +35,7 @@ encode_punycode (const Utf8String &src); namespace selftest { -void -rust_punycode_encode_test (); +void rust_punycode_encode_test (); } // namespace selftest diff --git a/gcc/rust/util/rust-stacked-contexts.h b/gcc/rust/util/rust-stacked-contexts.h index fe0bc8a..b263d75 100644 --- a/gcc/rust/util/rust-stacked-contexts.h +++ b/gcc/rust/util/rust-stacked-contexts.h @@ -71,7 +71,14 @@ public: return last; } - const T &peek () + const T &peek () const + { + rust_assert (!stack.empty ()); + + return stack.back (); + } + + T &peek () { rust_assert (!stack.empty ()); diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc index fc34adb..0865bf9 100644 --- a/gcc/rust/util/rust-token-converter.cc +++ b/gcc/rust/util/rust-token-converter.cc @@ -102,7 +102,9 @@ ProcMacro::TokenStream convert (const std::vector<const_TokenPtr> &tokens) { std::vector<ProcMacro::TokenStream> trees; - trees.push_back (ProcMacro::TokenStream::make_tokenstream ()); + trees.reserve (tokens.size ()); + + trees.emplace_back (ProcMacro::TokenStream::make_tokenstream ()); for (auto &token : tokens) { auto loc = convert (token->get_locus ()); @@ -202,7 +204,8 @@ convert (const std::vector<const_TokenPtr> &tokens) case PERCENT_EQ: case SCOPE_RESOLUTION: case NOT_EQUAL: - case EQUAL_EQUAL: { + case EQUAL_EQUAL: + { auto str = token->as_string (); auto it = str.cbegin (); for (; it != str.cend () - 1; it++) @@ -260,9 +263,8 @@ convert (const std::vector<const_TokenPtr> &tokens) return trees.back (); } -static void -from_tokenstream (const ProcMacro::TokenStream &ts, - std::vector<const_TokenPtr> &result); +static void from_tokenstream (const ProcMacro::TokenStream &ts, + std::vector<const_TokenPtr> &result); /** * Append the token corresponding to a given Ident to a vector. diff --git a/gcc/rust/util/rust-token-converter.h b/gcc/rust/util/rust-token-converter.h index 5405d6e..6e4af50 100644 --- a/gcc/rust/util/rust-token-converter.h +++ b/gcc/rust/util/rust-token-converter.h @@ -23,14 +23,11 @@ namespace Rust { -ProcMacro::TokenStream -convert (const std::vector<const_TokenPtr> &tokens); +ProcMacro::TokenStream convert (const std::vector<const_TokenPtr> &tokens); -std::vector<const_TokenPtr> -convert (const ProcMacro::TokenStream &ts); +std::vector<const_TokenPtr> convert (const ProcMacro::TokenStream &ts); -ProcMacro::Literal -convert_literal (const_TokenPtr lit); +ProcMacro::Literal convert_literal (const_TokenPtr lit); } // namespace Rust diff --git a/gcc/rust/util/rust-unicode.h b/gcc/rust/util/rust-unicode.h index 6a6526d..6579b80 100644 --- a/gcc/rust/util/rust-unicode.h +++ b/gcc/rust/util/rust-unicode.h @@ -59,20 +59,15 @@ public: Utf8String nfc_normalize () const; }; -bool -is_alphabetic (uint32_t codepoint); +bool is_alphabetic (uint32_t codepoint); -bool -is_ascii_only (const std::string &str); +bool is_ascii_only (const std::string &str); -bool -is_numeric (uint32_t codepoint); +bool is_numeric (uint32_t codepoint); -bool -is_nfc_qc_no (uint32_t codepoint); +bool is_nfc_qc_no (uint32_t codepoint); -bool -is_nfc_qc_maybe (uint32_t codepoint); +bool is_nfc_qc_maybe (uint32_t codepoint); enum class QuickCheckResult { @@ -81,8 +76,7 @@ enum class QuickCheckResult MAYBE }; -QuickCheckResult -nfc_quick_check (const std::vector<Codepoint> &s); +QuickCheckResult nfc_quick_check (const std::vector<Codepoint> &s); } // namespace Rust @@ -90,14 +84,11 @@ nfc_quick_check (const std::vector<Codepoint> &s); namespace selftest { -void -rust_nfc_qc_test (); +void rust_nfc_qc_test (); -void -rust_utf8_normalize_test (); +void rust_utf8_normalize_test (); -void -rust_utf8_property_test (); +void rust_utf8_property_test (); } // namespace selftest diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h index bebdc3a..ccc1e61 100644 --- a/gcc/rust/util/rust-unwrap-segment.h +++ b/gcc/rust/util/rust-unwrap-segment.h @@ -16,6 +16,10 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" +#include "optional.h" +#include "rust-lang-item.h" +#include "rust-mapping-common.h" #include <ast/rust-ast-full-decls.h> namespace Rust { @@ -83,14 +87,11 @@ public: /* * Used to get the node id of a path segment object */ -NodeId -unwrap_segment_node_id (const AST::TypePathSegment &seg); +NodeId unwrap_segment_node_id (const AST::TypePathSegment &seg); -NodeId -unwrap_segment_node_id (const AST::SimplePathSegment &seg); +NodeId unwrap_segment_node_id (const AST::SimplePathSegment &seg); -NodeId -unwrap_segment_node_id (const AST::PathExprSegment &seg); +NodeId unwrap_segment_node_id (const AST::PathExprSegment &seg); template <class T> NodeId @@ -118,4 +119,20 @@ unwrap_segment_get_lang_item (const std::unique_ptr<T> &ptr) return unwrap_segment_get_lang_item (*ptr); } +/** + * Used to output a path in error messages + */ + +inline static std::string +unwrap_segment_error_string (const AST::TypePath &path) +{ + return path.make_debug_string (); +} + +inline static std::string +unwrap_segment_error_string (const AST::PathInExpression &path) +{ + return path.as_simple_path ().as_string (); +} + } // namespace Rust |
