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  | 
