diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-02-16 15:40:28 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-03-01 10:35:07 +0000 |
commit | 9af2ae0ff91535da104db0d3828d863770439fad (patch) | |
tree | 57b375ba818f22c70066c87a4d9c2a1c1b78f69e | |
parent | 06bb1d6542a9d07f4d866613a5b039be7bcb5f95 (diff) | |
download | gcc-9af2ae0ff91535da104db0d3828d863770439fad.zip gcc-9af2ae0ff91535da104db0d3828d863770439fad.tar.gz gcc-9af2ae0ff91535da104db0d3828d863770439fad.tar.bz2 |
Support Generic arguments to Structs
This removes StructFieldType from the TyTy base as it is not a type that
can be unified against.
It adds in a substition mapper implementation which will likely change
over time when this this support is extended over to Functions and
TupleStructs.
Note generic argument binding is not supported as part of this yet.
Fixes #235
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; +} |