diff options
Diffstat (limited to 'gcc/rust')
194 files changed, 9486 insertions, 13344 deletions
diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog index f960ef2..556ce28 100644 --- a/gcc/rust/ChangeLog +++ b/gcc/rust/ChangeLog @@ -1,3 +1,1446 @@ +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): @@ -5197,7 +6640,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 8cdf6c9..e5a8a5e 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -84,6 +84,7 @@ 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 \ @@ -147,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 \ @@ -209,7 +201,6 @@ GRS_OBJS = \ rust/rust-lint-marklive.o \ rust/rust-lint-unused-var.o \ rust/rust-readonly-check.o \ - rust/rust-readonly-check2.o \ rust/rust-hir-type-check-path.o \ rust/rust-unsafe-checker.o \ rust/rust-hir-pattern-analysis.o \ @@ -443,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 @@ -515,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.cc b/gcc/rust/ast/rust-ast-builder.cc index ed10ce7..632f945 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -554,12 +554,12 @@ 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 ()); @@ -605,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), @@ -626,12 +626,11 @@ Builder::new_type_param ( { 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; @@ -642,11 +641,10 @@ Builder::new_type_param ( 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; @@ -664,12 +662,9 @@ 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; @@ -677,10 +672,9 @@ Builder::new_type_param ( { 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; } @@ -709,18 +703,14 @@ 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 = t.reconstruct (); - GenericArgsBinding b (binding.get_identifier (), std::move (ty), - binding.get_locus ()); - binding_args.push_back (std::move (b)); + binding_args.emplace_back (binding.get_identifier (), std::move (ty), + binding.get_locus ()); } for (auto &arg : args.get_generic_args ()) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 3d9ea78..721d274 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -76,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 @@ -101,7 +101,7 @@ TokenCollector::decrement_indentation () void TokenCollector::comment (std::string comment) { - tokens.push_back ({comment}); + tokens.emplace_back (comment); } void @@ -355,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: @@ -2171,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 ()); @@ -2632,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 ()); @@ -2649,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 ()) { @@ -2682,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 ()) { @@ -3009,8 +2997,216 @@ 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 diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index d3ab18a..3e33476 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -330,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); @@ -370,12 +369,12 @@ 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); diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h index aace93f..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 { 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 09706ce..2903ba7 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -195,7 +195,6 @@ class Enum; class Union; class ConstantItem; class StaticItem; -class TraitItemConst; class TraitItemType; class Trait; class Impl; @@ -240,12 +239,12 @@ 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; 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 ab8cdbe..afdd2b1 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -248,6 +248,7 @@ void DefaultASTVisitor::visit (AST::ErrorPropagationExpr &expr) { visit_outer_attrs (expr); + visit (expr.get_propagating_expr ()); } void @@ -1025,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); @@ -1296,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); @@ -1319,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); diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 2d81aa1..a7a2ac4 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -164,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; @@ -204,12 +203,12 @@ 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; @@ -349,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; @@ -381,11 +379,11 @@ 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; diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 8e856fb..337a338 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -48,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; } } @@ -80,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; } @@ -112,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; } } @@ -143,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 (); @@ -166,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 (); @@ -232,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; } /** @@ -389,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 (); @@ -636,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"; } @@ -3034,20 +3044,6 @@ 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); @@ -3367,7 +3363,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 @@ -4132,6 +4134,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 ()) { @@ -4149,11 +4157,12 @@ 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)) + || (string_path != Values::Attributes::CFG + && string_path != Values::Attributes::CFG_ATTR)) { // DEBUG message rust_debug ( @@ -4169,6 +4178,13 @@ Attribute::check_cfg_predicate (const Session &session) const return false; auto &meta_item = static_cast<AttrInputMetaItemContainer &> (*attr_input); + if (meta_item.get_items ().empty () + && string_path == Values::Attributes::CFG_ATTR) + { + rust_error_at (path.get_locus (), + "malformed %<cfg_attr%> attribute input"); + return false; + } return meta_item.get_items ().front ()->check_cfg_predicate (session); } @@ -4740,12 +4756,6 @@ StaticItem::accept_vis (ASTVisitor &vis) } void -TraitItemConst::accept_vis (ASTVisitor &vis) -{ - vis.visit (*this); -} - -void TraitItemType::accept_vis (ASTVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 2d2c5d0..8a7e618 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -184,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; @@ -209,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 @@ -283,7 +226,7 @@ public: std::vector<std::unique_ptr<Token>> to_token_stream () const override; TokenId get_id () const { return tok_ref->get_id (); } - bool has_str () const { return tok_ref->has_str (); } + 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 (); } @@ -1137,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; @@ -1536,7 +1481,8 @@ 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: @@ -1799,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 @@ -1829,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; } }; @@ -1957,18 +1905,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; @@ -1977,30 +1926,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); @@ -2010,23 +1964,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; } @@ -2071,6 +2025,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 (); diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h index 2893e7b..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; } @@ -255,6 +262,7 @@ public: 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; } diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index 306c6f7..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); } } diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h index 56a5646..5d5fba5 100644 --- a/gcc/rust/ast/rust-cond-compilation.h +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -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 index bca14ee..de34e15 100644 --- a/gcc/rust/ast/rust-desugar-apit.cc +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -188,9 +188,10 @@ public: // Convert to TypePath by creating path segments std::vector<std::unique_ptr<TypePathSegment>> segments; - segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( - PathIdentSegment (ident.as_string (), type.get_locus ()), false, - type.get_locus ()))); + segments.emplace_back ( + new TypePathSegment (PathIdentSegment (ident.as_string (), + type.get_locus ()), + false, type.get_locus ())); // Create TypePath from segments auto type_path @@ -198,6 +199,8 @@ public: // 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 ()); @@ -228,9 +231,10 @@ public: // Convert to TypePath by creating path segments std::vector<std::unique_ptr<TypePathSegment>> segments; - segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( - PathIdentSegment (ident.as_string (), type.get_locus ()), false, - type.get_locus ()))); + segments.emplace_back ( + new TypePathSegment (PathIdentSegment (ident.as_string (), + type.get_locus ()), + false, type.get_locus ())); // Create TypePath from segments auto type_path @@ -407,6 +411,9 @@ private: 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 (); @@ -459,9 +466,10 @@ private: 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.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( - PathIdentSegment (ident.as_string (), ident.get_locus ()), false, - ident.get_locus ()))); + 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); } diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index 5cc1c19..9a12423 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -51,7 +51,7 @@ 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))); diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc index 01400d8..20a4903 100644 --- a/gcc/rust/ast/rust-desugar-question-mark.cc +++ b/gcc/rust/ast/rust-desugar-question-mark.cc @@ -55,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))); @@ -82,7 +82,7 @@ err_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_ERR), std::move (pattern_item))); diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 7b0df25..3c36238 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -282,6 +282,8 @@ public: Expr &get_expr () { return *expr; } + std::unique_ptr<Expr> &get_expr_ptr () { return expr; } + std::string as_string () const override { return path.as_string () + " = " + expr->as_string (); @@ -296,7 +298,11 @@ public: // 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; @@ -414,6 +420,12 @@ 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; } @@ -455,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: @@ -488,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; @@ -536,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: @@ -865,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 () { @@ -872,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: @@ -1282,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 () { @@ -1289,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 { @@ -1468,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 () { @@ -1475,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; } @@ -1599,6 +1665,7 @@ class TupleIndexExpr : public ExprWithoutBlock TupleIndex tuple_index; location_t locus; + bool to_strip; // i.e. pair.0 @@ -1610,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) @@ -1630,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) @@ -1649,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 () @@ -1659,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; } @@ -1807,6 +1883,12 @@ public: 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 @@ -1923,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 @@ -2293,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; } @@ -2381,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; } @@ -2480,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 ()); @@ -2532,6 +2638,7 @@ public: 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 @@ -2597,6 +2704,12 @@ public: 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 */ @@ -2827,6 +2940,12 @@ public: 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 @@ -2922,8 +3041,7 @@ 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; @@ -2947,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 (); } @@ -2962,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) @@ -2985,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_expr () override + 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 () { @@ -3147,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; } @@ -3274,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 */ @@ -3335,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 */ @@ -3397,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 */ @@ -3510,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 */ @@ -3572,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 */ @@ -3645,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: @@ -3726,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; } @@ -3801,6 +3986,7 @@ public: // 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; } @@ -3886,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; } @@ -3978,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; } @@ -4078,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; @@ -4156,6 +4360,12 @@ 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 { @@ -4233,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 () { @@ -4240,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; @@ -4892,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; } @@ -5494,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; @@ -5667,6 +5897,10 @@ public: } std::vector<TupleTemplateStr> &get_templates () { return templates; } + const std::vector<TupleTemplateStr> &get_templates () const + { + return templates; + } Expr::Kind get_expr_kind () const override { @@ -5685,9 +5919,12 @@ public: 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 index 9f6a62f..7626abc 100644 --- a/gcc/rust/ast/rust-expression-yeast.cc +++ b/gcc/rust/ast/rust-expression-yeast.cc @@ -21,10 +21,8 @@ #include "rust-desugar-question-mark.h" #include "rust-desugar-try-block.h" #include "rust-desugar-for-loops.h" -#include "rust-ast-full.h" #include "rust-desugar-while-let.h" #include "rust-expr.h" -#include "rust-stmt.h" namespace Rust { namespace AST { @@ -32,7 +30,7 @@ namespace AST { void ExpressionYeast::go (AST::Crate &crate) { - DefaultASTVisitor::visit (crate); + PointerVisitor::visit (crate); } void @@ -54,7 +52,7 @@ ExpressionYeast::dispatch_loops (std::unique_ptr<Expr> &loop_expr) } void -ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr) +ExpressionYeast::reseat (std::unique_ptr<Expr> &expr) { switch (expr->get_expr_kind ()) { @@ -71,47 +69,8 @@ ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr) default: break; } -} - -void -ExpressionYeast::visit (ExprStmt &stmt) -{ - dispatch (stmt.get_expr_ptr ()); - - DefaultASTVisitor::visit (stmt); -} - -void -ExpressionYeast::visit (CallExpr &call) -{ - dispatch (call.get_function_expr_ptr ()); - - for (auto &arg : call.get_params ()) - dispatch (arg); - - DefaultASTVisitor::visit (call); -} - -void -ExpressionYeast::visit (BlockExpr &block) -{ - for (auto &stmt : block.get_statements ()) - if (stmt->get_stmt_kind () == Stmt::Kind::Expr) - dispatch (static_cast<ExprStmt &> (*stmt).get_expr_ptr ()); - - if (block.has_tail_expr ()) - dispatch (block.get_tail_expr_ptr ()); - - DefaultASTVisitor::visit (block); -} - -void -ExpressionYeast::visit (LetStmt &stmt) -{ - if (stmt.has_init_expr ()) - dispatch (stmt.get_init_expr_ptr ()); - DefaultASTVisitor::visit (stmt); + visit (expr); } } // namespace AST diff --git a/gcc/rust/ast/rust-expression-yeast.h b/gcc/rust/ast/rust-expression-yeast.h index 855918f..3f64b1d 100644 --- a/gcc/rust/ast/rust-expression-yeast.h +++ b/gcc/rust/ast/rust-expression-yeast.h @@ -19,7 +19,7 @@ #ifndef RUST_EXPRESSION_YEAST #define RUST_EXPRESSION_YEAST -#include "rust-ast-visitor.h" +#include "rust-ast-pointer-visitor.h" #include "rust-ast.h" #include "rust-desugar-question-mark.h" @@ -28,22 +28,19 @@ namespace AST { // This visitor takes care of all the expression desugars: try-blocks, // error-propagation, etc. -class ExpressionYeast : public AST::DefaultASTVisitor +class ExpressionYeast : public AST::PointerVisitor { - using AST::DefaultASTVisitor::visit; + using AST::PointerVisitor::reseat; + using AST::PointerVisitor::visit; public: void go (AST::Crate &); private: // Dispatch to the proper desugar - void dispatch (std::unique_ptr<Expr> &expr); - void dispatch_loops (std::unique_ptr<Expr> &loop_expr); + void reseat (std::unique_ptr<Expr> &expr) override; - void visit (AST::ExprStmt &) override; - void visit (AST::CallExpr &) override; - void visit (AST::LetStmt &) override; - void visit (AST::BlockExpr &) override; + void dispatch_loops (std::unique_ptr<Expr> &loop_expr); }; } // namespace AST 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 3722db2..e59bed3 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -20,20 +20,171 @@ #define RUST_FMT_H #include "rust-system.h" - -// FIXME: How to encode Option? +#include "optional.h" 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 +317,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 +389,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,12 +397,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" @@ -281,33 +410,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 d11eed7..7aea763 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -631,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); @@ -714,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? @@ -1567,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. @@ -1595,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; } @@ -2515,9 +2536,12 @@ 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 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; @@ -2528,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 () @@ -2695,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 { diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 793423a..068e364 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -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,8 +257,8 @@ 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, diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index a1b19d5..be04882 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -377,6 +377,13 @@ public: return *type; } + std::unique_ptr<AST::Type> &get_type_ptr () + { + rust_assert (has_type ()); + + return type; + } + GenericArg &get_default_value_unchecked () { rust_assert (has_default_value ()); @@ -448,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; @@ -465,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; } @@ -1252,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; } diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index 15ab0b7..a2fe5d5 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -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; @@ -421,7 +421,7 @@ SlicePattern::accept_vis (ASTVisitor &vis) } void -TuplePatternItemsRanged::accept_vis (ASTVisitor &vis) +TuplePatternItemsHasRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -433,7 +433,7 @@ TuplePattern::accept_vis (ASTVisitor &vis) } void -TuplePatternItemsMultiple::accept_vis (ASTVisitor &vis) +TuplePatternItemsNoRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -517,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 4945ec4..0da1981 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 { @@ -143,6 +144,12 @@ public: return *subpattern; } + std::unique_ptr<Pattern> &get_subpattern_ptr () + { + rust_assert (has_subpattern ()); + return subpattern; + } + Identifier get_ident () const { return variable_ident; } bool get_is_mut () const { return is_mut; } @@ -518,6 +525,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; } @@ -681,6 +694,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: @@ -761,6 +780,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: @@ -818,7 +843,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; @@ -834,29 +859,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 ()); @@ -868,7 +893,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 ()); @@ -913,7 +938,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 (); } @@ -975,49 +1000,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) @@ -1025,7 +1063,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 ()); @@ -1036,9 +1074,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; @@ -1051,32 +1088,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) @@ -1088,7 +1125,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 ()); @@ -1104,8 +1141,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; @@ -1131,14 +1169,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); } }; @@ -1221,49 +1259,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) @@ -1271,7 +1292,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 ()); @@ -1282,8 +1303,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; @@ -1297,35 +1318,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) @@ -1337,7 +1356,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 ()); @@ -1353,8 +1372,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; @@ -1381,17 +1400,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); } }; @@ -1508,6 +1524,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; } @@ -1522,35 +1544,18 @@ protected: }; // Base abstract class representing patterns in a SlicePattern -class SlicePatternItems +class SlicePatternItems : public PatternItems { public: - enum SlicePatternItemType - { - NO_REST, - HAS_REST, - }; - - virtual ~SlicePatternItems () {} - - // TODO: should this store location data? - // Unique pointer custom clone function std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const { - return std::unique_ptr<SlicePatternItems> ( - clone_slice_pattern_items_impl ()); + return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ()); } - virtual std::string as_string () const = 0; - - virtual void accept_vis (ASTVisitor &vis) = 0; - - virtual SlicePatternItemType get_pattern_type () const = 0; - protected: // pure virtual clone implementation - virtual SlicePatternItems *clone_slice_pattern_items_impl () const = 0; + virtual SlicePatternItems *clone_pattern_items_impl () const = 0; }; // Class representing the patterns in a SlicePattern without `..` @@ -1598,15 +1603,12 @@ public: return patterns; } - SlicePatternItemType get_pattern_type () const override - { - return SlicePatternItemType::NO_REST; - } + 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_slice_pattern_items_impl () const override + SlicePatternItemsNoRest *clone_pattern_items_impl () const override { return new SlicePatternItemsNoRest (*this); } @@ -1683,15 +1685,12 @@ public: return upper_patterns; } - SlicePatternItemType get_pattern_type () const override - { - return SlicePatternItemType::HAS_REST; - } + 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_slice_pattern_items_impl () const override + SlicePatternItemsHasRest *clone_pattern_items_impl () const override { return new SlicePatternItemsHasRest (*this); } 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 2a3496b..014963f 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -571,6 +571,12 @@ 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; } @@ -646,6 +652,12 @@ 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.value (); } @@ -720,6 +732,12 @@ 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? AnonConst &get_size_expr () { @@ -986,7 +1004,7 @@ public: return_type (std::move (type)), locus (locus) { if (!variadic_attrs.empty ()) - is_variadic = true; + _is_variadic = true; } // Copy constructor with clone @@ -1044,14 +1062,24 @@ 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, return_type->reconstruct (), locus); + _is_variadic, variadic_attrs, std::move (ret_type), locus); } protected: diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 73c34b2..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); } diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index e9b8596..3bf26af 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -56,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); diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index d4a642b..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; @@ -154,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) @@ -164,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) @@ -279,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 (); } @@ -318,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 () { @@ -332,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 () { diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 6433923..0a627f3 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -828,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, @@ -891,6 +895,10 @@ 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 ()) { @@ -1647,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); @@ -2000,13 +2010,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 (); + + // Check if capacity is a const type + if (capacity_ty->get_kind () != TyTy::TypeKind::CONST) + { + 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 (); - if (!TREE_CONSTANT (capacity_expr)) + 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", array_type); + rust_error_at (expr_locus, "non const num copies %qT", cap_tree); return error_mark_node; } @@ -2059,9 +2081,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 (); @@ -2209,11 +2231,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 ()); @@ -2617,15 +2638,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-extern.h b/gcc/rust/backend/rust-compile-extern.h index d6aa589..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 { @@ -57,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; @@ -124,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, @@ -158,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-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index fe65921..82333dc 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -27,6 +27,7 @@ #include "rust-hir-pattern.h" #include "rust-system.h" #include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Compile { @@ -158,13 +159,15 @@ CompilePatternCheckExpr::visit (HIR::RangePattern &pattern) pattern.get_mappings (), pattern.get_locus (), ctx); + 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, @@ -354,17 +357,51 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { - // TODO - rust_unreachable (); + 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 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 (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; - case HIR::TupleStructItems::MULTIPLE: + case HIR::TupleStructItems::NO_REST: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); + HIR::TupleStructItemsNoRest &items_no_range + = static_cast<HIR::TupleStructItemsNoRest &> (items); rust_assert (items_no_range.get_patterns ().size () == variant->num_fields ()); @@ -428,10 +465,10 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - 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 ()); size_t tuple_field_index = 0; // lookup the type to find out number of fields @@ -477,10 +514,10 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) } break; - case HIR::TuplePatternItems::MULTIPLE: + case HIR::TuplePatternItems::NO_REST: { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); size_t tuple_field_index = 0; for (auto &pat : items.get_patterns ()) @@ -532,25 +569,14 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) || lookup->get_kind () == TyTy::TypeKind::SLICE || lookup->get_kind () == TyTy::REF); - size_t array_element_index = 0; + // 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: - for (auto &pattern_member : pattern.get_items ()) - { - tree array_index_tree - = Backend::size_constant_expression (array_element_index++); - tree element_expr - = Backend::array_index_expression (match_scrutinee_expr, - array_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 ()); - } + scrutinee_index_expr_func = Backend::array_index_expression; break; case TyTy::TypeKind::SLICE: rust_sorry_at ( @@ -560,25 +586,81 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) 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 ()); - // First compare the size - check_expr = Backend::comparison_expression ( - ComparisonOperator::EQUAL, size_field, - build_int_cst (size_type_node, pattern.get_items ().size ()), - 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); - // Then compare each element in the slice pattern - for (auto &pattern_member : pattern.get_items ()) + // 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 slice_index_tree - = Backend::size_constant_expression (array_element_index++); + tree index_tree + = Backend::size_constant_expression (element_index++); tree element_expr - = Backend::slice_index_expression (match_scrutinee_expr, - slice_index_tree, - pattern.get_locus ()); + = 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); @@ -586,10 +668,82 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) 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; - default: - rust_unreachable (); } } @@ -628,25 +782,54 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { - // TODO - rust_unreachable (); + 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: + case HIR::TupleStructItems::NO_REST: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); - - rust_assert (items_no_range.get_patterns ().size () + 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, @@ -668,12 +851,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 ()); @@ -777,8 +958,9 @@ 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 ()) @@ -843,11 +1025,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 (); @@ -887,11 +1069,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 ()) { @@ -930,43 +1112,132 @@ CompilePatternBindings::visit (HIR::SlicePattern &pattern) || lookup->get_kind () == TyTy::TypeKind::SLICE || lookup->get_kind () == TyTy::REF); - size_t array_element_index = 0; + // 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: - for (auto &pattern_member : pattern.get_items ()) - { - tree array_index_tree - = Backend::size_constant_expression (array_element_index++); - tree element_expr - = Backend::array_index_expression (match_scrutinee_expr, - array_index_tree, - pattern.get_locus ()); - CompilePatternBindings::Compile (*pattern_member, element_expr, ctx); - } + 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"); + 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: { - for (auto &pattern_member : pattern.get_items ()) + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_patterns ()) { - tree slice_index_tree - = Backend::size_constant_expression (array_element_index++); + tree index_tree + = Backend::size_constant_expression (element_index++); tree element_expr - = Backend::slice_index_expression (match_scrutinee_expr, - slice_index_tree, - pattern.get_locus ()); + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); CompilePatternBindings::Compile (*pattern_member, element_expr, ctx); } - break; } - default: - rust_unreachable (); + 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; } } @@ -979,6 +1250,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 ()) { @@ -990,6 +1266,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); } @@ -1013,22 +1294,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 (); @@ -1069,11 +1393,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 ()) { diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index f3b9dc2..c33d0b0 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -97,8 +97,11 @@ 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); diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 0622954..5b00afa 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -136,13 +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::ConstType &) +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; } @@ -186,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); @@ -217,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 ()) @@ -227,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 ()) @@ -277,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) @@ -357,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); @@ -382,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 ())); } // @@ -460,10 +473,9 @@ 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); @@ -476,8 +488,22 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) { tree element_type = TyTyResolveCompile::compile (ctx, type.get_element_type ()); - TyTy::ConstType *const_capacity = type.get_capacity (); - tree folded_capacity_expr = const_capacity->get_value (); + auto const_capacity = type.get_capacity (); + + // 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; + } + + auto *capacity_const = const_capacity->as_const_type (); + + 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 (); // build_index_type takes the maximum index, which is one less than // the length. @@ -772,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 0675343..d6c3259 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -50,7 +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::ConstType &) 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 5c6d145..1f306ad 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -64,31 +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: + case HIR::TuplePatternItems::ItemType::NO_REST: { - rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( + auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> ( pattern.get_items ()); - size_t offs = 0; - for (auto &sub : items.get_patterns ()) + tree field = TYPE_FIELDS (translated_type); + for (auto &sub : items_no_rest.get_patterns ()) { - tree sub_ty = error_mark_node; - tree field = TYPE_FIELDS (translated_type); - for (size_t i = 0; i < offs; i++) + 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 ()); + + // 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 ()) + { + 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 dbd8515..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); diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index d524d09..d04f864 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -101,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 */ @@ -457,23 +499,24 @@ save_fundef_copy (tree fun, tree copy) 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 tree eval_constant_expression (const constexpr_ctx *ctx, tree, bool, - bool *, bool *, tree * = NULL); + bool *, bool *, tree *jump_target); 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 *); + bool *, bool *, tree *jump_target); static tree eval_call_expression (const constexpr_ctx *ctx, tree r, bool, - bool *, bool *); + bool *, bool *, tree *); static tree eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, - bool *, bool *); + bool *, bool *, tree *jump_target); static tree get_function_named_in_call (tree t); @@ -488,7 +531,8 @@ static tree eval_conditional_expression (const constexpr_ctx *ctx, tree t, 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); + 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, @@ -500,7 +544,15 @@ static tree eval_switch_expr (const constexpr_ctx *ctx, tree t, static tree eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, bool *non_constant_p, - bool *overflow_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. */ @@ -562,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 @@ -589,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) @@ -607,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; @@ -654,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 */ @@ -663,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))); @@ -672,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; } } @@ -691,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; } } @@ -721,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; @@ -780,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 @@ -795,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] */ @@ -804,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 @@ -824,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; @@ -842,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; @@ -862,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 @@ -891,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; @@ -917,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; } @@ -1243,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); @@ -1280,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; @@ -1331,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; @@ -1401,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]; @@ -1409,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]); } @@ -1555,7 +1617,8 @@ 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); + bool *non_constant_p, bool *overflow_p, + tree *jump_target); // forked from gcc/cp/constexpr.cc cxx_eval_array_reference @@ -1564,11 +1627,11 @@ static tree 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 @@ -1577,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; @@ -1680,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; @@ -1693,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; @@ -1701,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) @@ -1790,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 @@ -1850,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) { @@ -1921,34 +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; - } + /* 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: @@ -2014,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 @@ -2023,14 +2099,14 @@ 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: @@ -2079,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. */ @@ -2096,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: @@ -2135,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 @@ -2156,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: @@ -2169,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: @@ -2189,13 +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: { 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; @@ -2225,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); @@ -2239,7 +2320,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, 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; @@ -2284,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)) @@ -2303,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: @@ -2318,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: @@ -2332,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: @@ -2381,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: @@ -2407,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; @@ -2417,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: @@ -2429,7 +2515,8 @@ 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. */ @@ -2440,7 +2527,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, 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); @@ -2571,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; @@ -2632,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; @@ -2653,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; } @@ -2665,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; @@ -2694,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; } @@ -2718,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; @@ -2910,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. */ @@ -3012,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; + 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 @@ -3065,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); @@ -3089,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; @@ -3155,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)); @@ -3258,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) @@ -3355,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. @@ -3363,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); @@ -3392,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 @@ -3960,7 +4145,7 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) 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: { @@ -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 @@ -4322,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)) @@ -4427,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) @@ -4443,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; } @@ -4456,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) @@ -4473,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)) @@ -4683,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)) { @@ -4722,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; @@ -4960,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; @@ -4995,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); @@ -5136,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); @@ -5148,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 @@ -5908,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 @@ -6484,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/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index e2cc2dd..de8a830 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -24,7 +24,6 @@ #include "rust-hir-item.h" #include "rust-hir-type-check.h" #include "rust-hir-visitor.h" -#include "rust-name-resolver.h" #include "rust-bir.h" #include "rust-bir-free-region.h" #include "rust-immutable-name-resolution-context.h" @@ -75,7 +74,7 @@ struct BuilderContext // External context. Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; // BIR output BasicBlocks basic_blocks; @@ -104,7 +103,7 @@ struct BuilderContext public: BuilderContext () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()) + resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()) { basic_blocks.emplace_back (); // StartBB } @@ -403,69 +402,31 @@ protected: // HIR resolution helpers template <typename T> NodeId resolve_label (T &expr) { - NodeId resolved_label; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - resolved_label = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_label ( - expr.get_mappings ().get_nodeid (), &resolved_label); - rust_assert (ok); - } - return resolved_label; + auto res = ctx.resolver.lookup (expr.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return res.value (); } template <typename T> PlaceId resolve_variable (T &variable) { - NodeId variable_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - variable_id = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); - } - return ctx.place_db.lookup_variable (variable_id); + auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return ctx.place_db.lookup_variable (res.value ()); } template <typename T> PlaceId resolve_variable_or_fn (T &variable, TyTy::BaseType *ty) { ty = (ty) ? ty : lookup_type (variable); + // Unlike variables, // functions do not have to be declared in PlaceDB before use. - NodeId variable_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - variable_id = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); - } if (ty->is<TyTy::FnType> ()) return ctx.place_db.get_constant (ty); - else - return ctx.place_db.lookup_or_add_variable (variable_id, ty); + + auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return ctx.place_db.lookup_or_add_variable (res.value (), ty); } protected: // Implicit conversions. diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc index 2d655f9..e78d750 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc @@ -70,11 +70,34 @@ PatternBindingBuilder::visit (HIR::SlicePattern &pattern) return ty->as<TyTy::SliceType> ()->get_element_type (); }); - // Regions are unchnaged. + // Regions are unchanged. - for (auto &item : pattern.get_items ()) + switch (pattern.get_items ().get_item_type ()) { - item->accept_vis (*this); + case HIR::SlicePatternItems::NO_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &member : items.get_patterns ()) + { + member->accept_vis (*this); + } + break; + } + case HIR::SlicePatternItems::HAS_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (auto &member : items.get_lower_patterns ()) + { + member->accept_vis (*this); + } + for (auto &member : items.get_upper_patterns ()) + { + member->accept_vis (*this); + } + break; + } } } @@ -202,17 +225,17 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::MULTIPLE: + case HIR::TuplePatternItems::NO_REST: { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } - case HIR::TuplePatternItems::RANGED: + case HIR::TuplePatternItems::HAS_REST: { auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); auto tyty = ctx.place_db[init.value ()].tyty; rust_assert (tyty->get_kind () == TyTy::TUPLE); @@ -249,10 +272,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { auto &items - = static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ()); + = static_cast<HIR::TupleStructItemsHasRest &> (pattern.get_items ()); rust_assert (type->get_kind () == TyTy::ADT); auto adt_ty = static_cast<TyTy::ADTType *> (type); @@ -267,10 +290,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) visit_tuple_fields (items.get_upper_patterns (), saved, index); break; } - case HIR::TupleStructItems::MULTIPLE: + case HIR::TupleStructItems::NO_REST: { auto &items - = static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ()); + = static_cast<HIR::TupleStructItemsNoRest &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h index d87ff8c..6cb87c7 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h @@ -225,11 +225,11 @@ protected: rust_unreachable (); } void visit (HIR::StructPattern &pattern) override { rust_unreachable (); } - void visit (HIR::TupleStructItemsNoRange &tuple_items) override + void visit (HIR::TupleStructItemsNoRest &tuple_items) override { rust_unreachable (); } - void visit (HIR::TupleStructItemsRange &tuple_items) override + void visit (HIR::TupleStructItemsHasRest &tuple_items) override { rust_unreachable (); } @@ -237,15 +237,23 @@ protected: { rust_unreachable (); } - void visit (HIR::TuplePatternItemsMultiple &tuple_items) override + void visit (HIR::TuplePatternItemsNoRest &tuple_items) override { rust_unreachable (); } - void visit (HIR::TuplePatternItemsRanged &tuple_items) override + void visit (HIR::TuplePatternItemsHasRest &tuple_items) override { rust_unreachable (); } void visit (HIR::TuplePattern &pattern) override { rust_unreachable (); } + void visit (HIR::SlicePatternItemsNoRest &tuple_items) override + { + rust_unreachable (); + } + void visit (HIR::SlicePatternItemsHasRest &tuple_items) override + { + rust_unreachable (); + } void visit (HIR::SlicePattern &pattern) override { rust_unreachable (); } void visit (HIR::AltPattern &pattern) override { rust_unreachable (); } void visit (HIR::EmptyStmt &stmt) override { rust_unreachable (); } diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h index 86f96c1..63f2a95 100644 --- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h @@ -170,12 +170,14 @@ public: void visit (HIR::StructPatternFieldIdentPat &field) override {} void visit (HIR::StructPatternFieldIdent &field) override {} void visit (HIR::StructPattern &pattern) override {} - void visit (HIR::TupleStructItemsNoRange &tuple_items) override {} - void visit (HIR::TupleStructItemsRange &tuple_items) override {} + void visit (HIR::TupleStructItemsNoRest &tuple_items) override {} + void visit (HIR::TupleStructItemsHasRest &tuple_items) override {} void visit (HIR::TupleStructPattern &pattern) override {} - void visit (HIR::TuplePatternItemsMultiple &tuple_items) override {} - void visit (HIR::TuplePatternItemsRanged &tuple_items) override {} + void visit (HIR::TuplePatternItemsNoRest &tuple_items) override {} + void visit (HIR::TuplePatternItemsHasRest &tuple_items) override {} void visit (HIR::TuplePattern &pattern) override {} + void visit (HIR::SlicePatternItemsNoRest &tuple_items) override {} + void visit (HIR::SlicePatternItemsHasRest &tuple_items) override {} void visit (HIR::SlicePattern &pattern) override {} void visit (HIR::AltPattern &pattern) override {} void visit (HIR::EmptyStmt &stmt) override {} diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/feature/rust-feature-gate.cc index 44007f9..44007f9 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.cc +++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/feature/rust-feature-gate.h index f1011e5..f1011e5 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.h +++ b/gcc/rust/checks/errors/feature/rust-feature-gate.h diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/feature/rust-feature.cc index 071d3f8..071d3f8 100644 --- a/gcc/rust/checks/errors/rust-feature.cc +++ b/gcc/rust/checks/errors/feature/rust-feature.cc diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/feature/rust-feature.h index e7cb0af..e7cb0af 100644 --- a/gcc/rust/checks/errors/rust-feature.h +++ b/gcc/rust/checks/errors/feature/rust-feature.h diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc index 5291276..90248d3 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc @@ -20,7 +20,7 @@ #include "rust-reachability.h" #include "rust-hir-type-check.h" #include "rust-hir-map.h" -#include "rust-name-resolver.h" +#include "rust-immutable-name-resolution-context.h" #include "rust-visibility-resolver.h" #include "rust-pub-restricted-visitor.h" #include "rust-privacy-reporter.h" @@ -35,12 +35,13 @@ Resolver::resolve (HIR::Crate &crate) { PrivacyContext ctx; auto &mappings = Analysis::Mappings::get (); - auto resolver = Rust::Resolver::Resolver::get (); + auto &resolver + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get (); - VisibilityResolver (mappings, *resolver).go (crate); + VisibilityResolver (mappings, resolver).go (crate); PubRestrictedVisitor (mappings).go (crate); - PrivacyReporter (mappings, *resolver, *ty_ctx).go (crate); + PrivacyReporter (mappings, resolver, *ty_ctx).go (crate); auto visitor = ReachabilityVisitor (ctx, *ty_ctx); diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index 4af9639..c1a3d45 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -28,7 +28,8 @@ namespace Rust { namespace Privacy { PrivacyReporter::PrivacyReporter ( - Analysis::Mappings &mappings, Resolver::Resolver &resolver, + Analysis::Mappings &mappings, + const Resolver2_0::NameResolutionContext &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx) : mappings (mappings), resolver (resolver), ty_ctx (ty_ctx), current_module (tl::nullopt) @@ -90,59 +91,18 @@ PrivacyReporter::go (HIR::Crate &crate) } } -static bool -is_child_module (Analysis::Mappings &mappings, NodeId parent, - NodeId possible_child) -{ - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - return nr_ctx.values.is_module_descendant (parent, possible_child); - } - - auto children = mappings.lookup_module_children (parent); - - if (!children) - return false; - - // Visit all toplevel children - for (auto &child : *children) - if (child == possible_child) - return true; - - // Now descend recursively in the child module tree - for (auto &child : *children) - if (is_child_module (mappings, child, possible_child)) - return true; - - return false; -} - // FIXME: This function needs a lot of refactoring void PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, const location_t locus) { - NodeId ref_node_id = UNKNOWN_NODEID; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (use_id)) - ref_node_id = *id; - } - // FIXME: Don't assert here - we might be dealing with a type - else if (!resolver.lookup_resolved_name (use_id, &ref_node_id)) - resolver.lookup_resolved_type (use_id, &ref_node_id); + NodeId ref_node_id; // FIXME: Assert here. For now, we return since this causes issues when // checking inferred types (#1260) - // rust_assert (ref_node_id != UNKNOWN_NODEID); - if (ref_node_id == UNKNOWN_NODEID) + if (auto id = resolver.lookup (use_id)) + ref_node_id = *id; + else return; auto vis = mappings.lookup_visibility (ref_node_id); @@ -175,7 +135,9 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, // FIXME: This needs a LOT of TLC: hinting about the definition, a // string to say if it's a module, function, type, etc... - if (!is_child_module (mappings, mod_node_id, current_module.value ())) + + if (!resolver.values.is_module_descendant (mod_node_id, + current_module.value ())) valid = false; } break; diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h index 72716a6..d64b7a7 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h @@ -22,8 +22,9 @@ #include "rust-hir-expr.h" #include "rust-hir-map.h" #include "rust-hir-visitor.h" +#include "rust-hir-type-check.h" #include "rust-mapping-common.h" -#include "rust-name-resolver.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Privacy { @@ -38,7 +39,7 @@ class PrivacyReporter : public HIR::HIRExpressionVisitor, { public: PrivacyReporter (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver, + const Resolver2_0::NameResolutionContext &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx); /** @@ -157,7 +158,7 @@ types virtual void visit (HIR::ExprStmt &stmt); Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; const Rust::Resolver::TypeCheckContext &ty_ctx; // `None` means we're in the root module - the crate diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc index c59763d..4240673 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc @@ -20,16 +20,14 @@ #include "rust-ast.h" #include "rust-hir.h" #include "rust-hir-item.h" -#include "rust-immutable-name-resolution-context.h" - -// for flag_name_resolution_2_0 -#include "options.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Privacy { -VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings, - Resolver::Resolver &resolver) +VisibilityResolver::VisibilityResolver ( + Analysis::Mappings &mappings, + const Resolver2_0::NameResolutionContext &resolver) : mappings (mappings), resolver (resolver) {} @@ -64,23 +62,12 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction, = Error (restriction.get_locus (), "cannot use non-module path as privacy restrictor"); - NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) + NodeId ref_node_id; + if (auto id = resolver.lookup (ast_node_id)) { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (ast_node_id)) - { - ref_node_id = *id; - } - else - { - invalid_path.emit (); - return false; - } + ref_node_id = *id; } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + else { invalid_path.emit (); return false; diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h index 4dfba4c..ddd70a8 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h @@ -24,7 +24,7 @@ #include "rust-hir-stmt.h" #include "rust-hir-item.h" #include "rust-hir-map.h" -#include "rust-name-resolver.h" +#include "rust-name-resolution-context.h" #include "rust-hir-visitor.h" namespace Rust { @@ -34,7 +34,7 @@ class VisibilityResolver : public HIR::HIRVisItemVisitor { public: VisibilityResolver (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver); + const Resolver2_0::NameResolutionContext &resolver); /** * Perform visibility resolving on an entire crate @@ -93,7 +93,7 @@ public: private: Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; DefId current_module; }; diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc index c40f9db..782d694 100644 --- a/gcc/rust/checks/errors/rust-const-checker.cc +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -813,11 +813,11 @@ ConstChecker::visit (StructPattern &) {} void -ConstChecker::visit (TupleStructItemsNoRange &) +ConstChecker::visit (TupleStructItemsNoRest &) {} void -ConstChecker::visit (TupleStructItemsRange &) +ConstChecker::visit (TupleStructItemsHasRest &) {} void @@ -825,11 +825,11 @@ ConstChecker::visit (TupleStructPattern &) {} void -ConstChecker::visit (TuplePatternItemsMultiple &) +ConstChecker::visit (TuplePatternItemsNoRest &) {} void -ConstChecker::visit (TuplePatternItemsRanged &) +ConstChecker::visit (TuplePatternItemsHasRest &) {} void @@ -837,6 +837,14 @@ ConstChecker::visit (TuplePattern &) {} void +ConstChecker::visit (SlicePatternItemsNoRest &) +{} + +void +ConstChecker::visit (SlicePatternItemsHasRest &) +{} + +void ConstChecker::visit (SlicePattern &) {} diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h index eb63095..d464b7b 100644 --- a/gcc/rust/checks/errors/rust-const-checker.h +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -180,12 +180,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 2566971..f132e04 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -28,15 +28,12 @@ #include "rust-tyty.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Analysis { PatternChecker::PatternChecker () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()), + resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()), mappings (Analysis::Mappings::get ()) {} @@ -238,17 +235,9 @@ PatternChecker::visit (CallExpr &expr) NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid (); NodeId ref_node_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (ast_node_id)) - ref_node_id = *id; - else - return; - } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + if (auto id = resolver.lookup (ast_node_id)) + ref_node_id = *id; + else return; if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id)) @@ -640,11 +629,11 @@ PatternChecker::visit (StructPattern &) {} void -PatternChecker::visit (TupleStructItemsNoRange &) +PatternChecker::visit (TupleStructItemsNoRest &) {} void -PatternChecker::visit (TupleStructItemsRange &) +PatternChecker::visit (TupleStructItemsHasRest &) {} void @@ -652,11 +641,11 @@ PatternChecker::visit (TupleStructPattern &) {} void -PatternChecker::visit (TuplePatternItemsMultiple &) +PatternChecker::visit (TuplePatternItemsNoRest &) {} void -PatternChecker::visit (TuplePatternItemsRanged &) +PatternChecker::visit (TuplePatternItemsHasRest &) {} void @@ -664,6 +653,14 @@ PatternChecker::visit (TuplePattern &) {} void +PatternChecker::visit (SlicePatternItemsNoRest &) +{} + +void +PatternChecker::visit (SlicePatternItemsHasRest &) +{} + +void PatternChecker::visit (SlicePattern &) {} @@ -980,7 +977,7 @@ Matrix::specialize (const Constructor &ctor) const if (ctor.is_covered_by (hd.ctor ())) { pats.pop_head_constructor (ctor, subfields_place_info.size ()); - new_rows.push_back (MatrixRow (pats, row.is_under_guard ())); + new_rows.emplace_back (pats, row.is_under_guard ()); } } @@ -1186,7 +1183,7 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, } } - stack.push_back (WitnessPat (ctor, subfield, ty)); + stack.emplace_back (ctor, subfield, ty); } } @@ -1213,27 +1210,54 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx, std::vector<DeconstructedPat> fields; switch (elems.get_item_type ()) { - case HIR::TupleStructItems::ItemType::MULTIPLE: + case HIR::TupleStructItems::ItemType::NO_REST: { - HIR::TupleStructItemsNoRange &multiple - = static_cast<HIR::TupleStructItemsNoRange &> (elems); + HIR::TupleStructItemsNoRest &items_no_rest + = static_cast<HIR::TupleStructItemsNoRest &> (elems); rust_assert (variant->get_fields ().size () - == multiple.get_patterns ().size ()); + == items_no_rest.get_patterns ().size ()); - for (size_t i = 0; i < multiple.get_patterns ().size (); i++) + for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++) { fields.push_back ( - lower_pattern (ctx, *multiple.get_patterns ().at (i), + lower_pattern (ctx, *items_no_rest.get_patterns ().at (i), variant->get_fields ().at (i)->get_field_type ())); } return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; - case HIR::TupleStructItems::ItemType::RANGED: + case HIR::TupleStructItems::ItemType::HAS_REST: { - // TODO: ranged tuple struct items - rust_unreachable (); + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (elems); + + size_t num_patterns = items_has_rest.get_lower_patterns ().size () + + items_has_rest.get_upper_patterns ().size (); + + rust_assert (num_patterns <= variant->num_fields ()); + + size_t i = 0; + for (auto &pattern_member : items_has_rest.get_lower_patterns ()) + { + fields.push_back (lower_pattern ( + ctx, *pattern_member, + variant->get_fields ().at (i++)->get_field_type ())); + } + while (i < variant->num_fields () + - items_has_rest.get_upper_patterns ().size ()) + { + fields.push_back ( + DeconstructedPat::make_wildcard (pattern.get_locus ())); + i++; + } + for (auto &pattern_member : items_has_rest.get_upper_patterns ()) + { + fields.push_back (lower_pattern ( + ctx, *pattern_member, + variant->get_fields ().at (i++)->get_field_type ())); + } + return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; default: @@ -1597,7 +1621,7 @@ check_match_usefulness (Resolver::TypeCheckContext *ctx, MatchArm lowered = lower_arm (ctx, arm, scrutinee_ty); PatOrWild pat = PatOrWild::make_pattern (lowered.get_pat ()); pats.push (pat); - rows.push_back (MatrixRow (pats, lowered.has_guard ())); + rows.emplace_back (pats, lowered.has_guard ()); } std::vector<PlaceInfo> place_infos = {{PlaceInfo (scrutinee_ty)}}; diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h index dd44abc..645e61d 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h @@ -26,7 +26,7 @@ #include "rust-tyty.h" #include "optional.h" #include "rust-hir-visitor.h" -#include "rust-name-resolver.h" +#include "rust-immutable-name-resolution-context.h" namespace Rust { namespace Analysis { @@ -46,7 +46,7 @@ public: private: Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; Analysis::Mappings &mappings; virtual void visit (Lifetime &lifetime) override; @@ -153,12 +153,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/errors/rust-readonly-check.cc b/gcc/rust/checks/errors/rust-readonly-check.cc index c128933..f484047 100644 --- a/gcc/rust/checks/errors/rust-readonly-check.cc +++ b/gcc/rust/checks/errors/rust-readonly-check.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -17,184 +17,252 @@ // <http://www.gnu.org/licenses/>. #include "rust-readonly-check.h" -#include "rust-tree.h" -#include "rust-gcc.h" -#include "print-tree.h" +#include "rust-hir-expr.h" +#include "rust-hir-node.h" +#include "rust-hir-path.h" +#include "rust-hir-map.h" +#include "rust-hir-pattern.h" +#include "rust-mapping-common.h" +#include "rust-system.h" +#include "rust-immutable-name-resolution-context.h" +#include "rust-tyty.h" namespace Rust { -namespace Analysis { +namespace HIR { -static std::map<tree, int> assignment_map = {}; +static std::set<HirId> already_assigned_variables = {}; + +ReadonlyChecker::ReadonlyChecker () + : resolver (*Resolver::Resolver::get ()), + mappings (Analysis::Mappings::get ()), + context (*Resolver::TypeCheckContext::get ()) +{} + +void +ReadonlyChecker::go (Crate &crate) +{ + for (auto &item : crate.get_items ()) + item->accept_vis (*this); +} -// ported over from c-family/c-warn.cc void -readonly_error (location_t loc, tree arg, enum lvalue_use use) +ReadonlyChecker::visit (AssignmentExpr &expr) { - gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement - || use == lv_asm); - STRIP_ANY_LOCATION_WRAPPER (arg); - /* Using this macro rather than (for example) arrays of messages - ensures that all the format strings are checked at compile - time. */ -#define READONLY_MSG(A, I, D, AS) \ - (use == lv_assign \ - ? (A) \ - : (use == lv_increment ? (I) : (use == lv_decrement ? (D) : (AS)))) - if (TREE_CODE (arg) == COMPONENT_REF) + Expr &lhs = expr.get_lhs (); + mutable_context.enter (expr.get_mappings ().get_hirid ()); + lhs.accept_vis (*this); + mutable_context.exit (); +} + +void +ReadonlyChecker::visit (PathInExpression &expr) +{ + if (!mutable_context.is_in_context ()) + return; + + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + NodeId def_id; + + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + if (auto id = nr_ctx.lookup (ast_node_id)) + def_id = *id; + else + return; + + auto hir_id = mappings.lookup_node_to_hir (def_id); + if (!hir_id) + return; + + // Check if the local variable is mutable. + auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id); + if (maybe_pattern + && maybe_pattern.value ()->get_pattern_type () + == HIR::Pattern::PatternType::IDENTIFIER) + check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()), + expr.get_locus ()); + + // Check if the static item is mutable. + auto maybe_item = mappings.lookup_hir_item (*hir_id); + if (maybe_item + && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static) { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - error_at (loc, - READONLY_MSG (G_ ("assignment of member " - "%qD in read-only object"), - G_ ("increment of member " - "%qD in read-only object"), - G_ ("decrement of member " - "%qD in read-only object"), - G_ ("member %qD in read-only object " - "used as %<asm%> output")), - TREE_OPERAND (arg, 1)); - else - error_at ( - loc, - READONLY_MSG (G_ ("assignment of read-only member %qD"), - G_ ("increment of read-only member %qD"), - G_ ("decrement of read-only member %qD"), - G_ ("read-only member %qD used as %<asm%> output")), - TREE_OPERAND (arg, 1)); + auto static_item = static_cast<HIR::StaticItem *> (*maybe_item); + if (!static_item->is_mut ()) + rust_error_at (expr.get_locus (), + "assignment of read-only location '%s'", + static_item->get_identifier ().as_string ().c_str ()); } - else if (VAR_P (arg)) - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only variable %qD"), - G_ ("increment of read-only variable %qD"), - G_ ("decrement of read-only variable %qD"), - G_ ( - "read-only variable %qD used as %<asm%> output")), - arg); - else if (TREE_CODE (arg) == PARM_DECL) - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only parameter %qD"), - G_ ("increment of read-only parameter %qD"), - G_ ("decrement of read-only parameter %qD"), - G_ ( - "read-only parameter %qD use as %<asm%> output")), - arg); - else if (TREE_CODE (arg) == RESULT_DECL) + + // Check if the constant item is mutable. + if (maybe_item + && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant) { - error_at (loc, - READONLY_MSG (G_ ("assignment of " - "read-only named return value %qD"), - G_ ("increment of " - "read-only named return value %qD"), - G_ ("decrement of " - "read-only named return value %qD"), - G_ ("read-only named return value %qD " - "used as %<asm%>output")), - arg); + auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item); + rust_error_at (expr.get_locus (), "assignment of read-only location '%s'", + const_item->get_identifier ().as_string ().c_str ()); } - else if (TREE_CODE (arg) == FUNCTION_DECL) - error_at (loc, - READONLY_MSG (G_ ("assignment of function %qD"), - G_ ("increment of function %qD"), - G_ ("decrement of function %qD"), - G_ ("function %qD used as %<asm%> output")), - arg); - else - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only location %qE"), - G_ ("increment of read-only location %qE"), - G_ ("decrement of read-only location %qE"), - G_ ( - "read-only location %qE used as %<asm%> output")), - arg); } -static void -emit_error (tree *t, tree lhs, enum lvalue_use use) +void +ReadonlyChecker::check_variable (IdentifierPattern *pattern, + location_t assigned_loc) { - readonly_error (EXPR_LOCATION (*t), lhs, use); - TREE_OPERAND (*t, 0) = error_mark_node; + if (!mutable_context.is_in_context ()) + return; + + TyTy::BaseType *type; + if (context.lookup_type (pattern->get_mappings ().get_hirid (), &type) + && is_mutable_type (type)) + return; + if (pattern->is_mut ()) + return; + + auto hir_id = pattern->get_mappings ().get_hirid (); + if (already_assigned_variables.count (hir_id) > 0) + rust_error_at (assigned_loc, "assignment of read-only variable '%s'", + pattern->as_string ().c_str ()); + already_assigned_variables.insert (hir_id); } -static void -check_modify_expr (tree *t) +void +ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern, + bool has_init_expr) { - tree lhs = TREE_OPERAND (*t, 0); - if (TREE_CODE (lhs) == ARRAY_REF || TREE_CODE (lhs) == COMPONENT_REF) - lhs = TREE_OPERAND (lhs, 0); - - tree lhs_type = TREE_TYPE (lhs); - if (TYPE_READONLY (lhs_type) || TREE_READONLY (lhs) || TREE_CONSTANT (lhs)) + if (has_init_expr) { - if (TREE_CODE (lhs) != VAR_DECL) - emit_error (t, lhs, lv_assign); - else if (!DECL_ARTIFICIAL (lhs)) - { - if (DECL_INITIAL (lhs) != NULL) - emit_error (t, lhs, lv_assign); - else - { - if (assignment_map.find (lhs) == assignment_map.end ()) - { - assignment_map.insert ({lhs, 0}); - } - assignment_map[lhs]++; - - if (assignment_map[lhs] > 1) - emit_error (t, lhs, lv_assign); - } - } + HirId pattern_id = pattern.get_mappings ().get_hirid (); + already_assigned_variables.insert (pattern_id); } } -static void -check_decl (tree *t) +void +ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern, + bool has_init_expr) { - switch (TREE_CODE (*t)) + switch (tuple_pattern.get_items ().get_item_type ()) { - case MODIFY_EXPR: - check_modify_expr (t); + case HIR::TuplePatternItems::ItemType::NO_REST: + { + auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> ( + tuple_pattern.get_items ()); + for (auto &sub : items_no_rest.get_patterns ()) + { + collect_assignment (*sub, has_init_expr); + } + } + break; + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> ( + tuple_pattern.get_items ()); + for (auto &sub : items_has_rest.get_lower_patterns ()) + collect_assignment (*sub, has_init_expr); + for (auto &sub : items_has_rest.get_upper_patterns ()) + collect_assignment (*sub, has_init_expr); + } + break; + default: break; + } +} +void +ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr) +{ + switch (pattern.get_pattern_type ()) + { + case HIR::Pattern::PatternType::IDENTIFIER: + { + collect_assignment_identifier (static_cast<IdentifierPattern &> ( + pattern), + has_init_expr); + } + break; + case HIR::Pattern::PatternType::TUPLE: + { + auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern); + collect_assignment_tuple (tuple_pattern, has_init_expr); + } + break; default: break; } } -static tree -readonly_walk_fn (tree *t, int *, void *) +void +ReadonlyChecker::visit (LetStmt &stmt) +{ + HIR::Pattern &pattern = stmt.get_pattern (); + collect_assignment (pattern, stmt.has_init_expr ()); +} + +void +ReadonlyChecker::visit (FieldAccessExpr &expr) { - check_decl (t); - return NULL_TREE; + if (mutable_context.is_in_context ()) + { + expr.get_receiver_expr ().accept_vis (*this); + } } void -ReadonlyCheck::Lint (Compile::Context &ctx) +ReadonlyChecker::visit (TupleIndexExpr &expr) { - assignment_map.clear (); - for (auto &fndecl : ctx.get_func_decls ()) + if (mutable_context.is_in_context ()) { - for (tree p = DECL_ARGUMENTS (fndecl); p != NULL_TREE; p = DECL_CHAIN (p)) - { - check_decl (&p); - } + expr.get_tuple_expr ().accept_vis (*this); + } +} - walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl), - &readonly_walk_fn, &ctx); +void +ReadonlyChecker::visit (ArrayIndexExpr &expr) +{ + if (mutable_context.is_in_context ()) + { + expr.get_array_expr ().accept_vis (*this); } +} - assignment_map.clear (); - for (auto &var : ctx.get_var_decls ()) +void +ReadonlyChecker::visit (TupleExpr &expr) +{ + if (mutable_context.is_in_context ()) { - tree decl = var->get_decl (); - check_decl (&decl); + // TODO: Add check for tuple expression } +} - assignment_map.clear (); - for (auto &const_decl : ctx.get_const_decls ()) +void +ReadonlyChecker::visit (LiteralExpr &expr) +{ + if (mutable_context.is_in_context ()) { - check_decl (&const_decl); + rust_error_at (expr.get_locus (), "assignment of read-only location"); } } -} // namespace Analysis +void +ReadonlyChecker::visit (DereferenceExpr &expr) +{ + if (!mutable_context.is_in_context ()) + return; + TyTy::BaseType *to_deref_type; + auto to_deref = expr.get_expr ().get_mappings ().get_hirid (); + if (!context.lookup_type (to_deref, &to_deref_type)) + return; + if (!is_mutable_type (to_deref_type)) + rust_error_at (expr.get_locus (), "assignment of read-only location"); +} + +bool +ReadonlyChecker::is_mutable_type (TyTy::BaseType *type) +{ + if (type->get_kind () == TyTy::TypeKind::REF) + return static_cast<TyTy::ReferenceType *> (type)->is_mutable (); + if (type->get_kind () == TyTy::TypeKind::POINTER) + return static_cast<TyTy::PointerType *> (type)->is_mutable (); + return false; +} +} // namespace HIR } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-readonly-check.h b/gcc/rust/checks/errors/rust-readonly-check.h index b39eee3..3525620 100644 --- a/gcc/rust/checks/errors/rust-readonly-check.h +++ b/gcc/rust/checks/errors/rust-readonly-check.h @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -16,21 +16,54 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#ifndef RUST_READONLY_CHECK -#define RUST_READONLY_CHECK - -#include "rust-compile-context.h" +#include "rust-hir-visitor.h" +#include "rust-name-resolver.h" +#include "rust-stacked-contexts.h" +#include "rust-hir-type-check.h" namespace Rust { -namespace Analysis { - -class ReadonlyCheck +namespace HIR { +class ReadonlyChecker : public DefaultHIRVisitor { public: - static void Lint (Compile::Context &ctx); -}; + ReadonlyChecker (); + + void go (HIR::Crate &crate); + +private: + enum class lvalue_use + { + assign, + increment, + decrement, + }; + + Resolver::Resolver &resolver; + Analysis::Mappings &mappings; + Resolver::TypeCheckContext &context; + StackedContexts<HirId> mutable_context; -} // namespace Analysis -} // namespace Rust + using DefaultHIRVisitor::visit; + + virtual void visit (AssignmentExpr &expr) override; + virtual void visit (PathInExpression &expr) override; + virtual void visit (FieldAccessExpr &expr) override; + virtual void visit (ArrayIndexExpr &expr) override; + virtual void visit (TupleExpr &expr) override; + virtual void visit (TupleIndexExpr &expr) override; + virtual void visit (LetStmt &stmt) override; + virtual void visit (LiteralExpr &expr) override; + virtual void visit (DereferenceExpr &expr) override; + + void collect_assignment (Pattern &pattern, bool has_init_expr); + void collect_assignment_identifier (IdentifierPattern &pattern, + bool has_init_expr); + void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr); + + void check_variable (IdentifierPattern *pattern, location_t assigned_loc); + + bool is_mutable_type (TyTy::BaseType *type); +}; -#endif // RUST_READONLY_CHECK +} // namespace HIR +} // namespace Rust
\ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-readonly-check2.cc b/gcc/rust/checks/errors/rust-readonly-check2.cc deleted file mode 100644 index 2fa92ae..0000000 --- a/gcc/rust/checks/errors/rust-readonly-check2.cc +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (C) 2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-readonly-check2.h" -#include "rust-hir-expr.h" -#include "rust-hir-node.h" -#include "rust-hir-path.h" -#include "rust-hir-map.h" -#include "rust-hir-pattern.h" -#include "rust-mapping-common.h" -#include "rust-system.h" -#include "rust-immutable-name-resolution-context.h" -#include "rust-tyty.h" - -namespace Rust { -namespace HIR { - -static std::set<HirId> already_assigned_variables = {}; - -ReadonlyChecker::ReadonlyChecker () - : resolver (*Resolver::Resolver::get ()), - mappings (Analysis::Mappings::get ()), - context (*Resolver::TypeCheckContext::get ()) -{} - -void -ReadonlyChecker::go (Crate &crate) -{ - for (auto &item : crate.get_items ()) - item->accept_vis (*this); -} - -void -ReadonlyChecker::visit (AssignmentExpr &expr) -{ - Expr &lhs = expr.get_lhs (); - mutable_context.enter (expr.get_mappings ().get_hirid ()); - lhs.accept_vis (*this); - mutable_context.exit (); -} - -void -ReadonlyChecker::visit (PathInExpression &expr) -{ - if (!mutable_context.is_in_context ()) - return; - - NodeId ast_node_id = expr.get_mappings ().get_nodeid (); - NodeId def_id; - - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id = nr_ctx.lookup (ast_node_id)) - def_id = *id; - else - return; - - auto hir_id = mappings.lookup_node_to_hir (def_id); - if (!hir_id) - return; - - // Check if the local variable is mutable. - auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id); - if (maybe_pattern - && maybe_pattern.value ()->get_pattern_type () - == HIR::Pattern::PatternType::IDENTIFIER) - check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()), - expr.get_locus ()); - - // Check if the static item is mutable. - auto maybe_item = mappings.lookup_hir_item (*hir_id); - if (maybe_item - && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static) - { - auto static_item = static_cast<HIR::StaticItem *> (*maybe_item); - if (!static_item->is_mut ()) - rust_error_at (expr.get_locus (), - "assignment of read-only location '%s'", - static_item->get_identifier ().as_string ().c_str ()); - } - - // Check if the constant item is mutable. - if (maybe_item - && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant) - { - auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item); - rust_error_at (expr.get_locus (), "assignment of read-only location '%s'", - const_item->get_identifier ().as_string ().c_str ()); - } -} - -void -ReadonlyChecker::check_variable (IdentifierPattern *pattern, - location_t assigned_loc) -{ - if (!mutable_context.is_in_context ()) - return; - if (pattern->is_mut ()) - return; - - auto hir_id = pattern->get_mappings ().get_hirid (); - if (already_assigned_variables.count (hir_id) > 0) - rust_error_at (assigned_loc, "assignment of read-only variable '%s'", - pattern->as_string ().c_str ()); - already_assigned_variables.insert (hir_id); -} - -void -ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern, - bool has_init_expr) -{ - if (has_init_expr) - { - HirId pattern_id = pattern.get_mappings ().get_hirid (); - already_assigned_variables.insert (pattern_id); - } -} - -void -ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern, - bool has_init_expr) -{ - switch (tuple_pattern.get_items ().get_item_type ()) - { - case HIR::TuplePatternItems::ItemType::MULTIPLE: - { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - tuple_pattern.get_items ()); - for (auto &sub : items.get_patterns ()) - { - collect_assignment (*sub, has_init_expr); - } - } - break; - default: - break; - } -} - -void -ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr) -{ - switch (pattern.get_pattern_type ()) - { - case HIR::Pattern::PatternType::IDENTIFIER: - { - collect_assignment_identifier (static_cast<IdentifierPattern &> ( - pattern), - has_init_expr); - } - break; - case HIR::Pattern::PatternType::TUPLE: - { - auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern); - collect_assignment_tuple (tuple_pattern, has_init_expr); - } - break; - default: - break; - } -} - -void -ReadonlyChecker::visit (LetStmt &stmt) -{ - HIR::Pattern &pattern = stmt.get_pattern (); - collect_assignment (pattern, stmt.has_init_expr ()); -} - -void -ReadonlyChecker::visit (FieldAccessExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_receiver_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (TupleIndexExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_tuple_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (ArrayIndexExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_array_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (TupleExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - // TODO: Add check for tuple expression - } -} - -void -ReadonlyChecker::visit (LiteralExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } -} - -void -ReadonlyChecker::visit (DereferenceExpr &expr) -{ - if (!mutable_context.is_in_context ()) - return; - TyTy::BaseType *to_deref_type; - auto to_deref = expr.get_expr ().get_mappings ().get_hirid (); - if (!context.lookup_type (to_deref, &to_deref_type)) - return; - if (to_deref_type->get_kind () == TyTy::TypeKind::REF) - { - auto ref_type = static_cast<TyTy::ReferenceType *> (to_deref_type); - if (!ref_type->is_mutable ()) - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } - if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER) - { - auto ptr_type = static_cast<TyTy::PointerType *> (to_deref_type); - if (!ptr_type->is_mutable ()) - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } -} -} // namespace HIR -} // namespace Rust diff --git a/gcc/rust/checks/errors/rust-readonly-check2.h b/gcc/rust/checks/errors/rust-readonly-check2.h deleted file mode 100644 index 06af9db..0000000 --- a/gcc/rust/checks/errors/rust-readonly-check2.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-hir-visitor.h" -#include "rust-name-resolver.h" -#include "rust-stacked-contexts.h" -#include "rust-hir-type-check.h" - -namespace Rust { -namespace HIR { -class ReadonlyChecker : public DefaultHIRVisitor -{ -public: - ReadonlyChecker (); - - void go (HIR::Crate &crate); - -private: - enum class lvalue_use - { - assign, - increment, - decrement, - }; - - Resolver::Resolver &resolver; - Analysis::Mappings &mappings; - Resolver::TypeCheckContext &context; - StackedContexts<HirId> mutable_context; - - using DefaultHIRVisitor::visit; - - virtual void visit (AssignmentExpr &expr) override; - virtual void visit (PathInExpression &expr) override; - virtual void visit (FieldAccessExpr &expr) override; - virtual void visit (ArrayIndexExpr &expr) override; - virtual void visit (TupleExpr &expr) override; - virtual void visit (TupleIndexExpr &expr) override; - virtual void visit (LetStmt &stmt) override; - virtual void visit (LiteralExpr &expr) override; - virtual void visit (DereferenceExpr &expr) override; - - void collect_assignment (Pattern &pattern, bool has_init_expr); - void collect_assignment_identifier (IdentifierPattern &pattern, - bool has_init_expr); - void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr); - - void check_variable (IdentifierPattern *pattern, location_t assigned_loc); -}; - -} // namespace HIR -} // namespace Rust
\ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index 405c59b..607d20f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -926,11 +926,11 @@ UnsafeChecker::visit (StructPattern &) {} void -UnsafeChecker::visit (TupleStructItemsNoRange &) +UnsafeChecker::visit (TupleStructItemsNoRest &) {} void -UnsafeChecker::visit (TupleStructItemsRange &) +UnsafeChecker::visit (TupleStructItemsHasRest &) {} void @@ -938,11 +938,11 @@ UnsafeChecker::visit (TupleStructPattern &) {} void -UnsafeChecker::visit (TuplePatternItemsMultiple &) +UnsafeChecker::visit (TuplePatternItemsNoRest &) {} void -UnsafeChecker::visit (TuplePatternItemsRanged &) +UnsafeChecker::visit (TuplePatternItemsHasRest &) {} void @@ -950,6 +950,14 @@ UnsafeChecker::visit (TuplePattern &) {} void +UnsafeChecker::visit (SlicePatternItemsNoRest &) +{} + +void +UnsafeChecker::visit (SlicePatternItemsHasRest &) +{} + +void UnsafeChecker::visit (SlicePattern &) {} diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h index dc3b482..420668f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.h +++ b/gcc/rust/checks/errors/rust-unsafe-checker.h @@ -161,12 +161,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/lints/rust-lint-marklive-base.h b/gcc/rust/checks/lints/rust-lint-marklive-base.h index 2a97577..dec9396 100644 --- a/gcc/rust/checks/lints/rust-lint-marklive-base.h +++ b/gcc/rust/checks/lints/rust-lint-marklive-base.h @@ -19,9 +19,6 @@ #ifndef RUST_HIR_LIVENESS_BASE #define RUST_HIR_LIVENESS_BASE -#include "rust-diagnostics.h" -#include "rust-lint-marklive.h" -#include "rust-lint-marklive-base.h" #include "rust-hir-visitor.h" #include "rust-hir-map.h" diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 58d8071..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; } @@ -2062,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 @@ -2374,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 ())) @@ -2383,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 @@ -2396,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 @@ -2429,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); @@ -2444,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); diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h index 767cf28..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,11 +174,11 @@ 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; @@ -194,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 321fa00..27dcc66 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -64,11 +64,10 @@ DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr) 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 (tl::nullopt, - /* 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 */ {}, @@ -211,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 ( diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc index 22ca16f..9890bb7 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.cc +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -101,9 +101,9 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw) auto other_variant_path = builder.variant_path (enum_path, 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 ( @@ -114,7 +114,7 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw) other_variant_path, std::move (other_pattern_items))), false, false, builder.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 @@ -176,7 +176,7 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw) std::move (other_elts))), false, false, builder.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 diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc index 7da137f..17332a4 100644 --- a/gcc/rust/expand/rust-derive-eq.cc +++ b/gcc/rust/expand/rust-derive-eq.cc @@ -128,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)); diff --git a/gcc/rust/expand/rust-derive-hash.cc b/gcc/rust/expand/rust-derive-hash.cc index 94aede2..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))), diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index afc4b71..6f3981f 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -120,7 +120,7 @@ DeriveOrd::make_equal () if (ordering == Ordering::Partial) { auto pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (vec (std::move (equal)))); + new TupleStructItemsNoRest (vec (std::move (equal)))); equal = std::make_unique<TupleStructPattern> (builder.path_in_expression ( diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index a0bf87a..287d8a7 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -146,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); @@ -186,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 ( @@ -199,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); @@ -254,7 +254,7 @@ DerivePartialEq::match_enum_struct (PathInExpression variant_path, variant_path, loc, std::move (other_elts))), 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); diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 10c146c..d28bba9 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -192,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{}; @@ -224,11 +223,11 @@ 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{}; @@ -262,4 +261,4 @@ private: } // 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-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 8f6e7fa..4593cc3 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -18,6 +18,7 @@ #include "rust-expand-visitor.h" #include "rust-ast-fragment.h" +#include "rust-item.h" #include "rust-proc-macro.h" #include "rust-attributes.h" #include "rust-ast.h" @@ -62,7 +63,7 @@ derive_item (AST::Item &item, AST::SimplePath &to_derive, { switch (node.get_kind ()) { - case AST::SingleASTNode::ITEM: + case AST::SingleASTNode::Kind::Item: result.push_back (node.take_item ()); break; default: @@ -85,7 +86,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 +115,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: @@ -329,10 +330,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 ()) @@ -342,14 +348,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 @@ -424,6 +470,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 ()); } @@ -465,6 +513,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 @@ -542,12 +598,6 @@ 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 ()); @@ -569,6 +619,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 ()); @@ -602,20 +659,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 @@ -677,22 +725,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 @@ -838,15 +874,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 ()) @@ -970,13 +997,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 ()); @@ -1006,10 +1090,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 845e10c..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" @@ -35,27 +37,48 @@ bool is_derive (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 @@ -128,7 +151,10 @@ public: 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 (); @@ -210,17 +236,16 @@ public: void visit (AST::AttrInputMacro &) override; void visit (AST::MetaItemLitExpr &) override; void visit (AST::MetaItemPathExpr &) override; - void visit (AST::ErrorPropagationExpr &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::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; @@ -231,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; @@ -251,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; @@ -269,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> @@ -287,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 61222db..c991ca7 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -101,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 { @@ -787,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 (); @@ -880,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 = {}; @@ -1124,8 +1125,11 @@ parse_llvm_clobbers (LlvmAsmContext &ctx) { ctx.llvm_asm.get_clobbers ().push_back ( {strip_double_quotes (token->as_string ()), token->get_locus ()}); + + parser.skip_token (STRING_LITERAL); } - parser.skip_token (STRING_LITERAL); + + parser.maybe_skip_token (COMMA); token = parser.peek_current_token (); } } @@ -1177,12 +1181,13 @@ parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc, auto asm_ctx = LlvmAsmContext (llvm_asm, parser, last_token_id); - auto resulting_context + tl::optional<LlvmAsmContext> resulting_context = parse_llvm_templates (asm_ctx).and_then (parse_llvm_arguments); if (resulting_context) { - auto node = (*resulting_context).llvm_asm.clone_expr_without_block (); + auto resulting_ctx = resulting_context.value (); + auto node = resulting_ctx.llvm_asm.clone_expr_without_block (); std::vector<AST::SingleASTNode> single_vec = {}; @@ -1190,12 +1195,13 @@ parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc, // need to make it a statement. This way, it will be expanded // properly. if (semicolon == AST::InvocKind::Semicoloned) - single_vec.emplace_back (AST::SingleASTNode ( - std::make_unique<AST::ExprStmt> (std::move (node), invoc_locus, - 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 (AST::SingleASTNode (std::move (node))); + single_vec.emplace_back (std::move (node)); AST::Fragment fragment_ast = AST::Fragment (single_vec, diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc index b20c849..eb2a1cc 100644 --- a/gcc/rust/expand/rust-macro-builtins-format-args.cc +++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc @@ -37,39 +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); - - // 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; + std::unique_ptr<AST::Expr> format_expr = parser.parse_expr (); + rust_assert (format_expr); - // TODO: Handle the case where we're not parsing a string literal (macro - // invocation for e.g.) - switch (parser.peek_current_token ()->get_id ()) + if (format_expr->get_expr_kind () == AST::Expr::Kind::MacroInvocation) { - case STRING_LITERAL: - case RAW_STRING_LITERAL: - format_expr = parser.parse_literal_expr (); - default: - // do nothing - ; + 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))); } - rust_assert (format_expr); - // 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 @@ -126,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> @@ -135,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!()%>"); @@ -173,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'; @@ -189,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.h b/gcc/rust/expand/rust-macro-builtins-helpers.h index 32cf58f..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" diff --git a/gcc/rust/expand/rust-macro-builtins-offset-of.cc b/gcc/rust/expand/rust-macro-builtins-offset-of.cc index 53efe74..02c637b 100644 --- a/gcc/rust/expand/rust-macro-builtins-offset-of.cc +++ b/gcc/rust/expand/rust-macro-builtins-offset-of.cc @@ -56,7 +56,7 @@ MacroBuiltin::offset_of_handler (location_t invoc_locus, parser.skip_token (COMMA); auto field_tok = parser.parse_identifier_or_keyword_token (); - auto invalid_field = !field_tok || !field_tok->has_str (); + 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", diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index a7ae220..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" diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 4c54cef..52f8e2b 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -27,7 +27,6 @@ #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" @@ -961,9 +960,14 @@ transcribe_expression (Parser<MacroInvocLexer> &parser) auto &lexer = parser.get_token_source (); auto start = lexer.get_offs (); - auto expr = parser.parse_expr (); + auto attrs = parser.parse_outer_attributes (); + auto expr = parser.parse_expr (std::move (attrs)); if (expr == nullptr) - return AST::Fragment::create_error (); + { + for (auto error : parser.get_errors ()) + error.emit (); + return AST::Fragment::create_error (); + } // FIXME: make this an error for some edititons if (parser.peek_current_token ()->get_id () == SEMICOLON) @@ -999,6 +1003,27 @@ transcribe_type (Parser<MacroInvocLexer> &parser) 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 (); + + 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, @@ -1011,6 +1036,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()] @@ -1039,6 +1065,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); @@ -1080,8 +1108,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 (); @@ -1128,11 +1157,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); @@ -1165,7 +1190,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: @@ -1174,7 +1199,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..c3d5e7d 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; diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index ac36ed8..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 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/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index b723f59..1c8e5b6 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -372,9 +372,6 @@ void ASTLoweringBase::visit (AST::StaticItem &) {} void -ASTLoweringBase::visit (AST::TraitItemConst &) -{} -void ASTLoweringBase::visit (AST::TraitItemType &) {} void @@ -473,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 &) @@ -622,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; } @@ -659,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; @@ -681,16 +675,15 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) { case AST::GenericArg::Kind::Type: { - auto type = ASTLoweringType::translate (arg.get_type ()); - type_args.emplace_back (std::unique_ptr<HIR::Type> (type)); + type_args.emplace_back ( + ASTLoweringType::translate (arg.get_type ())); break; } 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: @@ -850,9 +843,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, @@ -877,41 +871,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> @@ -1008,14 +1032,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 e86aacb..933f77b 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -189,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; @@ -228,12 +227,12 @@ 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; @@ -317,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-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 4ed51d9..a1e24ee 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -81,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 (), @@ -221,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 ( @@ -248,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 (), @@ -338,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 (), @@ -569,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 (), @@ -814,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 (), @@ -841,11 +836,10 @@ ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &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 (), @@ -1000,6 +994,23 @@ ASTLoweringExpr::visit (AST::InlineAsm &expr) 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) { @@ -1009,7 +1020,10 @@ ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr) 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 ()) { @@ -1029,13 +1043,15 @@ ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr) expr.is_stack_aligned (), expr.get_dialect ()}; - // We're not really supporting llvm_asm, only the bare minimum - // we're quite conservative here as the current code support more usecase. - rust_assert (outputs.size () == 0); - rust_assert (inputs.size () <= 1); - rust_assert (expr.get_clobbers ().size () <= 1); - rust_assert (expr.get_templates ().size () == 1); - rust_assert (expr.get_templates ()[0].symbol == ""); + 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, diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h index 3dca1b6..1f3ceda 100644 --- a/gcc/rust/hir/rust-ast-lower-extern.h +++ b/gcc/rust/hir/rust-ast-lower-extern.h @@ -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 5db11cb..8fd9d16 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.cc +++ b/gcc/rust/hir/rust-ast-lower-implitem.cc @@ -115,7 +115,7 @@ ASTLowerImplItem::visit (AST::Function &function) { 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)); @@ -162,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; @@ -272,10 +271,9 @@ 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 (std::move (hir_param)); + function_params.emplace_back (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); } if (func.has_self_param ()) @@ -320,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; 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 4e5a747..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)); @@ -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 ()); @@ -390,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 @@ -418,10 +416,41 @@ ASTLoweringItem::visit (AST::Function &function) : 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> ( @@ -434,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; @@ -446,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)); @@ -479,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 ()); @@ -540,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 ()); } @@ -563,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 ()); @@ -589,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 (); @@ -636,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 ()); @@ -690,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 ()) @@ -700,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 () diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index 8aabcd8..4250adb 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -81,26 +81,45 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case AST::TupleStructItems::RANGE: + case AST::TupleStructItems::HAS_REST: { - // TODO - rust_unreachable (); + 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: + case AST::TupleStructItems::NO_REST: { - AST::TupleStructItemsNoRange &items_no_range - = static_cast<AST::TupleStructItemsNoRange &> (items); + 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; } @@ -121,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 ()) @@ -196,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 (); @@ -204,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)); } @@ -223,21 +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: + case AST::TuplePatternItems::ItemType::NO_REST: { - AST::TuplePatternItemsMultiple &ref - = static_cast<AST::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + AST::TuplePatternItemsNoRest &ref + = static_cast<AST::TuplePatternItemsNoRest &> (pattern.get_items ()); items = lower_tuple_pattern_multiple (ref); } break; - case AST::TuplePatternItems::TuplePatternItemType::RANGED: + case AST::TuplePatternItems::ItemType::HAS_REST: { - AST::TuplePatternItemsRanged &ref - = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ()); + AST::TuplePatternItemsHasRest &ref + = static_cast<AST::TuplePatternItemsHasRest &> (pattern.get_items ()); items = lower_tuple_pattern_ranged (ref); } break; @@ -268,8 +286,6 @@ ASTLoweringPattern::visit (AST::LiteralPattern &pattern) 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 ()); @@ -278,9 +294,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 @@ -322,26 +340,22 @@ ASTLoweringPattern::visit (AST::ReferencePattern &pattern) void ASTLoweringPattern::visit (AST::SlicePattern &pattern) { - std::vector<std::unique_ptr<HIR::Pattern>> items; + std::unique_ptr<HIR::SlicePatternItems> items; - switch (pattern.get_items ().get_pattern_type ()) + switch (pattern.get_items ().get_item_type ()) { - case AST::SlicePatternItems::SlicePatternItemType::NO_REST: + case AST::SlicePatternItems::ItemType::NO_REST: { - AST::SlicePatternItemsNoRest &ref + auto &ref = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ()); - for (auto &p : ref.get_patterns ()) - { - HIR::Pattern *item = ASTLoweringPattern::translate (*p); - items.push_back (std::unique_ptr<HIR::Pattern> (item)); - } + items = ASTLoweringBase::lower_slice_pattern_no_rest (ref); } break; - case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: + case AST::SlicePatternItems::ItemType::HAS_REST: { - rust_error_at (pattern.get_locus (), - "lowering of slice patterns with rest elements are not " - "supported yet"); + auto &ref + = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ()); + items = ASTLoweringBase::lower_slice_pattern_has_rest (ref); } break; } @@ -364,12 +378,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.cc b/gcc/rust/hir/rust-ast-lower.cc index e6e327f..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 (); @@ -127,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) @@ -231,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 ()); @@ -241,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, @@ -255,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; @@ -265,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 @@ -442,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), @@ -457,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 (); @@ -490,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))); @@ -531,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-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index a0cdcb2..49ce143 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -2307,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 @@ -2337,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 @@ -2363,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"); } diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h index 3e6ae30..4dfc885 100644 --- a/gcc/rust/hir/rust-hir-dump.h +++ b/gcc/rust/hir/rust-hir-dump.h @@ -223,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; diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h index 57b3a4d..aec2f36 100644 --- a/gcc/rust/hir/tree/rust-hir-full-decls.h +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -199,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-item.h b/gcc/rust/hir/tree/rust-hir-item.h index d9df602..eb9cec7 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -452,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; } }; diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 9c636ca..89b9cc6 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -350,6 +350,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 +360,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 +371,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 +381,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 +397,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 +683,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 +693,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 +712,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 +722,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 +791,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 +818,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 +855,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 +866,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 +879,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 +917,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 +933,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 +960,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 +1040,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 +1073,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 +1084,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 +1103,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 +1137,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 +1153,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 +1184,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 +1251,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 +1413,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 +1437,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-visitor.cc b/gcc/rust/hir/tree/rust-hir-visitor.cc index 58c1e1a..1e201a5 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.cc +++ b/gcc/rust/hir/tree/rust-hir-visitor.cc @@ -1023,14 +1023,14 @@ DefaultHIRVisitor::walk (StructPattern &pattern) } void -DefaultHIRVisitor::walk (TupleStructItemsNoRange &tuple_items) +DefaultHIRVisitor::walk (TupleStructItemsNoRest &tuple_items) { for (auto &item : tuple_items.get_patterns ()) item->accept_vis (*this); } void -DefaultHIRVisitor::walk (TupleStructItemsRange &tuple_items) +DefaultHIRVisitor::walk (TupleStructItemsHasRest &tuple_items) { for (auto &lower : tuple_items.get_lower_patterns ()) lower->accept_vis (*this); @@ -1046,14 +1046,14 @@ DefaultHIRVisitor::walk (TupleStructPattern &pattern) } void -DefaultHIRVisitor::walk (TuplePatternItemsMultiple &tuple_items) +DefaultHIRVisitor::walk (TuplePatternItemsNoRest &tuple_items) { for (auto &pattern : tuple_items.get_patterns ()) pattern->accept_vis (*this); } void -DefaultHIRVisitor::walk (TuplePatternItemsRanged &tuple_items) +DefaultHIRVisitor::walk (TuplePatternItemsHasRest &tuple_items) { for (auto &lower : tuple_items.get_lower_patterns ()) lower->accept_vis (*this); @@ -1068,10 +1068,25 @@ DefaultHIRVisitor::walk (TuplePattern &pattern) } 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) { - for (auto &item : pattern.get_items ()) - item->accept_vis (*this); + pattern.get_items ().accept_vis (*this); } void diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 7996260..77760b0 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -132,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; @@ -305,12 +307,14 @@ public: } virtual void visit (StructPatternFieldIdent &node) override { walk (node); } virtual void visit (StructPattern &node) override { walk (node); } - virtual void visit (TupleStructItemsNoRange &node) override { walk (node); } - virtual void visit (TupleStructItemsRange &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 (TuplePatternItemsMultiple &node) override { walk (node); } - virtual void visit (TuplePatternItemsRanged &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); } @@ -438,12 +442,14 @@ protected: virtual void walk (StructPatternFieldIdentPat &) final; virtual void walk (StructPatternFieldIdent &) final; virtual void walk (StructPattern &) final; - virtual void walk (TupleStructItemsNoRange &) final; - virtual void walk (TupleStructItemsRange &) final; + virtual void walk (TupleStructItemsNoRest &) final; + virtual void walk (TupleStructItemsHasRest &) final; virtual void walk (TupleStructPattern &) final; - virtual void walk (TuplePatternItemsMultiple &) final; - virtual void walk (TuplePatternItemsRanged &) 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; @@ -586,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 {} diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index a802e8c..ce10b02 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -2239,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 @@ -2281,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), @@ -2387,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 (); } @@ -2400,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: "); @@ -2413,7 +2452,7 @@ AltPattern::as_string () const } std::string -TuplePatternItemsMultiple::as_string () const +TuplePatternItemsNoRest::as_string () const { std::string str; @@ -2426,7 +2465,7 @@ TuplePatternItemsMultiple::as_string () const } std::string -TuplePatternItemsRanged::as_string () const +TuplePatternItemsHasRest::as_string () const { std::string str; @@ -2480,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; } @@ -2620,7 +2678,7 @@ IdentifierPattern::as_string () const } std::string -TupleStructItemsNoRange::as_string () const +TupleStructItemsNoRest::as_string () const { std::string str; @@ -2633,7 +2691,7 @@ TupleStructItemsNoRange::as_string () const } std::string -TupleStructItemsRange::as_string () const +TupleStructItemsHasRest::as_string () const { std::string str ("\n Lower patterns: "); @@ -4471,13 +4529,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); } @@ -4489,13 +4547,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); } @@ -4507,6 +4565,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); diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 76ff15c..214161f 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'; } diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index c396e10..43682af 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -178,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 { diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index 2021aec..71a7503 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -22,6 +22,7 @@ #include "rust-system.h" #include "rust-linemap.h" #include "rust-unicode.h" +#include "rust-diagnostics.h" namespace Rust { @@ -249,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. */ @@ -257,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 } @@ -283,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: @@ -322,7 +319,7 @@ 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))); @@ -331,7 +328,7 @@ public: 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); @@ -340,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); @@ -349,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); @@ -372,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))); @@ -413,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 @@ -464,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 1829a85..4dfc280 100644 --- a/gcc/rust/metadata/rust-export-metadata.cc +++ b/gcc/rust/metadata/rust-export-metadata.cc @@ -91,8 +91,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), diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 14bccbd..ec4c1c1 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1053,6 +1053,7 @@ Parser<ManagedTokenSource>::parse_identifier_or_keyword_token () } else { + add_error (Error (t->get_locus (), "expected keyword or identifier")); return nullptr; } } @@ -1716,10 +1717,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), @@ -3316,8 +3316,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params () break; } - lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> ( - new AST::LifetimeParam (std::move (lifetime_param.value ())))); + lifetime_params.emplace_back ( + new AST::LifetimeParam (std::move (lifetime_param.value ()))); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3356,8 +3356,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; @@ -5219,7 +5219,7 @@ Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs, // 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 (); @@ -5257,10 +5257,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 @@ -10484,16 +10483,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)); @@ -10812,9 +10817,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)); @@ -10822,8 +10827,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)); @@ -10887,8 +10892,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)); } @@ -10928,9 +10933,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)); } @@ -11113,7 +11118,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 (), @@ -11240,7 +11245,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () // 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 ( @@ -11325,9 +11331,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 @@ -11369,8 +11375,8 @@ 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))); + 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 @@ -11402,9 +11408,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 @@ -11424,7 +11430,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 (); @@ -11437,7 +11443,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems () { lexer.skip_token (); etc_attrs = std::move (outer_attrs); - has_etc = true; + has_rest = true; break; } @@ -11462,7 +11468,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 @@ -11761,6 +11767,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)) { @@ -11772,9 +11780,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 ( @@ -12149,20 +12160,12 @@ 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); return left_denotations (std::move (expr), right_binding_power, std::move (outer_attrs), restrictions); @@ -12230,8 +12233,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 @@ -12241,6 +12243,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: @@ -12249,28 +12253,26 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, case DOLLAR_SIGN: case CRATE: 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); } @@ -13035,12 +13037,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", @@ -14436,119 +14432,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> @@ -14686,35 +14569,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.h b/gcc/rust/parse/rust-parse.h index 8253885..7b40463 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -212,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 (); @@ -228,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> @@ -368,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 (); @@ -393,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, @@ -598,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 ()); @@ -782,7 +785,7 @@ private: // don't want to make things *only* AttributeParser uses public // TODO: fold more of AttributeParser into Parser? - friend class ::Rust::AST::AttributeParser; + friend struct ::Rust::AST::AttributeParser; }; std::string extract_module_path (const AST::AttrVec &inner_attrs, 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 3c7b425..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ /dev/null @@ -1,691 +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::MetaItemPathExpr &) -{} - -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::AnonConst &) -{} - -void -ResolverBase::visit (AST::ConstBlock &) -{} - -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::TryExpr &) -{} - -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::LlvmInlineAsm &) -{} - -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::SlicePatternItemsNoRest &) -{} - -void -ResolverBase::visit (AST::SlicePatternItemsHasRest &) -{} - -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) -{} - -void -ResolverBase::visit (AST::OffsetOf &offset_of) -{} - -} // 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 89c5c35..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ /dev/null @@ -1,238 +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-builtin-ast-nodes.h" -#include "rust-expr.h" -#include "rust-name-resolver.h" -#include "rust-diagnostics.h" -#include "rust-location.h" - -namespace Rust { -namespace Resolver { -inline void -redefined_error (const rich_location &loc) -{ - rust_error_at (loc, "redefined multiple times"); -} - -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::MetaItemPathExpr &); - 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::AnonConst &); - void visit (AST::ConstBlock &); - 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::TryExpr &); - 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::LlvmInlineAsm &); - - 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::SlicePatternItemsNoRest &); - void visit (AST::SlicePatternItemsHasRest &); - 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); - void visit (AST::OffsetOf &offset_of); - -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 a410193..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ /dev/null @@ -1,816 +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. */ - diagnostics::text_finalizer (global_dc) = 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 ()); - } - 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 -ResolveExpr::visit (AST::AnonConst &expr) -{ - ResolveExpr::go (expr.get_inner_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ConstBlock &expr) -{ - ResolveExpr::go (expr.get_const_expr (), prefix, canonical_prefix); -} - -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.get_inner_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::LlvmInlineAsm &expr) -{ - for (auto &output : expr.get_outputs ()) - ResolveExpr::go (*output.expr, prefix, canonical_prefix); - - for (auto &input : expr.get_inputs ()) - ResolveExpr::go (*input.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_unchecked ().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", - label.as_string ().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_unchecked (); - 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_unchecked ().get_locus (), - ErrorCode::E0426, "use of undeclared label %qs", - label.as_string ().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_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::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 aad1605..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ /dev/null @@ -1,105 +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::AnonConst &expr) override; - void visit (AST::ConstBlock &expr) override; - void visit (AST::InlineAsm &expr) override; - void visit (AST::LlvmInlineAsm &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 2081697..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ /dev/null @@ -1,260 +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); - redefined_error (r); - }); - } - - 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); - redefined_error (r); - }); - } - - 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); - redefined_error (r); - }); - } - -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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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 1d5ebed..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ /dev/null @@ -1,1247 +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); - - ResolveExpr::go (item.get_expr (), path, 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 ()); - if (constant.has_expr ()) - 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 - { - cpath = canonical_prefix.append (impl_type_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 - { - cpath = canonical_prefix.append (canonical_projection); - } - - // 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 d31f910..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ /dev/null @@ -1,161 +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 fb6715d..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, - "%qs in paths can only be used in start position", - 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 (), ErrorCode::E0433, - "%<super%> in paths 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 3b80f9f..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ /dev/null @@ -1,419 +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) -{ - if (pattern.has_subpattern ()) - { - pattern.get_subpattern ().accept_vis (*this); - } - - 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) -{ - auto &items = pattern.get_items (); - switch (items.get_pattern_type ()) - { - case AST::SlicePatternItems::SlicePatternItemType::NO_REST: - { - auto &ref - = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ()); - - for (auto &p : ref.get_patterns ()) - p->accept_vis (*this); - } - break; - - case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: - { - auto &ref - = static_cast<AST::SlicePatternItemsHasRest &> (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; - } -} - -} // 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 bfba302..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); - redefined_error (r); - }); - - 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 d714511..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ /dev/null @@ -1,408 +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); - redefined_error (r); - }); - - ResolveType::go (constant.get_type ()); - if (constant.has_expr ()) - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - // 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - // 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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 f52fb8a..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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }; - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - - 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); - redefined_error (r); - }); - } - -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 a040228..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.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-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 ().get ()); -} - -// 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, - "%qs in paths can only be used in start position", - 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->get_ident_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 f1481fc..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_unchecked ().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 2208f70..0000000 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ /dev/null @@ -1,114 +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-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 4fd1dd2..0dff831 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -438,7 +438,9 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) // 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 @@ -447,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 ()) @@ -459,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 ()) @@ -484,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 960de0e..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 { 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 7b365ef..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::MetaItemPathExpr &) -{} - -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 d3c5225..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::MetaItemPathExpr &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-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 1ed87b3..848f5e6 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -531,7 +531,7 @@ ForeverStack<N>::resolve_segments ( || 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 @@ -583,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 ()); @@ -611,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); } 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 e39ca15..96b38f4 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -24,6 +24,7 @@ #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" @@ -38,84 +39,10 @@ Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx), funny_error (false), block_big_self (false) {} -static NodeId -next_node_id () -{ - return Analysis::Mappings::get ().get_next_node_id (); -}; - -static HirId -next_hir_id () -{ - return Analysis::Mappings::get ().get_next_hir_id (); -}; - -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); -} - void Late::go (AST::Crate &crate) { - setup_builtin_types (); + Builtins::setup_type_ctx (); visit (crate); } @@ -521,20 +448,22 @@ Late::visit_impl_type (AST::Type &type) block_big_self = false; } -void -Late::visit (AST::TypePath &type) +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); - // prevent "impl Self {}" and similar if (type.get_segments ().size () == 1 - && !type.get_segments ().front ()->is_lang_item () - && type.get_segments ().front ()->is_big_self_seg () && block_big_self) + && !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"); @@ -547,17 +476,17 @@ Late::visit (AST::TypePath &type) if (!resolved.has_value ()) { - if (!ctx.lookup (type.get_segments ().front ()->get_node_id ())) + 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", - type.make_debug_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } if (resolved->is_ambiguous ()) { rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous", - type.make_debug_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } @@ -574,6 +503,14 @@ Late::visit (AST::TypePath &type) } 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 ()) @@ -649,10 +586,7 @@ Late::visit (AST::StructExprStruct &s) visit_inner_attrs (s); DefaultResolver::visit (s.get_struct_name ()); - auto resolved = ctx.resolve_path (s.get_struct_name (), 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 @@ -663,10 +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 (), 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 @@ -680,10 +611,7 @@ Late::visit (AST::StructExprStructFields &s) for (auto &field : s.get_fields ()) visit (field); - auto resolved = ctx.resolve_path (s.get_struct_name (), 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 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 95540e3..608ae38 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -75,9 +75,6 @@ public: private: void resolve_label (AST::Lifetime &lifetime); - /* Setup Rust's builtin types (u8, i32, !...) in the resolver */ - void setup_builtin_types (); - bool funny_error; /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */ 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/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 398dea1..8f950d17 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1258,7 +1258,7 @@ constructor_expression (tree type_tree, bool is_variant, 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; diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index 93ce041..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" @@ -442,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-session-manager.cc b/gcc/rust/rust-session-manager.cc index 17f9c06..6418118 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -29,7 +29,6 @@ #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" @@ -46,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" @@ -422,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; @@ -551,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 (); @@ -563,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 @@ -613,13 +612,13 @@ Session::compile_crate (const char *filename) if (last_step == CompileOptions::CompileStep::Expansion) return; - AST::CollectLangItems ().go (parsed_crate); - auto name_resolution_ctx = Resolver2_0::NameResolutionContext (); // expansion pipeline stage expansion (parsed_crate, name_resolution_ctx); + 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); @@ -738,7 +734,7 @@ Session::compile_crate (const char *filename) // lints Analysis::ScanDeadcode::Scan (hir); Analysis::UnusedVariables::Lint (*ctx); - Analysis::ReadonlyCheck::Lint (*ctx); + HIR::ReadonlyChecker ().go (hir); // metadata bool specified_emit_metadata @@ -758,6 +754,9 @@ Session::compile_crate (const char *filename) } } + if (saw_errors ()) + return; + // pass to GCC middle-end ctx->write_to_backend (); } @@ -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++; @@ -993,8 +987,7 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) // 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 - if (flag_name_resolution_2_0) - Resolver2_0::TopLevel (ctx).go (crate); + Resolver2_0::TopLevel (ctx).go (crate); } // error reporting - check unused macros, get missing fragment specifiers @@ -1190,14 +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); - // if flag_name_resolution_2_0 is enabled - // then we perform resolution later - if (!flag_name_resolution_2_0) - { - // name resolve it - Resolver::NameResolution::Resolve (parsed_crate); - } - // always restore the crate_num mappings.set_current_crate (saved_crate_num); diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc index 10a59bd..8cc2b7b 100644 --- a/gcc/rust/typecheck/rust-autoderef.cc +++ b/gcc/rust/typecheck/rust-autoderef.cc @@ -425,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; @@ -436,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 f06d9ed..7d08601 100644 --- a/gcc/rust/typecheck/rust-casts.cc +++ b/gcc/rust/typecheck/rust-casts.cc @@ -277,6 +277,7 @@ TypeCastRules::cast_rules () break; case TyTy::TypeKind::REF: + case TyTy::TypeKind::FNPTR: case TyTy::TypeKind::POINTER: switch (to.get_ty ()->get_kind ()) { @@ -286,8 +287,9 @@ TypeCastRules::cast_rules () 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{ diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc index fd12839..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 ()); @@ -127,15 +88,14 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) { case TyTy::TypeKind::POINTER: { - TyTy::PointerType *ptr = static_cast<TyTy::PointerType *> (expected); + 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); + auto *ptr = expected->as<TyTy::ReferenceType> (); try_result = coerce_borrowed_pointer (receiver, ptr, ptr->mutability ()); return !try_result.is_error (); @@ -174,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) @@ -273,12 +271,9 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver, { case TyTy::TypeKind::REF: { - TyTy::ReferenceType *from - = static_cast<TyTy::ReferenceType *> (receiver); - from_mutbl = from->mutability (); + from_mutbl = receiver->as<TyTy::ReferenceType> ()->mutability (); } break; - default: { rust_debug ("coerce_borrowed_pointer -- unify"); @@ -318,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 ()); @@ -344,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 (); @@ -356,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) { @@ -369,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 (); @@ -381,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 @@ -401,17 +397,14 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, { 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) @@ -424,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; } @@ -432,7 +425,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, } adjustments.clear (); - return TypeCoercionRules::CoercionResult::get_error (); + return tl::unexpected<CoerceUnsizedError> (CoerceUnsizedError::Regular); } bool @@ -446,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 7b7944c..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 @@ -136,11 +139,11 @@ MethodResolver::assemble_inherent_impl_candidates ( 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); @@ -175,7 +178,7 @@ MethodResolver::assemble_inherent_impl_candidates ( return true; } - inherent_impl_fns.push_back ({func, impl, fnty}); + inherent_impl_fns.emplace_back (func, impl, fnty); return true; }); @@ -220,10 +223,11 @@ MethodResolver::assemble_trait_impl_candidates ( 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); @@ -259,7 +263,7 @@ MethodResolver::assemble_trait_impl_candidates ( continue; } - impl_candidates.push_back ({func, impl, fnty}); + impl_candidates.emplace_back (func, impl, fnty); return true; } @@ -282,11 +286,11 @@ MethodResolver::assemble_trait_impl_candidates ( 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_candidates.push_back (candidate); + trait_candidates.emplace_back (func, trait, fnty, trait_ref, item_ref); return true; }); @@ -299,7 +303,8 @@ MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver) 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,7 +351,8 @@ MethodResolver::try_select_inherent_impl_candidates ( 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 (); @@ -384,7 +390,8 @@ MethodResolver::try_select_trait_impl_candidates ( 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}", @@ -464,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 cc40472..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; }; @@ -67,6 +71,11 @@ public: 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; @@ -74,6 +83,13 @@ public: 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; diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc index c02702f..59118e6 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.cc +++ b/gcc/rust/typecheck/rust-hir-path-probe.cc @@ -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; } diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index 0fd0147..03121d1 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -224,8 +224,7 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) 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) { @@ -247,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; @@ -291,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 ()); @@ -553,9 +554,9 @@ AssociatedImplTrait::setup_associated_types ( 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; @@ -579,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 { auto param = p.get_param_ty (); auto resolved = param->destructure (); - subst_args.push_back (TyTy::SubstitutionArg (&p, resolved)); + subst_args.emplace_back (&p, resolved); param_mappings[param->get_symbol ()] = resolved->get_ref (); } } diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h index 5384700..392ff20 100644 --- a/gcc/rust/typecheck/rust-hir-type-bounds.h +++ b/gcc/rust/typecheck/rust-hir-type-bounds.h @@ -30,7 +30,7 @@ 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); @@ -46,9 +46,9 @@ private: 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 68001bf..f878720 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -56,7 +56,9 @@ walk_types_to_constrain (std::set<HirId> &constrained_symbols, if (arg != nullptr) { 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, @@ -66,6 +68,83 @@ 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, @@ -87,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; @@ -296,17 +367,17 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, tree capacity = Compile::HIRCompileBase::query_compile_const_expr ( ctx, expected_ty, *literal_capacity); - TyTy::ConstType *capacity_expr - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", - expected_ty, capacity, {}, - literal_capacity->get_locus (), - literal_capacity->get_mappings ().get_hirid (), - literal_capacity->get_mappings ().get_hirid (), - {}); - - TyTy::ArrayType *array - = new TyTy::ArrayType (array_mapping.get_hirid (), locus, - capacity_expr, TyTy::TyVar (u8->get_ref ())); + 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 (), @@ -341,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; } @@ -350,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 (); @@ -526,22 +601,21 @@ TypeCheckBase::resolve_generic_params ( = Compile::HIRCompileBase::query_compile_const_expr ( ctx, specified_type, expr); - TyTy::ConstType *default_const_decl - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - param.get_name (), specified_type, - default_value, {}, param.get_locus (), - expr.get_mappings ().get_hirid (), - expr.get_mappings ().get_hirid (), {}); + 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); } - TyTy::ConstType *const_decl - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Decl, - param.get_name (), specified_type, - error_mark_node, {}, param.get_locus (), - param.get_mappings ().get_hirid (), - param.get_mappings ().get_hirid (), {}); + 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); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 438200b..7885dfc 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -34,6 +34,7 @@ #include "rust-immutable-name-resolution-context.h" #include "rust-compile-base.h" #include "rust-tyty-util.h" +#include "rust-tyty.h" #include "tree.h" namespace Rust { @@ -125,7 +126,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); @@ -160,7 +167,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); @@ -629,10 +636,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 ()); } } @@ -669,16 +675,9 @@ TypeCheckExpr::visit (HIR::AnonConst &expr) return; } - auto locus = expr.get_locus (); - auto infer_ty_var = TyTy::TyVar::get_implicit_infer_var (locus); - - HirId next = mappings.get_next_hir_id (); - infered = new TyTy::ConstType (TyTy::ConstType::ConstKind::Infer, "", - infer_ty_var.get_tyty (), error_mark_node, {}, - locus, next, next, {}); - - context->insert_implicit_type (infered->get_ref (), infered); - mappings.insert_location (infered->get_ref (), locus); + TyTy::TyVar var + = TyTy::TyVar::get_implicit_const_infer_var (expr.get_locus ()); + infered = var.get_tyty (); } void @@ -730,7 +729,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 (), @@ -774,7 +773,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 (), @@ -818,7 +817,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 (), @@ -991,7 +990,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 (), @@ -1091,15 +1090,19 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) auto capacity_expr_ty = TypeCheckExpr::Resolve (elems.get_num_copies_expr ()); + if (capacity_expr_ty->is<TyTy::ErrorType> ()) + return; context->insert_type (elems.get_num_copies_expr ().get_mappings (), expected_ty); - unify_site ( + 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; @@ -1152,14 +1155,23 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) tree capacity_value = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type, *capacity_expr); - HirId size_id = capacity_expr->get_mappings ().get_hirid (); - TyTy::ConstType *const_type - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", expected_ty, - capacity_value, {}, capacity_expr->get_locus (), - size_id, size_id); + + // 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 (), - const_type, TyTy::TyVar (element_type->get_ref ())); + TyTy::TyVar ( + const_type->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (element_type->get_ref ())); } // empty struct @@ -1888,7 +1900,7 @@ 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, false); @@ -1974,13 +1986,13 @@ TypeCheckExpr::resolve_operator_overload ( std::vector<TyTy::SubstitutionArg> mappings; auto &self_param_mapping = trait_subst[0]; - mappings.push_back (TyTy::SubstitutionArg (&self_param_mapping, lhs)); + mappings.emplace_back (&self_param_mapping, lhs); if (rhs != nullptr) { rust_assert (trait_subst.size () == 2); auto &rhs_param_mapping = trait_subst[1]; - mappings.push_back (TyTy::SubstitutionArg (&rhs_param_mapping, lhs)); + mappings.emplace_back (&rhs_param_mapping, lhs); } std::map<std::string, TyTy::BaseType *> binding_args; @@ -2033,24 +2045,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 @@ -2312,7 +2306,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 @@ -2325,9 +2319,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, diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index c8544a1..e7f6632 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -121,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); @@ -324,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 ()) @@ -335,8 +335,8 @@ 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); } auto &nr_ctx @@ -469,8 +469,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 @@ -519,8 +519,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 @@ -578,8 +578,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 3ba607b..4987c88a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -115,13 +115,13 @@ TypeCheckItem::ResolveImplBlockSelfWithInference ( 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 ())); + args.emplace_back (&p, infer_var.get_tyty ()); } else { auto param = p.get_param_ty (); auto resolved = param->destructure (); - args.push_back (TyTy::SubstitutionArg (&p, resolved)); + args.emplace_back (&p, resolved); } } @@ -554,8 +554,8 @@ 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 &nr_ctx diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index cc5c412..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 { @@ -517,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); } } diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index be926fc..7dae303 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -21,6 +21,8 @@ #include "rust-hir-type-check-expr.h" #include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" +#include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Resolver { @@ -160,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 @@ -200,33 +215,144 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { - // TODO - rust_unreachable (); + 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: + case HIR::TupleStructItems::NO_REST: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); + 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; @@ -299,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 ()); @@ -407,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; @@ -463,10 +613,10 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: + case HIR::TuplePatternItems::ItemType::NO_REST: { - auto &ref = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &ref + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); const auto &patterns = ref.get_patterns (); size_t nitems_to_resolve = patterns.size (); @@ -486,17 +636,17 @@ 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: + case HIR::TuplePatternItems::ItemType::HAS_REST: { - HIR::TuplePatternItemsRanged &ref - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + HIR::TuplePatternItemsHasRest &ref + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); const auto &lower = ref.get_lower_patterns (); const auto &upper = ref.get_upper_patterns (); @@ -507,37 +657,45 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) { emit_pattern_size_error (pattern, par.get_fields ().size (), min_size_required); - // TODO attempt to continue to do typechecking even after wrong size - break; + // continue and attempt to resolve individual items in the pattern } // Resolve lower patterns std::vector<TyTy::TyVar> pattern_elems; - for (size_t i = 0; i < lower.size (); i++) + 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.push_back (TyTy::TyVar (elem->get_ref ())); + 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 = par.get_fields ().size () - upper.size (); + 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.push_back (TyTy::TyVar (par_type->get_ref ())); + 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 < upper.size (); i++) + 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.push_back (TyTy::TyVar (elem->get_ref ())); + pattern_elems.emplace_back (elem->get_ref ()); } infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (), @@ -642,7 +800,32 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern) 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 = capacity->get_value (); + + 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 (), @@ -651,14 +834,45 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern) break; } auto cap_wi = wi::to_wide (cap).to_uhwi (); - if (cap_wi != pattern.get_items ().size ()) + + // size check during compile time + switch (pattern.get_items ().get_item_type ()) { - rust_error_at (pattern.get_locus (), ErrorCode::E0527, - "pattern requires %lu elements but array has %lu", - (unsigned long) pattern.get_items ().size (), - (unsigned long) cap_wi); + 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: @@ -694,10 +908,32 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern) infered->set_ref (pattern.get_mappings ().get_hirid ()); // Type check every item in the SlicePattern against parent's element ty - // TODO update this after adding support for RestPattern in SlicePattern - for (const auto &item : pattern.get_items ()) + switch (pattern.get_items ().get_item_type ()) { - TypeCheckPattern::Resolve (*item, parent_element_ty); + 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; + } } } @@ -814,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-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 4ef8348..eb44279 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -214,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); } } } @@ -245,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)); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 78037bd..799efc8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -97,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 @@ -118,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 (), @@ -207,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 (); @@ -261,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 { @@ -699,38 +706,47 @@ TypeCheckType::visit (HIR::ArrayType &type) rust_assert (ok); context->insert_type (type.get_size_expr ().get_mappings (), expected_ty); - TyTy::ConstType *const_type = nullptr; + TyTy::BaseConstType *const_type = nullptr; if (capacity_type->get_kind () == TyTy::TypeKind::CONST) { - const_type = static_cast<TyTy::ConstType *> (capacity_type); + const_type = capacity_type->as_const_type (); unify_site (type.get_size_expr ().get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty), - TyTy::TyWithLocation (const_type->get_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 (); - unify_site (size_id, TyTy::TyWithLocation (expected_ty), - TyTy::TyWithLocation (capacity_type, - type.get_size_expr ().get_locus ()), - type.get_size_expr ().get_locus ()); - - 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::ConstType (TyTy::ConstType::ConstKind::Value, "", - expected_ty, capacity_expr, {}, - type.get_size_expr ().get_locus (), - size_id, size_id); + 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 (), - const_type, TyTy::TyVar (element_type->get_ref ())); + TyTy::TyVar ( + const_type->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (element_type->get_ref ())); } void diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index aba4ab5..64f4314 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -260,7 +260,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 ()) @@ -270,8 +270,8 @@ 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 &nr_ctx diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc index c5b823e..238ede4 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.cc +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -268,12 +268,30 @@ SubstMapperInternal::visit (TyTy::ParamType &type) } void -SubstMapperInternal::visit (TyTy::ConstType &type) +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 ()); @@ -310,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 (); } diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 2389d83..98f9e72 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -61,7 +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::ConstType &) 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 (); } @@ -93,7 +96,10 @@ public: void visit (TyTy::ReferenceType &type) override; void visit (TyTy::PointerType &type) override; void visit (TyTy::ParamType &type) override; - void visit (TyTy::ConstType &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; @@ -147,13 +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::ConstType &) 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); @@ -188,7 +197,10 @@ public: void visit (const TyTy::ReferenceType &) override {} void visit (const TyTy::PointerType &) override {} void visit (const TyTy::ParamType &) override {} - void visit (const TyTy::ConstType &) 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/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index 2d66166..6f30ebf 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -152,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; } @@ -173,32 +174,34 @@ 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_loc ( - unify_locus, - "begin unify_site_and commit %s infer %s id={%u} expected={%s} expr={%s}", - 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 ()); + 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, @@ -228,7 +231,8 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, // 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; @@ -325,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 dd97f1e..7f4a94e 100644 --- a/gcc/rust/typecheck/rust-type-util.h +++ b/gcc/rust/typecheck/rust-type-util.h @@ -28,7 +28,8 @@ namespace Resolver { bool 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 = true); TyTy::BaseType *unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t unify_locus); @@ -37,7 +38,7 @@ 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 cleanup, bool check_bounds = true); TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, @@ -52,7 +53,7 @@ TyTy::BaseType *cast_site (HirId id, TyTy::TyWithLocation from, 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 c74a920..3419ef6 100644 --- a/gcc/rust/typecheck/rust-typecheck-context.cc +++ b/gcc/rust/typecheck/rust-typecheck-context.cc @@ -154,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 @@ -310,7 +310,7 @@ TypeCheckContext::insert_associated_impl_mapping (HirId trait_id, 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 diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 6cf9b04..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 (); @@ -75,22 +75,18 @@ TypeBoundsProbe::process_impl_block ( 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; - } + if (!types_compatable (TyTy::TyWithLocation (receiver), + TyTy::TyWithLocation (impl_type), impl->get_locus (), + false /*emit_errors*/, false /*check-bounds*/)) + return true; - possible_trait_paths.push_back ({&impl->get_trait_ref (), impl}); + possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl); return true; } @@ -110,7 +106,7 @@ 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... @@ -185,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 @@ -306,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*/, @@ -468,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 @@ -577,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); - const auto item_ref = item.get_raw_item (); + if (!item.has_value ()) + continue; + + const auto item_ref = item->get_raw_item (); item_ref->associated_type_set (type); } @@ -601,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 (); @@ -613,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 ( @@ -658,7 +655,7 @@ TypeBoundPredicateItem::get_parent () const return &parent; } -TypeBoundPredicateItem +tl::optional<TypeBoundPredicateItem> TypeBoundPredicate::lookup_associated_item ( const Resolver::TraitItemReference *ref) const { @@ -691,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, {}, @@ -735,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); } } @@ -802,18 +799,18 @@ TypeBoundPredicate::get_trait_hierachy ( 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> @@ -827,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; } diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 63bb1ff..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; @@ -327,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 9e4aab5..025a1ad 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -60,9 +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 (ConstType &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 c22dfdd..0000000 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ /dev/null @@ -1,1645 +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 ()); - } - } - - virtual void visit (const ConstType &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; -}; - -class ConstCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ConstCmp (const ConstType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - // TODO - -private: - const BaseType *get_base () const override { return base; } - - const ConstType *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 817910b..e82e8a3 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -54,8 +54,8 @@ SubstitutionParamMapping::as_string () const SubstitutionParamMapping SubstitutionParamMapping::clone () const { - return SubstitutionParamMapping (generic, - static_cast<ParamType *> (param->clone ())); + return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> ( + param->clone ())); } BaseGeneric * @@ -167,7 +167,12 @@ SubstitutionParamMapping::fill_param_ty ( } else if (type.get_kind () == TyTy::TypeKind::CONST) { - param = static_cast<BaseGeneric *> (type.clone ()); + 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) { @@ -554,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 ()); @@ -767,7 +773,7 @@ SubstitutionRef::get_mappings_from_generic_args ( } else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST) { - if (!resolved->is<ConstType> ()) + if (resolved->get_kind () != TyTy::TypeKind::CONST) { rich_location r (line_table, arg->get_locus ()); r.add_fixit_remove (arg->get_locus ()); @@ -777,9 +783,8 @@ SubstitutionRef::get_mappings_from_generic_args ( } } - SubstitutionArg subst_arg (¶m_mapping, resolved); + mappings.emplace_back (¶m_mapping, resolved); offs++; - mappings.push_back (std::move (subst_arg)); } for (auto &arg : args.get_const_args ()) @@ -802,40 +807,73 @@ SubstitutionRef::get_mappings_from_generic_args ( // get the const generic specified type const auto base_generic = param_mapping.get_param_ty (); - rust_assert (base_generic->is<ConstType> ()); + rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST); const auto const_param - = static_cast<const TyTy::ConstType *> (base_generic); - auto specified_type = const_param->get_ty (); + = static_cast<const TyTy::ConstParamType *> (base_generic); + auto specified_type = const_param->get_specified_type (); // validate this const generic is of the correct type - auto 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->is<ErrorType> ()) - return SubstitutionArgumentMappings::error (); - - // const fold it - auto ctx = Compile::Context::get (); - tree folded - = Compile::HIRCompileBase::query_compile_const_expr (ctx, coereced_type, - expr); + 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 (folded == error_mark_node) + if (coereced_type == nullptr || coereced_type->is<ErrorType> ()) return SubstitutionArgumentMappings::error (); - // create const type - auto const_value - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", - coereced_type, folded, {}, expr.get_locus (), - expr.get_mappings ().get_hirid (), - expr.get_mappings ().get_hirid (), {}); + 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); + } - SubstitutionArg subst_arg (¶m_mapping, const_value); + mappings.emplace_back (¶m_mapping, const_value_ty); offs++; - mappings.push_back (std::move (subst_arg)); } // we must need to fill out defaults @@ -865,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); } } @@ -892,30 +929,24 @@ SubstitutionRef::infer_substitions (location_t locus) if (have_mapping) { - args.push_back (SubstitutionArg (&p, it->second)); + args.emplace_back (&p, it->second); } 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) { - const auto const_param = p.get_param_ty (); - rust_assert (const_param->is<TyTy::ConstType> ()); - const auto &const_type - = *static_cast<const TyTy::ConstType *> (const_param); - - TyVar infer_var - = TyVar::get_implicit_const_infer_var (const_type, locus); - args.push_back (SubstitutionArg (&p, infer_var.get_tyty ())); + 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 ()); } } @@ -961,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 ()) @@ -1008,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 (); @@ -1032,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, @@ -1067,7 +1089,7 @@ SubstitutionRef::monomorphize () 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-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc index 4bc1723..72761d9 100644 --- a/gcc/rust/typecheck/rust-tyty-util.cc +++ b/gcc/rust/typecheck/rust-tyty-util.cc @@ -30,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 * @@ -39,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; } @@ -60,17 +62,14 @@ TyVar::get_implicit_infer_var (location_t locus) } TyVar -TyVar::get_implicit_const_infer_var (const ConstType &const_type, - location_t locus) +TyVar::get_implicit_const_infer_var (location_t locus) { auto &mappings = Analysis::Mappings::get (); auto context = Resolver::TypeCheckContext::get (); + TyVar ty_infer = get_implicit_infer_var (locus); HirId next = mappings.get_next_hir_id (); - auto infer - = new ConstType (ConstType::ConstKind::Infer, const_type.get_symbol (), - const_type.get_ty (), error_mark_node, - const_type.get_specified_bounds (), locus, next, next, {}); + auto infer = new ConstInferType (ty_infer.get_tyty (), next, next, {}); context->insert_implicit_type (infer->get_ref (), infer); mappings.insert_location (infer->get_ref (), locus); @@ -98,7 +97,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 ()); } @@ -108,6 +110,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 1c8fd72..26101fd 100644 --- a/gcc/rust/typecheck/rust-tyty-util.h +++ b/gcc/rust/typecheck/rust-tyty-util.h @@ -43,8 +43,7 @@ public: static TyVar get_implicit_infer_var (location_t locus); - static TyVar get_implicit_const_infer_var (const TyTy::ConstType &const_type, - location_t locus); + static TyVar get_implicit_const_infer_var (location_t locus); 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 deb76a7..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; }; @@ -171,7 +175,10 @@ public: void visit (OpaqueType &type) override {} - void visit (ConstType &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 7971ccf..d640d55 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc @@ -321,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]); @@ -410,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-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 7783075..f7f3665e 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -45,7 +45,10 @@ public: virtual void visit (ReferenceType &type) = 0; virtual void visit (PointerType &type) = 0; virtual void visit (ParamType &type) = 0; - virtual void visit (ConstType &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; @@ -76,7 +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 ConstType &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 db96773..da5c350 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -16,29 +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 "print-tree.h" #include "tree-pretty-print.h" +#include "optional.h" #include "options.h" -#include "rust-system.h" #include "tree.h" #include "fold-const.h" -#include <string> namespace Rust { namespace TyTy { @@ -295,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) @@ -351,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; @@ -395,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; @@ -501,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 ()) @@ -546,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 ()) @@ -583,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 (), elm, + arr->get_capacity_var (), elm, arr->get_combined_refs ()); } else if (auto slice = x->try_as<const SliceType> ()) @@ -637,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> ()) { @@ -780,7 +785,8 @@ BaseType::is_concrete () const { const TyTy::BaseType *x = destructure (); - if (x->is<ParamType> () || x->is<ProjectionType> ()) + if (x->is<ParamType> () || x->is<ProjectionType> () + || x->is<ConstParamType> ()) { return false; } @@ -862,10 +868,6 @@ BaseType::is_concrete () const return false; return closure->get_result_type ().is_concrete (); } - else if (auto const_type = x->try_as<const ConstType> ()) - { - return const_type->get_value () != error_mark_node; - } else if (x->is<InferType> () || x->is<BoolType> () || x->is<CharType> () || x->is<IntType> () || x->is<UintType> () || x->is<FloatType> () || x->is<USizeType> () || x->is<ISizeType> () || x->is<NeverType> () @@ -1113,13 +1115,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 { @@ -1410,12 +1405,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 { @@ -1800,13 +1789,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 ()) @@ -2037,13 +2019,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 ()) @@ -2126,13 +2101,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 ()) @@ -2331,14 +2299,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 @@ -2368,12 +2335,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 @@ -2396,13 +2399,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) @@ -2499,15 +2495,10 @@ ArrayType::accept_vis (TyConstVisitor &vis) const std::string ArrayType::as_string () const { - return "[" + get_element_type ()->as_string () + "; " + capacity->as_string () - + "]"; -} + 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 @@ -2537,6 +2528,12 @@ 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, @@ -2561,7 +2558,7 @@ ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings) BaseType *concrete_cap = Resolver::SubstMapperInternal::Resolve (cap, mappings); rust_assert (concrete_cap->get_kind () == TyTy::TypeKind::CONST); - ref->capacity = static_cast<TyTy::ConstType *> (concrete_cap); + ref->capacity = TyVar::subst_covariant_var (cap, concrete_cap); return ref; } @@ -2585,13 +2582,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 ()) @@ -2678,13 +2668,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 { @@ -2751,13 +2734,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 { @@ -2836,13 +2812,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 { @@ -2915,13 +2884,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 { @@ -2977,13 +2939,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 { @@ -3028,13 +2983,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 { @@ -3079,13 +3027,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 { @@ -3200,13 +3141,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 ()) @@ -3362,13 +3296,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 ()) @@ -3478,13 +3405,6 @@ 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 { @@ -3543,7 +3463,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; } @@ -3564,7 +3486,7 @@ ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) { const ParamType &pp = *static_cast<const ParamType *> (resolved); if (pp.can_resolve ()) - resolved = pp.resolve (); + pp.resolve (); } // this is the new subst that this needs to pass @@ -3586,155 +3508,382 @@ ParamType::is_implicit_self_trait () const return is_trait_self; } -// ConstType +static std::string +generate_tree_str (tree value) +{ + char *buf = nullptr; + size_t size = 0; -ConstType::ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, - tree value, - std::vector<TypeBoundPredicate> specified_bounds, - location_t locus, HirId ref, HirId ty_ref, - std::set<HirId> refs) - : BaseGeneric (ref, ty_ref, KIND, - {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, - symbol.empty () ? "<n/a>" - : symbol), + 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}, - specified_bounds, refs), - const_kind (kind), ty (ty), value (value), symbol (symbol) + {}, 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 -ConstType::accept_vis (TyVisitor &vis) +ConstParamType::accept_vis (TyVisitor &vis) { vis.visit (*this); } void -ConstType::accept_vis (TyConstVisitor &vis) const +ConstParamType::accept_vis (TyConstVisitor &vis) const { vis.visit (*this); } -void -ConstType::set_value (tree v) +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 { - value = v; - const_kind = ConstType::ConstKind::Value; + return new ConstParamType (get_symbol (), ident.locus, specified_type, + get_ref (), get_ty_ref (), get_combined_refs ()); } std::string -ConstType::as_string () const +ConstParamType::get_name () const { - return get_name (); + if (!can_resolve ()) + return get_symbol (); + + BaseType *lookup = resolve (); + // Avoid infinite recursion if resolve() returns this same type + if (lookup == this->as_base_type ()) + return get_symbol (); + + return lookup->get_name (); } bool -ConstType::can_eq (const BaseType *other, bool emit_errors) const +ConstParamType::is_equal (const BaseType &other) const { - ConstCmp r (this, emit_errors); - return r.can_eq (other); + 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 ()) + return Resolver::types_compatable (TyTy::TyWithLocation (resolve ()), + TyTy::TyWithLocation (other2.resolve ()), + ident.locus, false); + + return get_symbol ().compare (other2.get_symbol ()) == 0; } BaseType * -ConstType::clone () const +ConstParamType::handle_substitions ( + SubstitutionArgumentMappings &subst_mappings) { - return new ConstType (const_kind, symbol, ty, value, get_specified_bounds (), - ident.locus, ref, ty_ref, get_combined_refs ()); + 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; } -std::string -ConstType::get_symbol () const +// --- 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 symbol; + return BaseConstType::ConstKind::Value; } -bool -ConstType::can_resolve () const +void +ConstValueType::accept_vis (TyVisitor &vis) { - return false; + 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 * -ConstType::resolve () const +ConstValueType::clone () const { - rust_unreachable (); - return nullptr; + return new ConstValueType (folded_val, specified_type, get_ref (), + get_ty_ref (), get_combined_refs ()); } -static std::string -generate_tree_str (tree value) +std::string +ConstValueType::get_name () const { - char *buf = nullptr; - size_t size = 0; + return as_string (); +} - FILE *stream = open_memstream (&buf, &size); - if (!stream) - return "<error>"; +bool +ConstValueType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + return false; - print_generic_stmt (stream, value, TDF_NONE); - fclose (stream); + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Value) + return false; - std::string result = (buf ? std::string (buf, size) : "<error>"); - free (buf); + auto &other2 = static_cast<const ConstValueType &> (*other_const); + return folded_val == other2.folded_val; +} - if (!result.empty () && result.back () == '\n') - result.pop_back (); +tree +ConstValueType::get_value () const +{ + return folded_val; +} - return result; +// --- 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 -ConstType::get_name () const +ConstInferType::as_string () const { - if (value == error_mark_node) - { - switch (get_const_kind ()) - { - case Rust::TyTy::ConstType::Decl: - return "ConstType:<" + get_ty ()->get_name () + " " + get_symbol () - + ">"; + return specified_type->get_name () + "-?"; +} - case Rust::TyTy::ConstType::Infer: - return "ConstType:<" + get_ty ()->get_name () + " ?" + ">"; +BaseType * +ConstInferType::clone () const +{ + auto &mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); - default: - return "ConstType:<" + get_ty ()->get_name () + " - <error>" + ">"; - } - } + 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 generate_tree_str (value); + return clone; +} + +std::string +ConstInferType::get_name () const +{ + return as_string (); } bool -ConstType::is_equal (const BaseType &other) const +ConstInferType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) - { - return false; - } + return false; - const ConstType &rhs = static_cast<const ConstType &> (other); - if (!get_ty ()->is_equal (*rhs.get_ty ())) + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Infer) return false; - tree lv = get_value (); - tree rv = rhs.get_value (); + 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) +{} - return operand_equal_p (lv, rv, 0); +BaseConstType::ConstKind +ConstErrorType::const_kind () const +{ + return BaseConstType::ConstKind::Error; } -ConstType * -ConstType::handle_substitions (SubstitutionArgumentMappings &mappings) +void +ConstErrorType::accept_vis (TyVisitor &vis) { - SubstitutionArg arg = SubstitutionArg::error (); - bool found = mappings.get_argument_for_symbol (this, &arg); - if (found && !arg.is_error ()) - { - TyTy::BaseType *subst = arg.get_tyty (); - rust_assert (subst->is<TyTy::ConstType> ()); - return static_cast<TyTy::ConstType *> (subst); - } + 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; - return this; + auto other_const = other.as_const_type (); + return other_const->const_kind () == BaseConstType::ConstKind::Error; } // OpaqueType @@ -3787,13 +3936,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 { @@ -3815,7 +3957,24 @@ OpaqueType::is_equal (const BaseType &other) const if (can_resolve () != other2.can_resolve ()) return false; - return bounds_compatible (other, UNDEF_LOCATION, false); + if (num_specified_bounds () != other.num_specified_bounds ()) + return 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; } // StrType @@ -3863,13 +4022,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 (); @@ -3913,13 +4065,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 { @@ -3975,13 +4120,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 { @@ -4118,12 +4256,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 { @@ -4237,13 +4369,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 { @@ -4266,7 +4391,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< @@ -4287,7 +4426,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 49415ea..3236bf3 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -91,6 +91,7 @@ public: class TyVisitor; class TyConstVisitor; +class BaseConstType; class BaseType : public TypeBoundsMappings { public: @@ -110,29 +111,15 @@ 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); @@ -240,6 +227,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> ()); @@ -327,8 +319,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; @@ -359,8 +349,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; @@ -402,8 +390,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_symbol () const override final; @@ -426,7 +412,7 @@ private: std::string symbol; }; -class ConstType : public BaseGeneric +class BaseConstType { public: static constexpr auto KIND = TypeKind::CONST; @@ -439,25 +425,30 @@ public: Error }; - ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, tree value, - std::vector<TypeBoundPredicate> specified_bounds, location_t locus, - HirId ref, HirId ty_ref, - std::set<HirId> refs = std::set<HirId> ()); + virtual ConstKind const_kind () const = 0; - void accept_vis (TyVisitor &vis) override; - void accept_vis (TyConstVisitor &vis) const override; + BaseType *get_specified_type () const { return specified_type; } - ConstKind get_const_kind () const { return const_kind; } - TyTy::BaseType *get_ty () const { return ty; } - tree get_value () const { return value; } + // 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; - void set_value (tree value); +protected: + BaseConstType (BaseType *type) : specified_type (type) {} - std::string as_string () const override; + BaseType *specified_type; +}; - bool can_eq (const BaseType *other, bool emit_errors) const override final; +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> ()); - BaseType *clone () const final override; + ConstKind const_kind () const override final; std::string get_symbol () const override final; @@ -465,19 +456,126 @@ public: 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; - ConstType *handle_substitions (SubstitutionArgumentMappings &mappings); + 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: - ConstKind const_kind; - TyTy::BaseType *ty; - tree value; 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 { public: @@ -496,8 +594,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; @@ -557,8 +653,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; @@ -589,7 +683,7 @@ public: TypeBoundPredicate (const TypeBoundPredicate &other); - virtual ~TypeBoundPredicate (){}; + virtual ~TypeBoundPredicate () {} TypeBoundPredicate &operator= (const TypeBoundPredicate &other); @@ -617,10 +711,10 @@ public: bool contains_item (const std::string &search) const; - TypeBoundPredicateItem + tl::optional<TypeBoundPredicateItem> lookup_associated_item (const std::string &search) const; - TypeBoundPredicateItem + tl::optional<TypeBoundPredicateItem> lookup_associated_item (const Resolver::TraitItemReference *ref) const; // WARNING THIS WILL ALWAYS RETURN NULLPTR @@ -851,8 +945,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; } @@ -1003,8 +1095,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 (); } @@ -1076,19 +1166,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 (); } @@ -1117,8 +1210,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; @@ -1126,9 +1217,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 @@ -1194,8 +1293,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; @@ -1224,14 +1321,14 @@ class ArrayType : public BaseType public: static constexpr auto KIND = TypeKind::ARRAY; - ArrayType (HirId ref, location_t locus, ConstType *capacity, 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 (capacity) {} - ArrayType (HirId ref, HirId ty_ref, location_t locus, ConstType *capacity, + 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), @@ -1245,8 +1342,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; @@ -1254,13 +1349,14 @@ public: BaseType *clone () const final override; - ConstType *get_capacity () const { return capacity; } + BaseType *get_capacity () const; + const TyVar &get_capacity_var () const { return capacity; } ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings); private: TyVar element_type; - ConstType *capacity; + TyVar capacity; }; class SliceType : public BaseType @@ -1289,8 +1385,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; @@ -1319,8 +1413,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; }; @@ -1349,8 +1441,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; @@ -1387,8 +1477,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; @@ -1421,8 +1509,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; @@ -1448,8 +1534,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; }; @@ -1468,8 +1552,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; }; @@ -1487,8 +1569,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; }; @@ -1507,8 +1587,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; @@ -1532,8 +1610,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; @@ -1568,8 +1644,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; @@ -1612,8 +1686,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; @@ -1659,8 +1731,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; @@ -1683,8 +1753,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; @@ -1734,8 +1802,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 30ead5b..43dd6dc 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -24,31 +24,46 @@ 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 (); @@ -60,7 +75,7 @@ UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs) { TyTy::BaseType *result = UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error, infer_flag, - commits, infers); + 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 @@ -104,24 +119,59 @@ 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; - - // if any of the types are inference variables lets fix them - if (ref_tyty->is<TyTy::InferType> ()) - context.insert_implicit_type (ref, resolved); + 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 ()); + + for (auto &ref : resolved->get_combined_refs ()) + { + 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); + } + } } } } @@ -155,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 (); + } } } } @@ -222,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 @@ -239,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 @@ -248,6 +299,36 @@ 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) + { + const auto &lhs = *ltype->as_const_type (); + const 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) + { + TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var ( + lhs.as_base_type ()->get_locus ()); + ltype = iv.get_tyty (); + } + else if (rhs.const_kind () + == TyTy::BaseConstType::ConstKind::Decl) + { + TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var ( + rhs.as_base_type ()->get_locus ()); + rtype = iv.get_tyty (); + } + } + } } switch (ltype->get_kind ()) @@ -329,13 +410,13 @@ UnifyRules::go () return expect_opaque (static_cast<TyTy::OpaqueType *> (ltype), rtype); case TyTy::CONST: - return expect_const (static_cast<TyTy::ConstType *> (ltype), rtype); + 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 * @@ -350,7 +431,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, switch (ltype->get_infer_kind ()) { case TyTy::InferType::InferTypeKind::GENERAL: - return rtype->clone (); + return rtype; case TyTy::InferType::InferTypeKind::INTEGRAL: { @@ -388,7 +469,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, == TyTy::InferType::InferTypeKind::INTEGRAL); if (is_valid) { - ltype->apply_primitive_type_hint (*rtype); + if (commit_flag) + ltype->apply_primitive_type_hint (*rtype); return rtype; } } @@ -402,7 +484,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, == TyTy::InferType::InferTypeKind::FLOAT); if (is_valid) { - ltype->apply_primitive_type_hint (*rtype); + if (commit_flag) + ltype->apply_primitive_type_hint (*rtype); return rtype; } } @@ -431,15 +514,15 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, 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 * @@ -453,7 +536,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -462,17 +545,17 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) 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) @@ -482,7 +565,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++) @@ -498,7 +581,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (other_field_ty)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } } @@ -521,12 +604,12 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) 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; @@ -554,9 +637,9 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) 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 * @@ -570,12 +653,12 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *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: @@ -601,9 +684,9 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype) 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 * @@ -617,7 +700,7 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -632,7 +715,7 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) 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 @@ -640,12 +723,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; @@ -673,9 +754,9 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) 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 * @@ -689,7 +770,7 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -704,7 +785,7 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) 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 @@ -712,12 +793,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; @@ -745,9 +824,9 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) 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 * @@ -761,7 +840,7 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -810,9 +889,9 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) 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 * @@ -826,7 +905,7 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -838,24 +917,35 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (type.get_element_type ())); if (element_unify->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + 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->get_capacity ()), - TyTy::TyWithLocation (type.get_capacity ())); + = resolve_subtype (TyTy::TyWithLocation (ltype_cap), + TyTy::TyWithLocation (rtype_cap)); emit_error = save_emit_error; if (capacity_unify->get_kind () != TyTy::TypeKind::CONST) - return new TyTy::ErrorType (0); - - TyTy::ConstType *capacity_type_unify - = static_cast<TyTy::ConstType *> (capacity_unify); - return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, - capacity_type_unify, - TyTy::TyVar (element_unify->get_ref ())); + 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; @@ -883,9 +973,9 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) 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 * @@ -899,7 +989,7 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -911,12 +1001,7 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) 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; @@ -944,9 +1029,9 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) 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 * @@ -960,7 +1045,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -969,7 +1054,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) 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++) @@ -981,7 +1066,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } @@ -990,7 +1075,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) 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 @@ -1001,12 +1086,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; @@ -1034,9 +1119,9 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) 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 * @@ -1050,7 +1135,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1059,7 +1144,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) 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++) @@ -1071,7 +1156,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } @@ -1080,10 +1165,20 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) 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; @@ -1098,12 +1193,12 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) 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++) @@ -1116,11 +1211,30 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) 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 (); + // 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; @@ -1135,12 +1249,12 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) 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.get_num_params ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < ltype->num_params (); i++) @@ -1153,11 +1267,11 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) 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; @@ -1183,9 +1297,9 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) 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 * @@ -1199,7 +1313,7 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1208,7 +1322,7 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) 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; @@ -1221,13 +1335,12 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) = 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; @@ -1255,9 +1368,9 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) 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 * @@ -1272,14 +1385,15 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) = 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: @@ -1305,9 +1419,9 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) 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 * @@ -1322,14 +1436,15 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) = 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: @@ -1355,9 +1470,9 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) 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 * @@ -1373,8 +1488,9 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) || 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; @@ -1384,8 +1500,7 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) 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; @@ -1413,9 +1528,9 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) 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 * @@ -1431,8 +1546,9 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) || 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; @@ -1442,8 +1558,7 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) 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; @@ -1471,9 +1586,9 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) 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 * @@ -1489,8 +1604,9 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) || 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; @@ -1500,8 +1616,7 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) 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; @@ -1529,9 +1644,9 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) 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 * @@ -1546,14 +1661,15 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) = 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: @@ -1579,9 +1695,9 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) 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 * @@ -1596,14 +1712,15 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) = 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: @@ -1629,9 +1746,9 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) 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 * @@ -1645,14 +1762,14 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *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 * @@ -1667,12 +1784,12 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype, 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: @@ -1697,14 +1814,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 * @@ -1719,7 +1836,7 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype, bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1752,9 +1869,9 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype, 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 * @@ -1768,7 +1885,7 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1778,15 +1895,15 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) = *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; @@ -1814,9 +1931,9 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) 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 * @@ -1830,7 +1947,7 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1839,7 +1956,7 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) 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 @@ -1847,7 +1964,7 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) 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 @@ -1855,10 +1972,10 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) 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; @@ -1886,9 +2003,9 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) 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 * @@ -1898,7 +2015,7 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) { TyTy::OpaqueType *ro = rtype->as<TyTy::OpaqueType> (); if (!ltype->is_equal (*ro)) - return new TyTy::ErrorType (0); + return unify_error_type_node (); if (ltype->can_resolve () && ro->can_resolve ()) { @@ -1908,7 +2025,7 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) auto res = resolve_subtype (TyTy::TyWithLocation (lr), TyTy::TyWithLocation (rr)); if (res->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + return unify_error_type_node (); } else if (ltype->can_resolve ()) { @@ -1927,7 +2044,7 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) auto res = resolve_subtype (TyTy::TyWithLocation (underly), TyTy::TyWithLocation (rtype)); if (res->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + return unify_error_type_node (); } else { @@ -1938,70 +2055,108 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) } TyTy::BaseType * -UnifyRules::expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype) +UnifyRules::expect_const (TyTy::BaseConstType *ltype, TyTy::BaseType *rtype) { if (rtype->get_kind () != TyTy::TypeKind::CONST) - return new TyTy::ErrorType (0); + return unify_error_type_node (); - TyTy::ConstType &lhs = *ltype; - TyTy::ConstType &rhs = *static_cast<TyTy::ConstType *> (rtype); + auto &lhs = *ltype; + auto &rhs = *rtype->as_const_type (); - auto res = resolve_subtype (TyTy::TyWithLocation (lhs.get_ty ()), - TyTy::TyWithLocation (rhs.get_ty ())); - if (res->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + // 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 ()); + } - tree lv = lhs.get_value (); - tree rv = rhs.get_value (); + // Try to resolve Decl types (ConstParamType) + TyTy::BaseConstType *resolved_lhs = &lhs; + TyTy::BaseConstType *resolved_rhs = &rhs; - if (error_operand_p (lv) && error_operand_p (rv)) + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) { - // this is only allowed for some silly senarios like: - // gcc/testsuite/rust/compile/issue-const_generics_5.rs - if (lhs.get_const_kind () == rhs.get_const_kind ()) + auto *param = static_cast<TyTy::ConstParamType *> (&lhs); + if (param->can_resolve ()) { - return new TyTy::ConstType (lhs.get_const_kind (), lhs.get_symbol (), - res, error_mark_node, - lhs.get_specified_bounds (), - lhs.get_locus (), lhs.get_ref (), - lhs.get_ty_ref (), - lhs.get_combined_refs ()); + auto *resolved = param->resolve (); + if (resolved->get_kind () == TyTy::TypeKind::CONST) + resolved_lhs = resolved->as_const_type (); } - - return new TyTy::ErrorType (0); } - bool equal = operand_equal_p (lv, rv, 0); - if (equal) + if (rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) { - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - lhs.get_symbol (), res, lv, - lhs.get_specified_bounds (), lhs.get_locus (), - lhs.get_ref (), lhs.get_ty_ref (), - lhs.get_combined_refs ()); + 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 (); + } } - if (lhs.get_const_kind () == TyTy::ConstType::Infer && !error_operand_p (rv)) + 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) { - lhs.set_value (rv); - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - lhs.get_symbol (), res, rv, - lhs.get_specified_bounds (), lhs.get_locus (), - lhs.get_ref (), lhs.get_ty_ref (), - lhs.get_combined_refs ()); + 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 (rhs.get_const_kind () == TyTy::ConstType::Infer - && !error_operand_p (lv)) + 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) { - rhs.set_value (lv); - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - rhs.get_symbol (), res, lv, - rhs.get_specified_bounds (), rhs.get_locus (), - rhs.get_ref (), rhs.get_ty_ref (), - rhs.get_combined_refs ()); + // 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 new TyTy::ErrorType (0); + return unify_error_type_node (); } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h index b8c9cbc..4bed24c 100644 --- a/gcc/rust/typecheck/rust-unify.h +++ b/gcc/rust/typecheck/rust-unify.h @@ -30,6 +30,11 @@ class UnifyRules public: struct InferenceSite { + InferenceSite (HirId pref, HirId ptyref, TyTy::ParamType *param, + TyTy::InferType *infer) + : pref (pref), ptyref (ptyref), param (param), infer (infer) + {} + HirId pref; HirId ptyref; TyTy::ParamType *param; @@ -37,6 +42,11 @@ public: }; 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,12 +95,13 @@ protected: TyTy::BaseType *rtype); TyTy::BaseType *expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype); - TyTy::BaseType *expect_const (TyTy::ConstType *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, @@ -110,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/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/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h index 367044a..a22664a 100644 --- a/gcc/rust/util/rust-attribute-values.h +++ b/gcc/rust/util/rust-attribute-values.h @@ -36,6 +36,7 @@ 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"; @@ -48,6 +49,8 @@ public: static constexpr auto &PROC_MACRO_DERIVE = "proc_macro_derive"; static constexpr auto &PROC_MACRO_ATTRIBUTE = "proc_macro_attribute"; + static constexpr auto &DERIVE = "derive"; + static constexpr auto &TARGET_FEATURE = "target_feature"; // From now on, these are reserved by the compiler and gated through // #![feature(rustc_attrs)] @@ -60,6 +63,8 @@ public: 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"; @@ -88,8 +93,6 @@ public: static constexpr auto &TEST = "test"; - static constexpr auto &SIMD_TEST = "simd_test"; - static constexpr auto &RUSTC_ARGS_REQUIRED_CONST = "rustc_args_required_const"; }; diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index c846c2d..9621100 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,6 +78,7 @@ 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}, @@ -64,6 +90,8 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::PROC_MACRO, EXPANSION}, {Attrs::PROC_MACRO_DERIVE, EXPANSION}, {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION}, + + {Attrs::DERIVE, EXPANSION}, // FIXME: This is not implemented yet, see // https://github.com/Rust-GCC/gccrs/issues/1475 {Attrs::TARGET_FEATURE, CODE_GENERATION}, @@ -78,6 +106,7 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION}, {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS}, {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS}, + {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS}, {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}, {Attrs::TRACK_CALLER, CODE_GENERATION}, {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK}, @@ -100,8 +129,7 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::NON_EXHAUSTIVE, TYPE_CHECK}, {Attrs::RUSTFMT, EXTERNAL}, - {Attrs::TEST, CODE_GENERATION}, - {Attrs::SIMD_TEST, CODE_GENERATION}}; + {Attrs::TEST, CODE_GENERATION}}; BuiltinAttributeMappings * BuiltinAttributeMappings::get () @@ -144,6 +172,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) @@ -214,8 +243,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; } @@ -300,6 +329,20 @@ check_proc_macro_non_root (AST::AttrVec attributes, location_t loc) 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 @@ -314,6 +357,15 @@ AttributeChecker::check_attribute (const AST::Attribute &attribute) } void +AttributeChecker::check_inner_attributes (const AST::AttrVec &attributes) +{ + for (auto &attr : attributes) + if (attr.is_derive ()) + rust_error_at (attr.get_locus (), + "derive attribute cannot be used at crate level"); +} + +void AttributeChecker::check_attributes (const AST::AttrVec &attributes) { for (auto &attr : attributes) @@ -329,10 +381,6 @@ AttributeChecker::visit (AST::DelimTokenTree &) {} void -AttributeChecker::visit (AST::AttrInputMetaItemContainer &) -{} - -void AttributeChecker::visit (AST::IdentifierExpr &) {} @@ -395,8 +443,16 @@ AttributeChecker::visit (AST::MetaItemLitExpr &) {} void -AttributeChecker::visit (AST::MetaItemPathExpr &) -{} +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 &) @@ -622,6 +678,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 ()) { @@ -774,10 +831,6 @@ AttributeChecker::visit (AST::StaticItem &item) } void -AttributeChecker::visit (AST::TraitItemConst &) -{} - -void AttributeChecker::visit (AST::TraitItemType &) {} @@ -785,6 +838,7 @@ void AttributeChecker::visit (AST::Trait &trait) { check_proc_macro_non_function (trait.get_outer_attrs ()); + check_attributes (trait.get_outer_attrs ()); } void @@ -841,10 +895,6 @@ AttributeChecker::visit (AST::MetaItemPath &) {} void -AttributeChecker::visit (AST::MetaItemSeq &) -{} - -void AttributeChecker::visit (AST::MetaWord &) {} @@ -920,11 +970,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 @@ -934,11 +984,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 db8fe23..b10a080 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 @@ -104,13 +106,14 @@ private: void check_attribute (const AST::Attribute &attribute); /* Check the validity of all given attributes */ + + void check_inner_attributes (const AST::AttrVec &attributes); void check_attributes (const AST::AttrVec &attributes); // rust-ast.h 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; @@ -203,7 +206,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; @@ -219,7 +221,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; @@ -242,12 +243,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-canonical-path.h b/gcc/rust/util/rust-canonical-path.h index 079ae76..4c4d9df 100644 --- a/gcc/rust/util/rust-canonical-path.h +++ b/gcc/rust/util/rust-canonical-path.h @@ -114,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-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-ggc.cc b/gcc/rust/util/rust-ggc.cc index 0722af2..46220a2 100644 --- a/gcc/rust/util/rust-ggc.cc +++ b/gcc/rust/util/rust-ggc.cc @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-ggc.h" +#include "rust-ast.h" #include "stringpool.h" namespace Rust { @@ -29,6 +30,8 @@ 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 { diff --git a/gcc/rust/util/rust-ggc.h b/gcc/rust/util/rust-ggc.h index da28ede..da4ede1 100644 --- a/gcc/rust/util/rust-ggc.h +++ b/gcc/rust/util/rust-ggc.h @@ -24,6 +24,9 @@ namespace Rust { +// forward declare +class Identifier; + namespace GGC { class Ident @@ -33,6 +36,7 @@ class Ident 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; 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.h b/gcc/rust/util/rust-lang-item.h index 67a5d9c..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 @@ -185,3 +188,5 @@ template <> struct hash<Rust::LangItem::Kind> } }; } // namespace std + +#endif // RUST_LANG_ITEM_H diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc index 52172f4..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 ()); diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h index af3a237..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 { @@ -115,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 |
