diff options
Diffstat (limited to 'gcc')
32 files changed, 1169 insertions, 291 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 7316865..7d3a075 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1209,9 +1209,18 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual Location get_locus_slow () const = 0; + + NodeId get_node_id () { return node_id; } + protected: + GenericParam () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + GenericParam (NodeId node_id) : node_id (node_id) {} + // Clone function implementation as pure virtual method virtual GenericParam *clone_generic_param_impl () const = 0; + + NodeId node_id; }; // A lifetime generic parameter (as opposed to a type generic parameter) @@ -1251,6 +1260,10 @@ public: void accept_vis (ASTVisitor &vis) override; + Location get_locus () const { return locus; } + + Location get_locus_slow () const override final { return get_locus (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index a6f5398..35d1827 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -66,6 +66,8 @@ class TypeParam : public GenericParam Location locus; public: + Identifier get_type_representation () const { return type_representation; } + // Returns whether the type of the type param has been specified. bool has_type () const { return type != nullptr; } @@ -80,7 +82,8 @@ public: = std::vector<std::unique_ptr<TypeParamBound> > (), std::unique_ptr<Type> type = nullptr, Attribute outer_attr = Attribute::create_empty ()) - : outer_attr (std::move (outer_attr)), + : GenericParam (Analysis::Mappings::get ()->get_next_node_id ()), + outer_attr (std::move (outer_attr)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), type (std::move (type)), locus (locus) @@ -88,7 +91,7 @@ public: // Copy constructor uses clone TypeParam (TypeParam const &other) - : outer_attr (other.outer_attr), + : GenericParam (other.node_id), outer_attr (other.outer_attr), type_representation (other.type_representation), locus (other.locus) { // guard to prevent null pointer dereference @@ -106,6 +109,7 @@ public: type_representation = other.type_representation; outer_attr = other.outer_attr; locus = other.locus; + node_id = other.node_id; // guard to prevent null pointer dereference if (other.type != nullptr) @@ -128,6 +132,8 @@ public: Location get_locus () const { return locus; } + Location get_locus_slow () const override final { return get_locus (); } + void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? @@ -1756,6 +1762,8 @@ public: Location get_locus () const { return locus; } + Location get_locus_slow () const final { return get_locus (); }; + // Invalid if name is empty, so base stripping on that. void mark_for_strip () override { struct_name = ""; } bool is_marked_for_strip () const override { return struct_name.empty (); } @@ -1949,7 +1957,6 @@ public: std::move (outer_attrs)), is_unit (true) {} - // TODO: can a unit struct have generic fields? assuming yes for now. /* Returns whether the struct is a unit struct - struct defined without * fields. This is important because it also means an implicit constant of its diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index d6f3c42..81fce57 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -196,6 +196,8 @@ public: // TODO: is this better? Or is a "vis_pattern" better? std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; } + + std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; }; }; /* A segment of a path in expression, including an identifier aspect and maybe diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index c5ae3bb..b191554 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -274,7 +274,15 @@ public: void visit (TyTy::InferType &) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &) override { gcc_unreachable (); } + void visit (TyTy::ParamType ¶m) override + { + rust_assert (param.get_ref () != param.get_ty_ref ()); + + TyTy::BaseType *lookup = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type (param.get_ty_ref (), &lookup); + rust_assert (ok); + lookup->accept_vis (*this); + } void visit (TyTy::FnType &type) override { @@ -338,7 +346,7 @@ public: Btype *named_struct = ctx->get_backend ()->named_type (type.get_name (), struct_type_record, ctx->get_mappings ()->lookup_location ( - type.get_ty_ref ())); + type.get_ref ())); ctx->push_type (named_struct); ctx->insert_compiled_type (type.get_ty_ref (), named_struct); diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 00625df..95a6744 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -539,8 +539,16 @@ public: void visit (HIR::StructExprStructFields &struct_expr) { - Btype *type - = ResolvePathType::Compile (&struct_expr.get_struct_name (), ctx); + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + struct_expr.get_mappings ().get_hirid (), &tyty)) + { + rust_error_at (struct_expr.get_locus (), "unknown type"); + return; + } + + Btype *type = TyTyResolveCompile::compile (ctx, tyty); + rust_assert (type != nullptr); // this assumes all fields are in order from type resolution and if a base // struct was specified those fields are filed via accesors @@ -573,8 +581,8 @@ public: return; } rust_assert (receiver->get_kind () == TyTy::TypeKind::ADT); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver); - TyTy::ADTType *adt = (TyTy::ADTType *) receiver; size_t index = 0; adt->get_field (expr.get_field_name (), &index); diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index 3da269a..8018367 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -50,7 +50,7 @@ public: ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx); - std::string ident = self->as_string () + "::" + constant.get_identifier (); + std::string ident = self->get_name () + "::" + constant.get_identifier (); Bexpression *const_expr = ctx->get_backend ()->named_constant_expression ( type, constant.get_identifier (), value, constant.get_locus ()); @@ -95,7 +95,7 @@ public: unsigned int flags = 0; std::string fn_identifier - = self->as_string () + "::" + function.function_name; + = self->get_name () + "::" + function.function_name; // if its the main fn or pub visibility mark its as DECL_PUBLIC // please see https://github.com/Rust-GCC/gccrs/pull/137 @@ -259,7 +259,7 @@ public: unsigned int flags = 0; std::string fn_identifier - = self->as_string () + "::" + method.get_method_name (); + = self->get_name () + "::" + method.get_method_name (); // if its the main fn or pub visibility mark its as DECL_PUBLIC // please see https://github.com/Rust-GCC/gccrs/pull/137 diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index cfbe969..c6b135b 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -39,34 +39,6 @@ public: item->accept_vis (compiler); } - void visit (HIR::TupleStruct &struct_decl) - { - TyTy::BaseType *resolved = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - struct_decl.get_mappings ().get_hirid (), &resolved)) - { - rust_fatal_error (struct_decl.get_locus (), - "Failed to lookup type for struct decl"); - return; - } - - TyTyResolveCompile::compile (ctx, resolved); - } - - void visit (HIR::StructStruct &struct_decl) - { - TyTy::BaseType *resolved = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - struct_decl.get_mappings ().get_hirid (), &resolved)) - { - rust_fatal_error (struct_decl.get_locus (), - "Failed to lookup type for struct decl"); - return; - } - - TyTyResolveCompile::compile (ctx, resolved); - } - void visit (HIR::StaticItem &var) { TyTy::BaseType *resolved_type = nullptr; diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index de325fa..ffc2655 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -84,7 +84,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) CompileItem::compile (resolved_item, ctx); if (!ctx->lookup_function_decl (ref, &fn)) { - rust_error_at (expr.get_locus (), "forward decl was not compiled"); + rust_error_at (expr.get_locus (), "forward decl was not compiled 1"); return; } } @@ -112,12 +112,14 @@ ResolvePathType::visit (HIR::PathInExpression &expr) return; } - // assumes paths are functions for now - if (!ctx->lookup_compiled_types (ref, &resolved)) + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (ref, &tyty)) { - rust_error_at (expr.get_locus (), "forward decl was not compiled"); + rust_error_at (expr.get_locus (), "unknown type"); return; } + + resolved = TyTyResolveCompile::compile (ctx, tyty); } } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index aed96e3..683a9a7 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -48,8 +48,6 @@ public: void visit (TyTy::InferType &) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &) override { gcc_unreachable (); } - void visit (TyTy::ADTType &) override { gcc_unreachable (); } void visit (TyTy::TupleType &) override { gcc_unreachable (); } @@ -58,6 +56,8 @@ public: void visit (TyTy::ReferenceType &) override { gcc_unreachable (); } + void visit (TyTy::ParamType &) override { gcc_unreachable (); } + void visit (TyTy::UnitType &) override { translated = backend->void_type (); } void visit (TyTy::FnType &type) override diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index ea07f73..b46861e 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -74,27 +74,7 @@ public: return compiler.translated; } - void visit (AST::PathInExpression &expr) - { - std::vector<HIR::PathExprSegment> path_segments; - expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool { - rust_assert (s.has_generic_args () == false); // TODO - - HIR::PathIdentSegment is (s.get_ident_segment ().as_string ()); - HIR::PathExprSegment seg (is, s.get_locus ()); - path_segments.push_back (seg); - return true; - }); - - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), - mappings->get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); - - translated = new HIR::PathInExpression (mapping, std::move (path_segments), - expr.get_locus (), - expr.opening_scope_resolution ()); - } + void visit (AST::PathInExpression &expr) override; private: ASTLowerPathInExpression () : translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 1e48e82..2865a6a 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -54,6 +54,12 @@ public: void visit (AST::TupleStruct &struct_decl) { std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + if (struct_decl.has_generics ()) + { + generic_params + = lower_generic_params (struct_decl.get_generic_params ()); + } + std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); @@ -104,6 +110,12 @@ public: void visit (AST::StructStruct &struct_decl) { std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + if (struct_decl.has_generics ()) + { + generic_params + = lower_generic_params (struct_decl.get_generic_params ()); + } + std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = HIR::Visibility::create_public (); @@ -324,6 +336,19 @@ public: } private: + std::vector<std::unique_ptr<HIR::GenericParam> > lower_generic_params ( + std::vector<std::unique_ptr<AST::GenericParam> > ¶ms) + { + std::vector<std::unique_ptr<HIR::GenericParam> > lowered; + for (auto &ast_param : params) + { + auto hir_param = ASTLowerGenericParam::translate (ast_param.get ()); + lowered.push_back (std::unique_ptr<HIR::GenericParam> (hir_param)); + } + + return lowered; + } + ASTLoweringItem () : translated (nullptr) {} HIR::Item *translated; diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 425d5c1..b5d0b7e 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -121,6 +121,33 @@ public: segment.get_locus ()); } + void visit (AST::TypePathSegmentGeneric &segment) + { + std::vector<HIR::GenericArgsBinding> binding_args; // TODO + + std::string segment_name = segment.get_ident_segment ().as_string (); + bool has_separating_scope_resolution + = segment.get_separating_scope_resolution (); + + std::vector<HIR::Lifetime> lifetime_args; + for (auto &lifetime : segment.get_generic_args ().get_lifetime_args ()) + { + HIR::Lifetime l = lower_lifetime (lifetime); + lifetime_args.push_back (std::move (l)); + } + + std::vector<std::unique_ptr<HIR::Type> > type_args; + for (auto &type : segment.get_generic_args ().get_type_args ()) + { + HIR::Type *t = ASTLoweringType::translate (type.get ()); + type_args.push_back (std::unique_ptr<HIR::Type> (t)); + } + + translated_segment = new HIR::TypePathSegmentGeneric ( + segment_name, has_separating_scope_resolution, std::move (lifetime_args), + std::move (type_args), std::move (binding_args), segment.get_locus ()); + } + void visit (AST::TypePath &path) { std::vector<std::unique_ptr<HIR::TypePathSegment> > translated_segments; @@ -215,6 +242,49 @@ private: HIR::TypePathSegment *translated_segment; }; +class ASTLowerGenericParam : public ASTLoweringBase +{ +public: + static HIR::GenericParam *translate (AST::GenericParam *param) + { + ASTLowerGenericParam resolver; + param->accept_vis (resolver); + + rust_assert (resolver.translated != nullptr); + resolver.mappings->insert_location ( + resolver.translated->get_mappings ().get_crate_num (), + resolver.translated->get_mappings ().get_hirid (), + param->get_locus_slow ()); + + return resolver.translated; + } + + void visit (AST::TypeParam ¶m) override + { + HIR::Attribute outer_attr = HIR::Attribute::create_empty (); + std::vector<std::unique_ptr<HIR::TypeParamBound> > type_param_bounds; + HIR::Type *type = param.has_type () + ? ASTLoweringType::translate (param.get_type ().get ()) + : nullptr; + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, param.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated + = new HIR::TypeParam (mapping, param.get_type_representation (), + param.get_locus (), std::move (type_param_bounds), + std::unique_ptr<Type> (type), + std::move (outer_attr)); + } + +private: + ASTLowerGenericParam () : ASTLoweringBase (), translated (nullptr) {} + + HIR::GenericParam *translated; +}; + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 230919a..355d570 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -269,5 +269,51 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr) std::move (outer_attribs)); } +// rust-ast-lower-expr.h + +void +ASTLowerPathInExpression::visit (AST::PathInExpression &expr) +{ + std::vector<HIR::PathExprSegment> path_segments; + expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool { + std::vector<HIR::GenericArgsBinding> binding_args; // TODO + + std::vector<HIR::Lifetime> lifetime_args; + if (s.has_generic_args ()) + { + for (auto &lifetime : s.get_generic_args ().get_lifetime_args ()) + { + HIR::Lifetime l = lower_lifetime (lifetime); + lifetime_args.push_back (std::move (l)); + } + } + + std::vector<std::unique_ptr<HIR::Type> > type_args; + if (s.has_generic_args ()) + { + for (auto &type : s.get_generic_args ().get_type_args ()) + { + HIR::Type *t = ASTLoweringType::translate (type.get ()); + type_args.push_back (std::unique_ptr<HIR::Type> (t)); + } + } + + PathExprSegment seg (s.get_ident_segment ().as_string (), s.get_locus (), + std::move (lifetime_args), std::move (type_args), + std::move (binding_args)); + path_segments.push_back (seg); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::PathInExpression (mapping, std::move (path_segments), + expr.get_locus (), + expr.opening_scope_resolution ()); +} + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index c0d6d0f..1415727 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -57,12 +57,13 @@ public: // Returns whether the type param has an outer attribute. bool has_outer_attribute () const { return !outer_attr.is_empty (); } - TypeParam (Identifier type_representation, Location locus = Location (), + TypeParam (Analysis::NodeMapping mappings, Identifier type_representation, + Location locus = Location (), std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds = std::vector<std::unique_ptr<TypeParamBound> > (), std::unique_ptr<Type> type = nullptr, Attribute outer_attr = Attribute::create_empty ()) - : outer_attr (std::move (outer_attr)), + : GenericParam (mappings), outer_attr (std::move (outer_attr)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), type (std::move (type)), locus (locus) @@ -70,7 +71,7 @@ public: // Copy constructor uses clone TypeParam (TypeParam const &other) - : outer_attr (other.outer_attr), + : GenericParam (other.mappings), outer_attr (other.outer_attr), type_representation (other.type_representation), type (other.type->clone_type ()), locus (other.locus) { @@ -87,6 +88,7 @@ public: type = other.type->clone_type (); outer_attr = other.outer_attr; locus = other.locus; + mappings = other.mappings; type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -103,8 +105,12 @@ public: Location get_locus () const { return locus; } + Location get_locus_slow () const override final { return get_locus (); } + void accept_vis (HIRVisitor &vis) override; + Identifier get_type_representation () const { return type_representation; } + protected: // Clone function implementation as (not pure) virtual method TypeParam *clone_generic_param_impl () const override @@ -1502,6 +1508,11 @@ public: Location get_locus () const { return locus; } + std::vector<std::unique_ptr<GenericParam> > &get_generic_params () + { + return generic_params; + } + protected: Struct (Analysis::NodeMapping mappings, Identifier struct_name, std::vector<std::unique_ptr<GenericParam> > generic_params, diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 9a772f0..c4fe0da 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -172,7 +172,21 @@ public: std::vector<GenericArgsBinding> ()); } + bool is_empty () const + { + return lifetime_args.size () == 0 && type_args.size () == 0 + && binding_args.size () == 0; + } + std::string as_string () const; + + std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; } + + std::vector<std::unique_ptr<Type> > &get_type_args () { return type_args; } + + std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; } + + Location get_locus () const { return locus; } }; /* A segment of a path in expression, including an identifier aspect and maybe @@ -230,6 +244,8 @@ public: Location get_locus () const { return locus; } PathIdentSegment get_segment () const { return segment_name; } + + GenericArgs &get_generic_args () { return generic_args; } }; // HIR node representing a pattern that involves a "path" - abstract base class @@ -264,6 +280,8 @@ public: return; } } + + PathExprSegment get_final_segment () const { return segments.back (); } }; /* HIR node representing a path-in-expression pattern (path that allows generic @@ -432,6 +450,8 @@ public: void accept_vis (HIRVisitor &vis) override; + GenericArgs get_generic_args () { return generic_args; } + protected: // Use covariance to override base class method TypePathSegmentGeneric *clone_type_path_segment_impl () const override @@ -653,12 +673,14 @@ public: void iterate_segments (std::function<bool (TypePathSegment *)> cb) { - for (auto it = segments.begin (); it != segments.end (); it++) + for (auto &seg : segments) { - if (!cb ((*it).get ())) + if (!cb (seg.get ())) return; } } + + TypePathSegment *get_final_segment () { return segments.back ().get (); } }; struct QualifiedPathType diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index 1567215..97f303c 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -1114,9 +1114,17 @@ public: virtual void accept_vis (HIRVisitor &vis) = 0; + virtual Location get_locus_slow () const = 0; + + Analysis::NodeMapping get_mappings () const { return mappings; } + protected: // Clone function implementation as pure virtual method virtual GenericParam *clone_generic_param_impl () const = 0; + + GenericParam (Analysis::NodeMapping mapping) : mappings (mapping) {} + + Analysis::NodeMapping mappings; }; // A lifetime generic parameter (as opposed to a type generic parameter) @@ -1145,11 +1153,12 @@ public: bool is_error () const { return lifetime.is_error (); } // Constructor - LifetimeParam (Lifetime lifetime, Location locus = Location (), + LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime, + Location locus = Location (), std::vector<Lifetime> lifetime_bounds = std::vector<Lifetime> (), Attribute outer_attr = Attribute::create_empty ()) - : lifetime (std::move (lifetime)), + : GenericParam (mappings), lifetime (std::move (lifetime)), lifetime_bounds (std::move (lifetime_bounds)), outer_attr (std::move (outer_attr)), locus (locus) {} @@ -1158,8 +1167,9 @@ public: // Copy constructor with clone LifetimeParam (LifetimeParam const &other) - : lifetime (other.lifetime), lifetime_bounds (other.lifetime_bounds), - outer_attr (other.outer_attr), locus (other.locus) + : GenericParam (other.mappings), lifetime (other.lifetime), + lifetime_bounds (other.lifetime_bounds), outer_attr (other.outer_attr), + locus (other.locus) {} // Overloaded assignment operator to clone attribute @@ -1169,6 +1179,7 @@ public: lifetime_bounds = other.lifetime_bounds; outer_attr = other.outer_attr; locus = other.locus; + mappings = other.mappings; return *this; } @@ -1181,6 +1192,10 @@ public: void accept_vis (HIRVisitor &vis) override; + Location get_locus () const { return locus; } + + Location get_locus_slow () const override final { return get_locus (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index b8cf4de..216ab41 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -27,6 +27,21 @@ namespace Rust { namespace Resolver { +class ResolvePath : public ResolverBase +{ +public: + static void go (AST::PathInExpression *expr, NodeId parent) + { + ResolvePath resolver (parent); + resolver.resolve_path (expr); + } + +private: + ResolvePath (NodeId parent) : ResolverBase (parent) {} + + void resolve_path (AST::PathInExpression *expr); +}; + class ResolveExpr : public ResolverBase { public: @@ -50,31 +65,7 @@ public: ResolveExpr::go (elem.get (), expr.get_node_id ()); } - void visit (AST::PathInExpression &expr) - { - // name scope first - if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) - { - resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - resolver->insert_new_definition (expr.get_node_id (), - Definition{expr.get_node_id (), - parent}); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (expr.as_string (), - &resolved_node)) - { - resolver->insert_resolved_type (expr.get_node_id (), resolved_node); - resolver->insert_new_definition (expr.get_node_id (), - Definition{expr.get_node_id (), - parent}); - } - else - { - rust_error_at (expr.get_locus (), "unknown path %s", - expr.as_string ().c_str ()); - } - } + void visit (AST::PathInExpression &expr) { ResolvePath::go (&expr, parent); } void visit (AST::ReturnExpr &expr) { diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index f5dc579..02d864f 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -37,8 +37,6 @@ public: item->accept_vis (resolver); }; - ~ResolveItem () {} - void visit (AST::TupleStruct &struct_decl) { struct_decl.iterate ([&] (AST::TupleField &field) mutable -> bool { @@ -50,11 +48,25 @@ public: void visit (AST::StructStruct &struct_decl) { + NodeId scope_node_id = struct_decl.get_node_id (); + resolver->get_type_scope ().push (scope_node_id); + + if (struct_decl.has_generics ()) + { + for (auto &generic : struct_decl.get_generic_params ()) + { + ResolveGenericParam::go (generic.get (), + struct_decl.get_node_id ()); + } + } + struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool { ResolveType::go (field.get_field_type ().get (), struct_decl.get_node_id ()); return true; }); + + resolver->get_type_scope ().pop (); } void visit (AST::StaticItem &var) diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 4b08c21..24090a0 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -25,6 +25,53 @@ namespace Rust { namespace Resolver { +class ResolveTypePath : public ResolverBase +{ +public: + static NodeId go (AST::TypePath &path, NodeId parent) + { + ResolveTypePath resolver (parent); + resolver.resolve (path); + return resolver.resolved_node; + } + + void visit (AST::TypePathSegmentGeneric &seg) override; + + void visit (AST::TypePathSegment &seg) override; + +private: + void resolve (AST::TypePath &path) + { + for (auto &seg : path.get_segments ()) + { + seg->accept_vis (*this); + if (type_seg_failed_flag) + return; + } + + if (path_buffer.empty ()) + { + rust_error_at (path.get_locus (), "failed to resolve path: %s", + path.as_string ().c_str ()); + return; + } + + if (!resolver->get_type_scope ().lookup (path_buffer, &resolved_node)) + { + rust_error_at (path.get_locus (), "failed to resolve TypePath: %s", + path_buffer.c_str ()); + return; + } + } + + ResolveTypePath (NodeId parent) + : ResolverBase (parent), type_seg_failed_flag (false) + {} + + std::string path_buffer; + bool type_seg_failed_flag; +}; + class ResolveType : public ResolverBase { public: @@ -63,16 +110,8 @@ public: void visit (AST::TypePath &path) { - // this will need changed to handle mod/crate/use globs and look - // at the segments in granularity - if (!resolver->get_type_scope ().lookup (path.as_string (), &resolved_node)) - { - rust_error_at (path.get_locus (), "failed to resolve TypePath: %s", - path.as_string ().c_str ()); - return; - } - - ok = true; + resolved_node = ResolveTypePath::go (path, parent); + ok = resolved_node != UNKNOWN_NODEID; resolver->insert_resolved_type (path.get_node_id (), resolved_node); resolver->insert_new_definition (path.get_node_id (), Definition{path.get_node_id (), parent}); @@ -97,6 +136,40 @@ private: bool ok; }; +class ResolveGenericParam : public ResolverBase +{ +public: + static NodeId go (AST::GenericParam *param, NodeId parent) + { + ResolveGenericParam resolver (parent); + param->accept_vis (resolver); + if (!resolver.ok) + rust_error_at (param->get_locus_slow (), "unresolved generic parameter"); + + return resolver.resolved_node; + }; + + void visit (AST::TypeParam ¶m) override + { + ok = true; + + // for now lets focus on handling the basics: like struct<T> { a:T, ....} + resolver->get_type_scope ().insert ( + param.get_type_representation (), param.get_node_id (), + param.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (param.get_locus (), + "generic param redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); + } + +private: + ResolveGenericParam (NodeId parent) : ResolverBase (parent), ok (false) {} + + bool ok; +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index ddba7f2..6bc356a 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -368,5 +368,103 @@ ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field) ResolveExpr::go (&expr, field.get_node_id ()); } +// rust-ast-resolve-type.h + +void +ResolveTypePath::visit (AST::TypePathSegmentGeneric &seg) +{ + AST::GenericArgs &generics = seg.get_generic_args (); + for (auto > : generics.get_type_args ()) + ResolveType::go (gt.get (), UNKNOWN_NODEID); + + if (seg.is_error ()) + { + type_seg_failed_flag = true; + rust_error_at (Location (), "segment has error: %s", + seg.as_string ().c_str ()); + return; + } + + if (seg.get_separating_scope_resolution ()) + path_buffer += "::"; + + path_buffer += seg.get_ident_segment ().as_string (); +} + +void +ResolveTypePath::visit (AST::TypePathSegment &seg) +{ + if (seg.is_error ()) + { + type_seg_failed_flag = true; + rust_error_at (Location (), "segment has error: %s", + seg.as_string ().c_str ()); + return; + } + + if (seg.get_separating_scope_resolution ()) + path_buffer += "::"; + + path_buffer += seg.get_ident_segment ().as_string (); +} + +// rust-ast-resolve-expr.h + +void +ResolvePath::resolve_path (AST::PathInExpression *expr) +{ + // this needs extended similar to the TypePath to lookup each segment + // in turn then look its rib for the next segment and so forth until we + // resolve to a final NodeId generic args can be ignored + std::string path_buf; + for (auto &seg : expr->get_segments ()) + { + auto s = seg.get_ident_segment (); + if (s.is_error () && !seg.has_generic_args ()) + { + rust_error_at (expr->get_locus (), "malformed path"); + return; + } + + if (seg.has_generic_args ()) + { + AST::GenericArgs &args = seg.get_generic_args (); + for (auto > : args.get_type_args ()) + ResolveType::go (gt.get (), UNKNOWN_NODEID); + } + + if (!s.is_error ()) + { + bool needs_sep = !path_buf.empty (); + if (needs_sep) + path_buf += "::"; + + path_buf += s.as_string (); + } + } + + // name scope first + if (resolver->get_name_scope ().lookup (path_buf, &resolved_node)) + { + resolver->insert_resolved_name (expr->get_node_id (), resolved_node); + resolver->insert_new_definition (expr->get_node_id (), + Definition{expr->get_node_id (), + parent}); + } + // check the type scope + else if (resolver->get_type_scope ().lookup (path_buf, &resolved_node)) + { + resolver->insert_resolved_type (expr->get_node_id (), resolved_node); + resolver->insert_new_definition (expr->get_node_id (), + Definition{expr->get_node_id (), + parent}); + } + else + { + rust_error_at (expr->get_locus (), "unknown path %s", + expr->as_string ().c_str (), path_buf.c_str ()); + } +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 4df813b..7cb24d8 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1200,27 +1200,10 @@ Gcc_backend::named_type (const std::string &name, Btype *btype, if (type == error_mark_node) return this->error_type (); - // The middle-end expects a basic type to have a name. In Go every - // basic type will have a name. The first time we see a basic type, - // give it whatever Go name we have at this point. - if (TYPE_NAME (type) == NULL_TREE - && location.gcc_location () == BUILTINS_LOCATION - && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE - || TREE_CODE (type) == COMPLEX_TYPE - || TREE_CODE (type) == BOOLEAN_TYPE)) - { - tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, - get_identifier_from_string (name), type); - TYPE_NAME (type) = decl; - return this->make_type (type); - } - - tree copy = build_variant_type_copy (type); tree decl = build_decl (location.gcc_location (), TYPE_DECL, - get_identifier_from_string (name), copy); - DECL_ORIGINAL_TYPE (decl) = type; - TYPE_NAME (copy) = decl; - return this->make_type (copy); + get_identifier_from_string (name), type); + TYPE_NAME (type) = decl; + return this->make_type (type); } // Return a pointer type used as a marker for a circular type. diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 8747391..525381f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -32,9 +32,8 @@ class TypeCheckStructExpr : public TypeCheckBase public: static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr) { - TypeCheckStructExpr resolver; + TypeCheckStructExpr resolver (expr); expr->accept_vis (resolver); - rust_assert (resolver.resolved != nullptr); return resolver.resolved; } @@ -49,13 +48,18 @@ public: void visit (HIR::StructExprFieldIdentifier &field); private: - TypeCheckStructExpr () - : TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr) + TypeCheckStructExpr (HIR::Expr *e) + : TypeCheckBase (), + resolved (new TyTy::ErrorType (e->get_mappings ().get_hirid ())), + struct_path_resolved (nullptr) {} + // result TyTy::BaseType *resolved; + + // internal state: TyTy::ADTType *struct_path_resolved; - TyTy::BaseType *resolved_field; + TyTy::BaseType *resolved_field_value_expr; std::set<std::string> fields_assigned; std::map<size_t, HIR::StructExprField *> adtFieldIndexToField; }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index c82abaa..a7fa604 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -40,6 +40,20 @@ public: void visit (HIR::TupleStruct &struct_decl) { + std::vector<TyTy::SubstitionMapping> substitions; + if (struct_decl.has_generics ()) + { + for (auto &generic_param : struct_decl.get_generic_params ()) + { + auto param_type + = TypeResolveGenericParam::Resolve (generic_param.get ()); + context->insert_type (generic_param->get_mappings (), param_type); + + substitions.push_back ( + TyTy::SubstitionMapping (generic_param, param_type)); + } + } + std::vector<TyTy::StructFieldType *> fields; size_t idx = 0; @@ -57,13 +71,29 @@ public: TyTy::BaseType *type = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), - struct_decl.get_identifier (), std::move (fields)); + mappings->get_next_hir_id (), + struct_decl.get_identifier (), std::move (fields), + std::move (substitions)); context->insert_type (struct_decl.get_mappings (), type); } void visit (HIR::StructStruct &struct_decl) { + std::vector<TyTy::SubstitionMapping> substitions; + if (struct_decl.has_generics ()) + { + for (auto &generic_param : struct_decl.get_generic_params ()) + { + auto param_type + = TypeResolveGenericParam::Resolve (generic_param.get ()); + context->insert_type (generic_param->get_mappings (), param_type); + + substitions.push_back ( + TyTy::SubstitionMapping (generic_param, param_type)); + } + } + std::vector<TyTy::StructFieldType *> fields; struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool { TyTy::BaseType *field_type @@ -78,7 +108,9 @@ public: TyTy::BaseType *type = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), - struct_decl.get_identifier (), std::move (fields)); + mappings->get_next_hir_id (), + struct_decl.get_identifier (), std::move (fields), + std::move (substitions)); context->insert_type (struct_decl.get_mappings (), type); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 21f93fb..1592e22 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -62,6 +62,29 @@ private: size_t result; }; // namespace Resolver +class TypeCheckResolveGenericArguments : public TypeCheckBase +{ +public: + static HIR::GenericArgs resolve (HIR::TypePathSegment *segment) + { + TypeCheckResolveGenericArguments resolver; + segment->accept_vis (resolver); + return resolver.args; + }; + + void visit (HIR::TypePathSegmentGeneric &generic) override + { + args = generic.get_generic_args (); + } + +private: + TypeCheckResolveGenericArguments () + : TypeCheckBase (), args (HIR::GenericArgs::create_empty ()) + {} + + HIR::GenericArgs args; +}; + class TypeCheckType : public TypeCheckBase { public: @@ -71,11 +94,7 @@ public: type->accept_vis (resolver); if (resolver.translated == nullptr) - { - rust_error_at (Location (), "failed to translate %s", - type->as_string ().c_str ()); - return new TyTy::ErrorType (type->get_mappings ().get_hirid ()); - } + return new TyTy::ErrorType (type->get_mappings ().get_hirid ()); resolver.context->insert_type (type->get_mappings (), resolver.translated); return resolver.translated; @@ -156,10 +175,65 @@ public: translated = translated->clone (); auto ref = path.get_mappings ().get_hirid (); translated->set_ref (ref); + + HIR::TypePathSegment *final_seg = path.get_final_segment (); + HIR::GenericArgs args + = TypeCheckResolveGenericArguments::resolve (final_seg); + + bool path_declared_generic_arguments = !args.is_empty (); + if (path_declared_generic_arguments) + { + if (translated->has_subsititions_defined ()) + { + // so far we only support ADT so lets just handle it here + // for now + if (translated->get_kind () != TyTy::TypeKind::ADT) + { + rust_error_at ( + path.get_locus (), + "unsupported type for generic substitution: %s", + translated->as_string ().c_str ()); + return; + } + + TyTy::ADTType *adt + = static_cast<TyTy::ADTType *> (translated); + translated = adt->handle_substitions (args); + } + else + { + rust_error_at ( + path.get_locus (), + "TypePath %s declares generic argument's but " + "the type %s does not have any", + path.as_string ().c_str (), + translated->as_string ().c_str ()); + return; + } + } + else if (translated->supports_substitions ()) + { + // so far we only support ADT so lets just handle it here + // for now + if (translated->get_kind () != TyTy::TypeKind::ADT) + { + rust_error_at ( + path.get_locus (), + "unsupported type for generic substitution: %s", + translated->as_string ().c_str ()); + return; + } + + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (translated); + translated = adt->infer_substitions (); + } + return; } } - gcc_unreachable (); + + rust_error_at (path.get_locus (), "failed to resolve TypePath: %s", + path.as_string ().c_str ()); } void visit (HIR::ArrayType &type) @@ -197,6 +271,36 @@ private: TyTy::BaseType *translated; }; +class TypeResolveGenericParam : public TypeCheckBase +{ +public: + static TyTy::ParamType *Resolve (HIR::GenericParam *param) + { + TypeResolveGenericParam resolver; + param->accept_vis (resolver); + + if (resolver.resolved == nullptr) + { + rust_error_at (param->get_locus_slow (), + "failed to setup generic parameter"); + return nullptr; + } + + return resolver.resolved; + } + + void visit (HIR::TypeParam ¶m) override + { + resolved = new TyTy::ParamType (param.get_type_representation (), + param.get_mappings ().get_hirid (), param); + } + +private: + TypeResolveGenericParam () : TypeCheckBase (), resolved (nullptr) {} + + TyTy::ParamType *resolved; +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index a43dcf6..69f13db 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -158,14 +158,15 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) return; } - resolved = struct_path_resolved; + TyTy::ADTType *struct_def = struct_path_resolved; if (struct_expr.has_struct_base ()) { TyTy::BaseType *base_resolved = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get (), false); - resolved = struct_path_resolved->unify (base_resolved); - if (resolved == nullptr) + struct_def + = (TyTy::ADTType *) struct_path_resolved->unify (base_resolved); + if (struct_def == nullptr) { rust_fatal_error ( struct_expr.struct_base->base_struct->get_locus_slow (), @@ -174,11 +175,12 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) } } + std::vector<TyTy::StructFieldType *> infered_fields; bool ok = true; struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool { - resolved_field = nullptr; + resolved_field_value_expr = nullptr; field->accept_vis (*this); - if (resolved_field == nullptr) + if (resolved_field_value_expr == nullptr) { rust_fatal_error (field->get_locus (), "failed to resolve type for field"); @@ -186,13 +188,17 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) return false; } - context->insert_type (field->get_mappings (), resolved_field); + context->insert_type (field->get_mappings (), resolved_field_value_expr); return true; }); // something failed setting up the fields if (!ok) - return; + { + rust_error_at (struct_expr.get_locus (), + "constructor type resolution failure"); + return; + } // check the arguments are all assigned and fix up the ordering if (fields_assigned.size () != struct_path_resolved->num_fields ()) @@ -270,6 +276,8 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) std::unique_ptr<HIR::StructExprField> (adtFieldIndexToField[i])); } struct_expr.set_fields_as_owner (std::move (ordered_fields)); + + resolved = struct_def; } void @@ -315,7 +323,16 @@ TypeCheckStructExpr::visit (HIR::PathInExpression &expr) "expected an ADT type"); return; } - struct_path_resolved = (TyTy::ADTType *) lookup; + + struct_path_resolved = static_cast<TyTy::ADTType *> (lookup); + if (struct_path_resolved->has_substitions ()) + { + HIR::PathExprSegment seg = expr.get_final_segment (); + struct_path_resolved + = seg.has_generic_args () + ? struct_path_resolved->handle_substitions (seg.get_generic_args ()) + : struct_path_resolved->infer_substitions (); + } } void @@ -329,7 +346,6 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) } size_t field_index; - TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value (), false); TyTy::StructFieldType *field_type = struct_path_resolved->get_field (field.field_name, &field_index); if (field_type == nullptr) @@ -338,8 +354,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) return; } - resolved_field = field_type->get_field_type ()->unify (value); - if (resolved_field != nullptr) + TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value (), false); + resolved_field_value_expr = field_type->get_field_type ()->unify (value); + if (resolved_field_value_expr != nullptr) { fields_assigned.insert (field.field_name); adtFieldIndexToField[field_index] = &field; @@ -358,7 +375,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) } size_t field_index; - TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value (), false); + TyTy::StructFieldType *field_type = struct_path_resolved->get_field (field_name, &field_index); if (field_type == nullptr) @@ -367,8 +384,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) return; } - resolved_field = field_type->get_field_type ()->unify (value); - if (resolved_field != nullptr) + TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value (), false); + resolved_field_value_expr = field_type->get_field_type ()->unify (value); + if (resolved_field_value_expr != nullptr) { fields_assigned.insert (field_name); adtFieldIndexToField[field_index] = &field; @@ -400,8 +418,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) field.get_locus ()); TyTy::BaseType *value = TypeCheckExpr::Resolve (&expr, false); - resolved_field = field_type->get_field_type ()->unify (value); - if (resolved_field != nullptr) + resolved_field_value_expr = field_type->get_field_type ()->unify (value); + if (resolved_field_value_expr != nullptr) + { fields_assigned.insert (field.field_name); adtFieldIndexToField[field_index] = &field; diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h index 7e52f65..5bb33c9 100644 --- a/gcc/rust/typecheck/rust-tycheck-dump.h +++ b/gcc/rust/typecheck/rust-tycheck-dump.h @@ -32,11 +32,20 @@ public: { TypeResolverDump dumper; for (auto &item : crate.items) - item->accept_vis (dumper); + { + item->accept_vis (dumper); + dumper.dump += "\n"; + } out << dumper.dump; } + void visit (HIR::StructStruct &struct_decl) override + { + dump += indent () + "struct " + type_string (struct_decl.get_mappings ()) + + "\n"; + } + void visit (HIR::InherentImpl &impl_block) override { dump += indent () + "impl " @@ -177,6 +186,11 @@ public: dump += type_string (expr.get_mappings ()); } + void visit (HIR::StructExprStructFields &expr) override + { + dump += "ctor: " + type_string (expr.get_mappings ()); + } + protected: std::string type_string (const Analysis::NodeMapping &mappings) { @@ -192,8 +206,8 @@ protected: } buf += "]"; - return "<" + lookup->as_string () - + " HIRID: " + std::to_string (mappings.get_hirid ()) + std::string repr = lookup->as_string (); + return "<" + repr + " HIRID: " + std::to_string (mappings.get_hirid ()) + " RF:" + std::to_string (lookup->get_ref ()) + " TF:" + std::to_string (lookup->get_ty_ref ()) + +" - " + buf + ">"; } diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index e1f1a8c..612a5e8 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -42,7 +42,6 @@ public: void visit (UnitType &type) override { gcc_unreachable (); } void visit (InferType &type) override { gcc_unreachable (); } void visit (TupleType &type) override { gcc_unreachable (); } - void visit (StructFieldType &type) override { gcc_unreachable (); } void visit (ArrayType &type) override { gcc_unreachable (); } void visit (BoolType &type) override { gcc_unreachable (); } void visit (IntType &type) override { gcc_unreachable (); } @@ -53,6 +52,7 @@ public: void visit (ErrorType &type) override { gcc_unreachable (); } void visit (CharType &type) override { gcc_unreachable (); } void visit (ReferenceType &type) override { gcc_unreachable (); } + void visit (ParamType &) override { gcc_unreachable (); } // tuple-structs void visit (ADTType &type) override; @@ -86,7 +86,6 @@ public: void visit (UnitType &type) override { gcc_unreachable (); } void visit (InferType &type) override { gcc_unreachable (); } void visit (TupleType &type) override { gcc_unreachable (); } - void visit (StructFieldType &type) override { gcc_unreachable (); } void visit (ArrayType &type) override { gcc_unreachable (); } void visit (BoolType &type) override { gcc_unreachable (); } void visit (IntType &type) override { gcc_unreachable (); } @@ -98,6 +97,7 @@ public: void visit (ADTType &type) override { gcc_unreachable (); }; void visit (CharType &type) override { gcc_unreachable (); } void visit (ReferenceType &type) override { gcc_unreachable (); } + void visit (ParamType &) override { gcc_unreachable (); } // call fns void visit (FnType &type) override; diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 2479378..ef7a60c 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -55,8 +55,17 @@ public: This method is meant to be used internally by Ty. If you're trying to unify two ty, you can simply call `unify` on ty themselves. */ - BaseType *unify (BaseType *other) + virtual BaseType *unify (BaseType *other) { + if (other->get_kind () == TypeKind::PARAM) + { + ParamType *p = static_cast<ParamType *> (other); + if (p->can_resolve ()) + { + other = p->resolve (); + } + } + other->accept_vis (*this); if (resolved != nullptr) { @@ -197,7 +206,7 @@ public: type.as_string ().c_str ()); } - virtual void visit (StructFieldType &type) override + virtual void visit (CharType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", @@ -205,7 +214,7 @@ public: type.as_string ().c_str ()); } - virtual void visit (CharType &type) override + virtual void visit (ReferenceType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); rust_error_at (ref_locus, "expected [%s] got [%s]", @@ -213,12 +222,13 @@ public: type.as_string ().c_str ()); } - virtual void visit (ReferenceType &type) override + virtual void visit (ParamType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (ref_locus, "expected [%s] got [%s]", + rust_error_at (ref_locus, "expected [%s] got [ParamTy <%s>]", get_base ()->as_string ().c_str (), type.as_string ().c_str ()); + gcc_unreachable (); } protected: @@ -461,28 +471,6 @@ private: InferType *base; }; -class StructFieldTypeRules : public BaseRules -{ -public: - StructFieldTypeRules (StructFieldType *base) : BaseRules (base), base (base) - {} - - void visit (StructFieldType &type) - { - BaseType *ty = base->get_field_type ()->unify (type.get_field_type ()); - if (ty == nullptr) - return; - - resolved = new TyTy::StructFieldType (type.get_ref (), type.get_ty_ref (), - type.get_name (), ty); - } - -private: - BaseType *get_base () override { return base; } - - StructFieldType *base; -}; - class UnitRules : public BaseRules { public: @@ -718,7 +706,7 @@ class ADTRules : public BaseRules public: ADTRules (ADTType *base) : BaseRules (base), base (base) {} - void visit (ADTType &type) + void visit (ADTType &type) override { if (base->num_fields () != type.num_fields ()) { @@ -726,24 +714,23 @@ public: return; } - std::vector<TyTy::StructFieldType *> fields; for (size_t i = 0; i < type.num_fields (); ++i) { TyTy::StructFieldType *base_field = base->get_field (i); TyTy::StructFieldType *other_field = type.get_field (i); - BaseType *unified_ty = base_field->unify (other_field); + TyTy::BaseType *this_field_ty = base_field->get_field_type (); + TyTy::BaseType *other_field_ty = other_field->get_field_type (); + + BaseType *unified_ty = this_field_ty->unify (other_field_ty); if (unified_ty == nullptr) { BaseRules::visit (type); return; } - - fields.push_back ((TyTy::StructFieldType *) unified_ty); } - resolved = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (), - type.get_name (), fields); + resolved = base->clone (); } private: @@ -889,6 +876,46 @@ private: ReferenceType *base; }; +class ParamRules : public BaseRules +{ +public: + ParamRules (ParamType *base) : BaseRules (base), 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 + BaseType *unify (BaseType *other) override final + { + if (base->get_ref () == base->get_ty_ref ()) + { + Location locus = mappings->lookup_location (base->get_ref ()); + rust_fatal_error (locus, + "invalid use of unify with ParamTy [%s] and [%s]", + base->as_string ().c_str (), + other->as_string ().c_str ()); + return nullptr; + } + + auto context = Resolver::TypeCheckContext::get (); + BaseType *lookup = nullptr; + bool ok = context->lookup_type (base->get_ty_ref (), &lookup); + rust_assert (ok); + + return lookup->unify (other); + } + +private: + BaseType *get_base () override { return base; } + + ParamType *base; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 6609605..b49085d 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -29,7 +29,6 @@ class TyVisitor public: virtual void visit (UnitType &type) = 0; virtual void visit (InferType &type) = 0; - virtual void visit (StructFieldType &type) = 0; virtual void visit (ADTType &type) = 0; virtual void visit (TupleType &type) = 0; virtual void visit (FnType &type) = 0; @@ -43,6 +42,7 @@ public: virtual void visit (ErrorType &type) = 0; virtual void visit (CharType &type) = 0; virtual void visit (ReferenceType &type) = 0; + virtual void visit (ParamType &type) = 0; }; } // namespace TyTy diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 66b87e3..89507c7 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -20,7 +20,9 @@ #include "rust-tyty-visitor.h" #include "rust-tyty-call.h" #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-type.h" #include "rust-tyty-rules.h" +#include "rust-hir-map.h" namespace Rust { namespace TyTy { @@ -100,8 +102,6 @@ ErrorType::as_string () const BaseType * ErrorType::unify (BaseType *other) { - // FIXME - // rust_error_at (); return this; } @@ -111,45 +111,24 @@ ErrorType::clone () return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ()); } -void -StructFieldType::accept_vis (TyVisitor &vis) -{ - vis.visit (*this); -} - std::string StructFieldType::as_string () const { return name + ":" + ty->as_string (); } -BaseType * -StructFieldType::unify (BaseType *other) -{ - StructFieldTypeRules r (this); - return r.unify (other); -} - bool -StructFieldType::is_equal (const BaseType &other) const +StructFieldType::is_equal (const StructFieldType &other) const { - if (get_kind () != other.get_kind ()) - { - return false; - } - else - { - auto other2 = static_cast<const StructFieldType &> (other); - return get_field_type () == other2.get_field_type (); - } + return get_name ().compare (other.get_name ()) == 0 + && get_field_type ()->is_equal (*other.get_field_type ()); } -BaseType * -StructFieldType::clone () +StructFieldType * +StructFieldType::clone () const { - return new StructFieldType (get_ref (), get_ty_ref (), get_name (), - get_field_type ()->clone (), - get_combined_refs ()); + return new StructFieldType (get_ref (), get_name (), + get_field_type ()->clone ()); } void @@ -161,15 +140,35 @@ ADTType::accept_vis (TyVisitor &vis) std::string ADTType::as_string () const { - // if (num_fields () == 0) - // return identifier; + if (num_fields () == 0) + return identifier; + + std::string fields_buffer; + for (size_t i = 0; i < num_fields (); ++i) + { + fields_buffer += get_field (i)->as_string (); + if ((i + 1) < num_fields ()) + fields_buffer += ", "; + } + + return identifier + subst_as_string () + "{" + fields_buffer + "}"; +} - // std::string fields_buffer; - // for (auto &field : fields) - // fields_buffer += field->as_string () + ", "; +const StructFieldType * +ADTType::get_field (size_t index) const +{ + return fields.at (index); +} - // return identifier + "{" + fields_buffer + "}"; - return identifier; +const BaseType * +ADTType::get_field_type (size_t index) const +{ + const StructFieldType *ref = get_field (index); + auto context = Resolver::TypeCheckContext::get (); + BaseType *lookup = nullptr; + bool ok = context->lookup_type (ref->get_field_type ()->get_ref (), &lookup); + rust_assert (ok); + return lookup; } BaseType * @@ -183,25 +182,19 @@ bool ADTType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) + return false; + + auto other2 = static_cast<const ADTType &> (other); + if (num_fields () != other2.num_fields ()) + return false; + + for (size_t i = 0; i < num_fields (); i++) { - return false; - } - else - { - auto other2 = static_cast<const ADTType &> (other); - if (num_fields () != other2.num_fields ()) - { - return false; - } - for (size_t i = 0; i < num_fields (); i++) - { - if (!get_field (i)->is_equal (*other2.get_field (i))) - { - return false; - } - } - return true; + if (!get_field (i)->is_equal (*other2.get_field (i))) + return false; } + + return true; } BaseType * @@ -211,8 +204,93 @@ ADTType::clone () for (auto &f : fields) cloned_fields.push_back ((StructFieldType *) f->clone ()); - return new ADTType (get_ref (), get_ty_ref (), get_name (), cloned_fields, - get_combined_refs ()); + return new ADTType (get_ref (), get_ty_ref (), identifier, cloned_fields, + clone_substs (), get_combined_refs ()); +} + +ADTType * +ADTType::infer_substitions () +{ + auto context = Resolver::TypeCheckContext::get (); + ADTType *adt = static_cast<ADTType *> (clone ()); + + for (auto &sub : adt->get_substs ()) + { + // generate an new inference variable + InferType *infer = new InferType (mappings->get_next_hir_id (), + InferType::InferTypeKind::GENERAL); + context->insert_type ( + Analysis::NodeMapping (mappings->get_current_crate (), UNKNOWN_NODEID, + infer->get_ref (), UNKNOWN_LOCAL_DEFID), + infer); + + sub.fill_param_ty (infer); + adt->fill_in_params_for (sub, infer); + } + + // generate new ty ref id since this is an instantiate of the generic + adt->set_ty_ref (mappings->get_next_hir_id ()); + + return adt; +} + +ADTType * +ADTType::handle_substitions (HIR::GenericArgs &generic_args) +{ + if (generic_args.get_type_args ().size () != get_num_substitions ()) + { + rust_error_at (generic_args.get_locus (), + "invalid number of generic arguments to generic ADT type"); + return nullptr; + } + + ADTType *adt = static_cast<ADTType *> (clone ()); + size_t index = 0; + for (auto &arg : generic_args.get_type_args ()) + { + BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ()); + if (resolved == nullptr) + { + rust_error_at (generic_args.get_locus (), + "failed to resolve type arguments"); + return nullptr; + } + + adt->fill_in_at (index, resolved); + index++; + } + + // generate new ty ref id since this is an instantiate of the generic + adt->set_ty_ref (mappings->get_next_hir_id ()); + + return adt; +} + +void +ADTType::fill_in_at (size_t index, BaseType *type) +{ + SubstitionMapping sub = get_substition_mapping_at (index); + SubstitionRef<ADTType>::fill_in_at (index, type); + fill_in_params_for (sub, type); +} + +void +ADTType::fill_in_params_for (SubstitionMapping sub, BaseType *type) +{ + iterate_fields ([&] (StructFieldType *field) mutable -> bool { + bool is_param_ty = field->get_field_type ()->get_kind () == TypeKind::PARAM; + if (!is_param_ty) + return true; + + const ParamType *pp = sub.get_param_ty (); + ParamType *p = static_cast<ParamType *> (field->get_field_type ()); + + // for now let just see what symbols match up for the substitution + if (p->get_symbol ().compare (pp->get_symbol ()) == 0) + p->set_ty_ref (type->get_ref ()); + + return true; + }); } void @@ -637,14 +715,10 @@ bool ReferenceType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) - { - return false; - } - else - { - auto other2 = static_cast<const ReferenceType &> (other); - return get_base () == other2.get_base (); - } + return false; + + auto other2 = static_cast<const ReferenceType &> (other); + return get_base ()->is_equal (*other2.get_base ()); } const BaseType * @@ -674,6 +748,57 @@ ReferenceType::clone () get_combined_refs ()); } +void +ParamType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +ParamType::as_string () const +{ + if (get_ref () == get_ty_ref ()) + return get_symbol (); + + auto context = Resolver::TypeCheckContext::get (); + BaseType *lookup = nullptr; + bool ok = context->lookup_type (get_ty_ref (), &lookup); + rust_assert (ok); + + return lookup->as_string (); +} + +BaseType * +ParamType::unify (BaseType *other) +{ + ParamRules r (this); + return r.unify (other); +} + +BaseType * +ParamType::clone () +{ + return new ParamType (get_symbol (), get_ref (), get_ty_ref (), + get_generic_param (), get_combined_refs ()); +} + +std::string +ParamType::get_symbol () const +{ + return symbol; +} + +BaseType * +ParamType::resolve () +{ + auto context = Resolver::TypeCheckContext::get (); + BaseType *lookup = nullptr; + bool ok = context->lookup_type (get_ty_ref (), &lookup); + rust_assert (ok); + + return lookup; +} + // rust-tyty-call.h void diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 12a3bd5..50fc352 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -42,7 +42,6 @@ enum TypeKind UINT, FLOAT, UNIT, - FIELD, USIZE, ISIZE, // there are more to add... @@ -68,6 +67,8 @@ public: virtual std::string as_string () const = 0; + virtual std::string get_name () const = 0; + /* Unify two types. Returns a pointer to the newly-created unified ty, or nullptr if the two ty cannot be unified. The caller is responsible for releasing the memory of the returned ty. */ @@ -90,21 +91,28 @@ public: * releasing the memory of the returned ty. */ virtual BaseType *clone () = 0; + // get_combined_refs returns the chain of node refs involved in unification std::set<HirId> get_combined_refs () { return combined; } void append_reference (HirId id) { combined.insert (id); } + virtual bool supports_substitions () const { return false; } + + virtual bool has_subsititions_defined () const { return false; } + protected: BaseType (HirId ref, HirId ty_ref, TypeKind kind, std::set<HirId> refs = std::set<HirId> ()) - : kind (kind), ref (ref), ty_ref (ty_ref), combined (refs) + : kind (kind), ref (ref), ty_ref (ty_ref), combined (refs), + mappings (Analysis::Mappings::get ()) {} TypeKind kind; HirId ref; HirId ty_ref; - std::set<HirId> combined; + + Analysis::Mappings *mappings; }; class InferType : public BaseType @@ -129,7 +137,7 @@ public: void accept_vis (TyVisitor &vis) override; - bool is_unit () const override { return true; } + bool is_unit () const override { return false; } std::string as_string () const override; @@ -139,6 +147,8 @@ public: InferTypeKind get_infer_kind () const { return infer_kind; } + std::string get_name () const override final { return as_string (); } + private: InferTypeKind infer_kind; }; @@ -163,6 +173,8 @@ public: BaseType *unify (BaseType *other) override; BaseType *clone () final override; + + std::string get_name () const override final { return as_string (); } }; class UnitType : public BaseType @@ -185,38 +197,31 @@ public: BaseType *unify (BaseType *other) override; BaseType *clone () final override; + + std::string get_name () const override final { return as_string (); } }; -class StructFieldType : public BaseType +class StructFieldType { public: - StructFieldType (HirId ref, std::string name, BaseType *ty, - std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::FIELD, refs), name (name), ty (ty) - {} - - StructFieldType (HirId ref, HirId ty_ref, std::string name, BaseType *ty, - std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::FIELD, refs), name (name), ty (ty) + StructFieldType (HirId ref, std::string name, BaseType *ty) + : ref (ref), name (name), ty (ty) {} - void accept_vis (TyVisitor &vis) override; - - bool is_unit () const override { return ty->is_unit (); } - - std::string as_string () const override; + HirId get_ref () const { return ref; } - BaseType *unify (BaseType *other) override; + std::string as_string () const; - virtual bool is_equal (const BaseType &other) const override; + bool is_equal (const StructFieldType &other) const; std::string get_name () const { return name; } BaseType *get_field_type () const { return ty; } - BaseType *clone () final override; + StructFieldType *clone () const; private: + HirId ref; std::string name; BaseType *ty; }; @@ -225,6 +230,7 @@ class TupleType : public BaseType { public: TupleType (HirId ref, std::vector<HirId> fields, + std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ref, TypeKind::TUPLE, refs), fields (fields) {} @@ -259,24 +265,148 @@ public: } } + std::string get_name () const override final { return as_string (); } + private: std::vector<HirId> fields; }; -class ADTType : public BaseType +class ParamType : public BaseType +{ +public: + ParamType (std::string symbol, HirId ref, HIR::GenericParam ¶m, + std::set<HirId> refs = std::set<HirId> ()) + : BaseType (ref, ref, TypeKind::PARAM), symbol (symbol), param (param) + {} + + ParamType (std::string symbol, HirId ref, HirId ty_ref, + HIR::GenericParam ¶m, + std::set<HirId> refs = std::set<HirId> ()) + : BaseType (ref, ty_ref, TypeKind::PARAM), symbol (symbol), param (param) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + BaseType *unify (BaseType *other) override; + + BaseType *clone () final override; + + std::string get_symbol () const; + + HIR::GenericParam &get_generic_param () { return param; } + + bool can_resolve () const { return get_ref () != get_ty_ref (); } + + BaseType *resolve (); + + std::string get_name () const override final { return as_string (); } + +private: + std::string symbol; + HIR::GenericParam ¶m; +}; + +class SubstitionMapping +{ +public: + SubstitionMapping (std::unique_ptr<HIR::GenericParam> &generic, + ParamType *param) + : generic (generic), param (param) + {} + + std::string as_string () const { return param->as_string (); } + + void fill_param_ty (BaseType *type) { param->set_ty_ref (type->get_ref ()); } + + SubstitionMapping clone () + { + return SubstitionMapping (generic, + static_cast<ParamType *> (param->clone ())); + } + + const ParamType *get_param_ty () const { return param; } + +private: + std::unique_ptr<HIR::GenericParam> &generic; + ParamType *param; +}; + +template <class T> class SubstitionRef +{ +public: + SubstitionRef (std::vector<SubstitionMapping> substitions) + : substitions (substitions) + {} + + bool has_substitions () const { return substitions.size () > 0; } + + std::string subst_as_string () const + { + std::string buffer; + for (size_t i = 0; i < substitions.size (); i++) + { + const SubstitionMapping &sub = substitions.at (i); + buffer += sub.as_string (); + + if ((i + 1) < substitions.size ()) + buffer += ", "; + } + + return buffer.empty () ? "" : "<" + buffer + ">"; + } + + size_t get_num_substitions () const { return substitions.size (); } + + std::vector<SubstitionMapping> &get_substs () { return substitions; } + + std::vector<SubstitionMapping> clone_substs () + { + std::vector<SubstitionMapping> clone; + for (auto &sub : substitions) + clone.push_back (sub.clone ()); + + return clone; + } + + virtual T *infer_substitions () = 0; + + virtual T *handle_substitions (HIR::GenericArgs &generic_args) = 0; + +protected: + virtual void fill_in_at (size_t index, BaseType *type) + { + substitions.at (index).fill_param_ty (type); + } + + SubstitionMapping get_substition_mapping_at (size_t index) + { + return substitions.at (index); + } + +private: + std::vector<SubstitionMapping> substitions; +}; + +class ADTType : public BaseType, public SubstitionRef<ADTType> { public: ADTType (HirId ref, std::string identifier, std::vector<StructFieldType *> fields, + std::vector<SubstitionMapping> subst_refs, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ref, TypeKind::ADT, refs), identifier (identifier), + : BaseType (ref, ref, TypeKind::ADT, refs), + SubstitionRef (std::move (subst_refs)), identifier (identifier), fields (fields) {} ADTType (HirId ref, HirId ty_ref, std::string identifier, std::vector<StructFieldType *> fields, + std::vector<SubstitionMapping> subst_refs, std::set<HirId> refs = std::set<HirId> ()) - : BaseType (ref, ty_ref, TypeKind::ADT, refs), identifier (identifier), + : BaseType (ref, ty_ref, TypeKind::ADT, refs), + SubstitionRef (std::move (subst_refs)), identifier (identifier), fields (fields) {} @@ -292,9 +422,18 @@ public: size_t num_fields () const { return fields.size (); } - std::string get_name () const { return identifier; } + std::string get_name () const override final + { + return identifier + subst_as_string (); + } + + BaseType *get_field_type (size_t index); + + const BaseType *get_field_type (size_t index) const; - StructFieldType *get_field (size_t index) const { return fields.at (index); } + const StructFieldType *get_field (size_t index) const; + + StructFieldType *get_field (size_t index) { return fields.at (index); } StructFieldType *get_field (const std::string &lookup, size_t *index = nullptr) const @@ -327,6 +466,21 @@ public: } } + bool supports_substitions () const override final { return true; } + + bool has_subsititions_defined () const override final + { + return has_substitions (); + } + + ADTType *infer_substitions () override final; + + ADTType *handle_substitions (HIR::GenericArgs &generic_args) override final; + + void fill_in_at (size_t index, BaseType *type) override final; + + void fill_in_params_for (SubstitionMapping sub, BaseType *type); + private: std::string identifier; std::vector<StructFieldType *> fields; @@ -352,6 +506,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *return_type () { return type; } BaseType *unify (BaseType *other) override; @@ -408,6 +564,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; virtual bool is_equal (const BaseType &other) const override; @@ -440,6 +598,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; BaseType *clone () final override; @@ -470,6 +630,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; IntKind get_kind () const { return int_kind; } @@ -505,6 +667,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; UintKind get_kind () const { return uint_kind; } @@ -538,6 +702,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; FloatKind get_kind () const { return float_kind; } @@ -563,6 +729,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; BaseType *clone () final override; @@ -583,6 +751,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; BaseType *clone () final override; @@ -604,6 +774,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; BaseType *clone () final override; @@ -630,6 +802,8 @@ public: std::string as_string () const override; + std::string get_name () const override final { return as_string (); } + BaseType *unify (BaseType *other) override; virtual bool is_equal (const BaseType &other) const override; diff --git a/gcc/testsuite/rust.test/compilable/generics1.rs b/gcc/testsuite/rust.test/compilable/generics1.rs new file mode 100644 index 0000000..8a2965a --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/generics1.rs @@ -0,0 +1,41 @@ +struct Foo { + a: f32, + b: bool, +} + +struct GenericStruct<T> { + a: T, + b: usize, +} + +fn main() { + let a1; + a1 = Foo { a: 1.0, b: false }; + + let b1: f32 = a1.a; + let c1: bool = a1.b; + + let a2: GenericStruct<i8>; + a2 = GenericStruct::<i8> { a: 1, b: 456 }; + + let b2: i8 = a2.a; + let c2: usize = a2.b; + + let a3; + a3 = GenericStruct::<i32> { a: 123, b: 456 }; + + let b3: i32 = a3.a; + let c3: usize = a3.b; + + let a4; + a4 = GenericStruct { a: 1.0, b: 456 }; + + let b4: f32 = a4.a; + let c4: usize = a4.b; + + let a5; + a5 = GenericStruct::<_> { a: true, b: 456 }; + + let b5: bool = a5.a; + let c5: usize = a5.b; +} |