diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-03-26 15:23:57 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-03-27 18:55:14 +0000 |
commit | e4ea09d6b8e501dc7bd7046da641b70e02814b09 (patch) | |
tree | a01041da77d9276a52d0dbcb08d6a5c3913b03fe | |
parent | 380c8295051c6b42adb4f703268c7465aed57c44 (diff) | |
download | gcc-e4ea09d6b8e501dc7bd7046da641b70e02814b09.zip gcc-e4ea09d6b8e501dc7bd7046da641b70e02814b09.tar.gz gcc-e4ea09d6b8e501dc7bd7046da641b70e02814b09.tar.bz2 |
Add Generic Impl block support
This extends the support from #237 to extend this to MethodCallExpr, this
now follows a similar path to normal CallExprs and ensures the used
arguments in substitution are preserved during unification of types. Part
of method resolution is fixed here by taking advantage if is_equal instead
of unify calls which could result in bad errors which are just part of the
probe process to lookup possible candidates for method resolution.
Fixes #306
-rw-r--r-- | gcc/rust/ast/rust-path.h | 15 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-implitem.h | 15 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 19 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-base.h | 7 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-expr.h | 7 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-item.h | 13 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower.cc | 81 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-full-test.cc | 3 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-path.h | 49 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-method-resolve.h | 20 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 48 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 21 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-substitution-mapper.h | 56 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-call.h | 1 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 7 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 47 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/generics9.rs | 22 |
17 files changed, 304 insertions, 127 deletions
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 81fce57..c8542d9 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -198,6 +198,8 @@ public: std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; } std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; }; + + Location get_locus () { return locus; } }; /* A segment of a path in expression, including an identifier aspect and maybe @@ -206,13 +208,9 @@ class PathExprSegment { // or should this extend PathIdentSegment? private: PathIdentSegment segment_name; - - // bool has_generic_args; GenericArgs generic_args; - Location locus; - - // TODO: does this require visitor? pretty sure not polymorphic + NodeId node_id; public: // Returns true if there are any generic arguments @@ -222,7 +220,8 @@ public: PathExprSegment (PathIdentSegment segment_name, Location locus = Location (), GenericArgs generic_args = GenericArgs::create_empty ()) : segment_name (std::move (segment_name)), - generic_args (std::move (generic_args)), locus (locus) + generic_args (std::move (generic_args)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} /* Constructor for segment with generic arguments (from segment name and all @@ -238,7 +237,7 @@ public: generic_args (GenericArgs (std::move (lifetime_args), std::move (type_args), std::move (binding_args))), - locus (locus) + locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Returns whether path expression segment is in an error state. @@ -262,6 +261,8 @@ public: } PathIdentSegment &get_ident_segment () { return segment_name; } + + NodeId get_node_id () const { return node_id; } }; // AST node representing a pattern that involves a "path" - abstract base class diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index 15aba9b..cee3a3b 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -272,6 +272,21 @@ public: } TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty); + if (fntype->has_subsititions_defined ()) + { + // we cant do anything for this only when it is used + if (concrete == nullptr) + return; + else + { + rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); + fntype = static_cast<TyTy::FnType *> (concrete); + + // override the Hir Lookups for the substituions in this context + fntype->override_context (); + } + } + // convert to the actual function type ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 7b1b2ff..a2f5247 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -122,9 +122,17 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) return; } + // lookup the expected function type + TyTy::BaseType *lookup_fntype = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + expr.get_method_name ().get_mappings ().get_hirid (), &lookup_fntype); + rust_assert (ok); + rust_assert (lookup_fntype->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup_fntype); + // lookup compiled functions Bfunction *fn = nullptr; - if (!ctx->lookup_function_decl (ref, &fn)) + if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) { // this might fail because its a forward decl so we can attempt to // resolve it now @@ -146,8 +154,13 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) return; } - CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true); - if (!ctx->lookup_function_decl (ref, &fn)) + if (!fntype->has_subsititions_defined ()) + CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true); + else + CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true, + fntype); + + if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) { rust_error_at (expr.get_locus (), "forward decl was not compiled"); return; diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index beeff87..b127ec4 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -284,6 +284,13 @@ protected: return HIR::LoopLabel (mapping, std::move (life), loop_label.get_locus ()); } + + std::vector<std::unique_ptr<HIR::GenericParam> > lower_generic_params ( + std::vector<std::unique_ptr<AST::GenericParam> > ¶ms); + + HIR::PathExprSegment lower_path_expr_seg (AST::PathExprSegment &s); + + HIR::GenericArgs lower_generic_args (AST::GenericArgs &args); }; } // namespace HIR diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index b003334..1922a3b 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -40,8 +40,6 @@ public: return folder.ok; } - virtual ~ArrayCapacityConstant () {} - void visit (AST::LiteralExpr &expr) override { switch (expr.get_lit_type ()) @@ -226,9 +224,8 @@ public: { std::vector<HIR::Attribute> outer_attribs; - HIR::PathExprSegment method_path ( - expr.get_method_name ().get_ident_segment ().as_string (), - expr.get_method_name ().get_locus ()); + HIR::PathExprSegment method_path + = lower_path_expr_seg (expr.get_method_name ()); HIR::Expr *receiver = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ()); diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 6f98b23..7f6594d 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -351,19 +351,6 @@ 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.cc b/gcc/rust/hir/rust-ast-lower.cc index b54c5ce..0bacdd2 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -276,32 +276,7 @@ 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); + path_segments.push_back (lower_path_expr_seg (s)); return true; }); @@ -315,5 +290,59 @@ ASTLowerPathInExpression::visit (AST::PathInExpression &expr) expr.opening_scope_resolution ()); } +// rust-ast-lower-base.h + +std::vector<std::unique_ptr<HIR::GenericParam> > +ASTLoweringBase::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; +} + +HIR::PathExprSegment +ASTLoweringBase::lower_path_expr_seg (AST::PathExprSegment &s) +{ + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, s.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + return HIR::PathExprSegment ( + std::move (mapping), + HIR::PathIdentSegment (s.get_ident_segment ().as_string ()), s.get_locus (), + s.has_generic_args () ? lower_generic_args (s.get_generic_args ()) + : HIR::GenericArgs::create_empty ()); +} + +HIR::GenericArgs +ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) +{ + std::vector<HIR::GenericArgsBinding> binding_args; // TODO + + std::vector<HIR::Lifetime> lifetime_args; + for (auto &lifetime : 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 : args.get_type_args ()) + { + HIR::Type *t = ASTLoweringType::translate (type.get ()); + type_args.push_back (std::unique_ptr<HIR::Type> (t)); + } + + return HIR::GenericArgs (std::move (lifetime_args), std::move (type_args), + std::move (binding_args), args.get_locus ()); +} + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index 9d26a0bd..093fcef 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -2692,8 +2692,7 @@ PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const for (const auto &segment : segments) { // return empty path if doesn't meet simple path segment requirements - if (segment.is_error () || segment.has_generic_args () - || segment.as_string () == "Self") + if (segment.has_generic_args () || segment.as_string () == "Self") { return SimplePath::create_empty (); } diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index c4fe0da..2affb68 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -192,53 +192,25 @@ public: /* A segment of a path in expression, including an identifier aspect and maybe * generic args */ class PathExprSegment -{ // or should this extend PathIdentSegment? +{ private: + Analysis::NodeMapping mappings; PathIdentSegment segment_name; - - // bool has_generic_args; GenericArgs generic_args; - Location locus; - // TODO: does this require visitor? pretty sure not polymorphic - public: // Returns true if there are any generic arguments bool has_generic_args () const { return generic_args.has_generic_args (); } // Constructor for segment (from IdentSegment and GenericArgs) - PathExprSegment (PathIdentSegment segment_name, Location locus = Location (), + PathExprSegment (Analysis::NodeMapping mappings, + PathIdentSegment segment_name, Location locus = Location (), GenericArgs generic_args = GenericArgs::create_empty ()) - : segment_name (std::move (segment_name)), + : mappings (std::move (mappings)), segment_name (std::move (segment_name)), generic_args (std::move (generic_args)), locus (locus) {} - /* Constructor for segment with generic arguments (from segment name and all - * args) */ - PathExprSegment (std::string segment_name, Location locus, - std::vector<Lifetime> lifetime_args - = std::vector<Lifetime> (), - std::vector<std::unique_ptr<Type> > type_args - = std::vector<std::unique_ptr<Type> > (), - std::vector<GenericArgsBinding> binding_args - = std::vector<GenericArgsBinding> ()) - : segment_name (PathIdentSegment (std::move (segment_name))), - generic_args (GenericArgs (std::move (lifetime_args), - std::move (type_args), - std::move (binding_args))), - locus (locus) - {} - - // Returns whether path expression segment is in an error state. - bool is_error () const { return segment_name.is_error (); } - - // Creates an error-state path expression segment. - static PathExprSegment create_error () - { - return PathExprSegment (PathIdentSegment::create_error ()); - } - std::string as_string () const; Location get_locus () const { return locus; } @@ -246,6 +218,8 @@ public: PathIdentSegment get_segment () const { return segment_name; } GenericArgs &get_generic_args () { return generic_args; } + + const Analysis::NodeMapping &get_mappings () const { return mappings; } }; // HIR node representing a pattern that involves a "path" - abstract base class @@ -335,6 +309,15 @@ public: bool opening_scope_resolution () { return has_opening_scope_resolution; } + bool is_self () const + { + if (!is_single_segment ()) + return false; + + return get_final_segment ().get_segment ().as_string ().compare ("self") + == 0; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/typecheck/rust-hir-method-resolve.h b/gcc/rust/typecheck/rust-hir-method-resolve.h index 7c472c7..ca5dbe5 100644 --- a/gcc/rust/typecheck/rust-hir-method-resolve.h +++ b/gcc/rust/typecheck/rust-hir-method-resolve.h @@ -22,6 +22,7 @@ #include "rust-hir-type-check-base.h" #include "rust-hir-full.h" #include "rust-tyty.h" +#include "rust-substitution-mapper.h" namespace Rust { namespace Resolver { @@ -66,16 +67,25 @@ public: return; } - // FIXME this can be simplified with - // https://github.com/Rust-GCC/gccrs/issues/187 - auto unified_ty = receiver->unify (self_lookup); - if (unified_ty == nullptr) + if (self_lookup->get_kind () != receiver->get_kind ()) + return; + + if (receiver->has_subsititions_defined () + != self_lookup->has_subsititions_defined ()) + return; + + if (self_lookup->has_subsititions_defined ()) + { + // we assume the receiver should be fully substituted at this stage + self_lookup = SubstMapperFromExisting::Resolve (receiver, self_lookup); + } + + if (!receiver->is_equal (*self_lookup)) { // incompatible self argument then this is not a valid method for this // receiver return; } - delete unified_ty; probed.push_back (&method); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 722f384..836328f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -77,7 +77,7 @@ public: if (resolved->get_kind () == TyTy::TypeKind::TUPLE) { - TyTy::TupleType *tuple = (TyTy::TupleType *) resolved; + TyTy::TupleType *tuple = static_cast<TyTy::TupleType *> (resolved); TupleIndex index = expr.get_tuple_index (); if ((size_t) index >= tuple->num_fields ()) { @@ -98,7 +98,7 @@ public: return; } - TyTy::ADTType *adt = (TyTy::ADTType *) resolved; + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (resolved); TupleIndex index = expr.get_tuple_index (); if ((size_t) index >= adt->num_fields ()) { @@ -115,6 +115,10 @@ public: } infered = field_tyty->get_field_type (); + printf ("ZXZX resolved: %s to: \n", expr.as_string ().c_str ()); + adt->debug (); + infered->debug (); + printf ("ZXZX done\n"); } void visit (HIR::TupleExpr &expr) override @@ -220,14 +224,15 @@ public: { rust_error_at ( expr.get_locus (), - "Generics and Traits are not implemented yet for MethodCall"); + "multiple candidates in MethodCallExpr have been probed is " + "not currently supported"); return; } auto resolved_method = probes.at (0); - TyTy::BaseType *lookup; + TyTy::BaseType *lookup_tyty; if (!context->lookup_type (resolved_method->get_mappings ().get_hirid (), - &lookup)) + &lookup_tyty)) { rust_error_at (resolved_method->get_locus (), "failed to lookup type for CallExpr: %s", @@ -235,20 +240,42 @@ public: return; } - infered = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, context); - if (infered == nullptr) + TyTy::BaseType *lookup = lookup_tyty; + if (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF) + { + TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup); + if (receiver_tyty->get_kind () == TyTy::TypeKind::ADT) + { + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver_tyty); + if (adt->has_substitutions ()) + { + rust_assert (adt->was_substituted ()); + lookup + = fn->handle_substitions (adt->get_substitution_arguments ()); + } + } + } + + TyTy::BaseType *function_ret_tyty + = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, context); + if (function_ret_tyty == nullptr + || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR) { rust_error_at (expr.get_locus (), "failed to lookup type to MethodCallExpr"); return; } - infered->set_ref (expr.get_mappings ().get_hirid ()); + // store the expected fntype + context->insert_type (expr.get_method_name ().get_mappings (), lookup); // set up the resolved name on the path resolver->insert_resolved_name ( expr.get_mappings ().get_nodeid (), resolved_method->get_mappings ().get_nodeid ()); + + // return the result of the function back + infered = function_ret_tyty; } void visit (HIR::AssignmentExpr &expr) override @@ -357,9 +384,7 @@ public: return; } - lookup->append_reference (lookup->get_ref ()); infered = lookup->clone (); - infered->set_ref (expr.get_mappings ().get_hirid ()); } void visit (HIR::LiteralExpr &expr) override @@ -788,6 +813,9 @@ public: return; } + if (expr.is_self ()) + return; + if (infered->has_subsititions_defined ()) { if (!infered->can_substitute ()) diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 9857045..dd62622 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -212,15 +212,12 @@ public: auto expected_ret_tyty = resolve_fn_type->get_return_type (); context->push_return_type (expected_ret_tyty); - auto result + auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ().get (), false); - auto ret_resolved = expected_ret_tyty->unify (result); - if (ret_resolved == nullptr) - return; - - context->peek_return_type ()->append_reference (ret_resolved->get_ref ()); context->pop_return_type (); + + expected_ret_tyty->unify (block_expr_ty); } void visit (HIR::Method &method) override @@ -245,15 +242,15 @@ public: auto expected_ret_tyty = resolve_fn_type->get_return_type (); context->push_return_type (expected_ret_tyty); - auto result - = TypeCheckExpr::Resolve (method.get_function_body ().get (), false); - auto ret_resolved = expected_ret_tyty->unify (result); - if (ret_resolved == nullptr) - return; + printf ("XXXX method body boyo: 1!!\n"); - context->peek_return_type ()->append_reference (ret_resolved->get_ref ()); + auto block_expr_ty + = TypeCheckExpr::Resolve (method.get_definition ().get (), false); context->pop_return_type (); + + expected_ret_tyty->unify (block_expr_ty); + printf ("XXXX method body boyo: 2!!\n"); } private: diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 46adf84..d449c72 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -162,6 +162,62 @@ private: TyTy::SubstitutionArgumentMappings &mappings; }; +class SubstMapperFromExisting : public TyTy::TyVisitor +{ +public: + static TyTy::BaseType *Resolve (TyTy::BaseType *concrete, + TyTy::BaseType *receiver) + { + rust_assert (concrete->get_kind () == receiver->get_kind ()); + + SubstMapperFromExisting mapper (concrete, receiver); + concrete->accept_vis (mapper); + return mapper.resolved; + } + + void visit (TyTy::FnType &type) override + { + rust_assert (type.was_substituted ()); + + TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver); + resolved = to_sub->handle_substitions (type.get_substitution_arguments ()); + } + + void visit (TyTy::ADTType &type) override + { + rust_assert (type.was_substituted ()); + + TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver); + resolved = to_sub->handle_substitions (type.get_substitution_arguments ()); + } + + void visit (TyTy::InferType &) override { gcc_unreachable (); } + void visit (TyTy::TupleType &) override { gcc_unreachable (); } + void visit (TyTy::FnPtr &) override { gcc_unreachable (); } + void visit (TyTy::ArrayType &) override { gcc_unreachable (); } + void visit (TyTy::BoolType &) override { gcc_unreachable (); } + void visit (TyTy::IntType &) override { gcc_unreachable (); } + void visit (TyTy::UintType &) override { gcc_unreachable (); } + void visit (TyTy::FloatType &) override { gcc_unreachable (); } + void visit (TyTy::USizeType &) override { gcc_unreachable (); } + void visit (TyTy::ISizeType &) override { gcc_unreachable (); } + void visit (TyTy::ErrorType &) override { gcc_unreachable (); } + void visit (TyTy::CharType &) override { gcc_unreachable (); } + void visit (TyTy::ReferenceType &) override { gcc_unreachable (); } + void visit (TyTy::ParamType &) override { gcc_unreachable (); } + void visit (TyTy::StrType &) override { gcc_unreachable (); } + +private: + SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver) + : concrete (concrete), receiver (receiver), resolved (nullptr) + {} + + TyTy::BaseType *concrete; + TyTy::BaseType *receiver; + + TyTy::BaseType *resolved; +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index d53ab11..4171da5 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -76,6 +76,7 @@ private: class TypeCheckMethodCallExpr : private TyVisitor { public: + // Resolve the Method parameters and return back the return type static BaseType *go (BaseType *ref, HIR::MethodCallExpr &call, Resolver::TypeCheckContext *context) { diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 729a6d5..58baee9 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -354,7 +354,8 @@ ADTType::clone () cloned_fields.push_back ((StructFieldType *) f->clone ()); return new ADTType (get_ref (), get_ty_ref (), identifier, get_is_tuple (), - cloned_fields, clone_substs (), get_combined_refs ()); + cloned_fields, clone_substs (), used_arguments, + get_combined_refs ()); } ADTType * @@ -368,6 +369,8 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings) return nullptr; } + used_arguments = subst_mappings; + ADTType *adt = static_cast<ADTType *> (clone ()); adt->set_ty_ref (mappings->get_next_hir_id ()); @@ -568,6 +571,8 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings) return nullptr; } + used_arguments = subst_mappings; + FnType *fn = static_cast<FnType *> (clone ()); fn->set_ty_ref (mappings->get_next_hir_id ()); diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 2e861fb..ac5a766 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -423,6 +423,18 @@ public: : mappings (mappings), locus (locus) {} + SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other) + : mappings (other.mappings), locus (other.locus) + {} + + SubstitutionArgumentMappings & + operator= (const SubstitutionArgumentMappings &other) + { + mappings = other.mappings; + locus = other.locus; + return *this; + } + static SubstitutionArgumentMappings error () { return SubstitutionArgumentMappings ({}, Location ()); @@ -471,8 +483,9 @@ private: class SubstitutionRef { public: - SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions) - : substitutions (substitutions) + SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions, + SubstitutionArgumentMappings arguments) + : substitutions (substitutions), used_arguments (arguments) {} bool has_substitutions () const { return substitutions.size () > 0; } @@ -514,6 +527,13 @@ public: } } + bool was_substituted () const { return !used_arguments.is_error (); } + + SubstitutionArgumentMappings get_substitution_arguments () + { + return used_arguments; + } + // We are trying to subst <i32, f32> into Struct Foo<X,Y> {} // in the case of Foo<i32,f32>{...} // @@ -548,28 +568,32 @@ public: protected: std::vector<SubstitutionParamMapping> substitutions; + SubstitutionArgumentMappings used_arguments; }; class ADTType : public BaseType, public SubstitutionRef - { public: ADTType (HirId ref, std::string identifier, bool is_tuple, std::vector<StructFieldType *> fields, std::vector<SubstitutionParamMapping> subst_refs, + SubstitutionArgumentMappings generic_arguments + = SubstitutionArgumentMappings::error (), std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ref, TypeKind::ADT, refs), - SubstitutionRef (std::move (subst_refs)), identifier (identifier), - fields (fields), is_tuple (is_tuple) + SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)), + identifier (identifier), fields (fields), is_tuple (is_tuple) {} ADTType (HirId ref, HirId ty_ref, std::string identifier, bool is_tuple, std::vector<StructFieldType *> fields, std::vector<SubstitutionParamMapping> subst_refs, + SubstitutionArgumentMappings generic_arguments + = SubstitutionArgumentMappings::error (), std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ty_ref, TypeKind::ADT, refs), - SubstitutionRef (std::move (subst_refs)), identifier (identifier), - fields (fields), is_tuple (is_tuple) + SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)), + identifier (identifier), fields (fields), is_tuple (is_tuple) {} bool get_is_tuple () { return is_tuple; } @@ -651,8 +675,9 @@ public: BaseType *type, std::vector<SubstitutionParamMapping> subst_refs, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ref, TypeKind::FNDEF, refs), - SubstitutionRef (std::move (subst_refs)), params (std::move (params)), - type (type) + SubstitutionRef (std::move (subst_refs), + SubstitutionArgumentMappings::error ()), + params (std::move (params)), type (type) {} FnType (HirId ref, HirId ty_ref, @@ -660,7 +685,9 @@ public: BaseType *type, std::vector<SubstitutionParamMapping> subst_refs, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ty_ref, TypeKind::FNDEF, refs), - SubstitutionRef (std::move (subst_refs)), params (params), type (type) + SubstitutionRef (std::move (subst_refs), + SubstitutionArgumentMappings::error ()), + params (params), type (type) {} void accept_vis (TyVisitor &vis) override; diff --git a/gcc/testsuite/rust.test/compile/generics9.rs b/gcc/testsuite/rust.test/compile/generics9.rs new file mode 100644 index 0000000..0399a62 --- /dev/null +++ b/gcc/testsuite/rust.test/compile/generics9.rs @@ -0,0 +1,22 @@ +struct GenericStruct<T>(T, usize); + +impl<T> GenericStruct<T> { + fn new(a: T, b: usize) -> Self { + GenericStruct(a, b) + } + + fn get(self) -> T { + self.0 + } +} + +fn main() { + let a: GenericStruct<i32> = GenericStruct::<i32>::new(123, 456); + let aa: i32 = a.get(); + + let b: GenericStruct<u32> = GenericStruct::<_>::new(123, 456); + let bb: u32 = b.get(); + + let c: GenericStruct<f32> = GenericStruct::new(123f32, 456); + let cc: f32 = c.get(); +} |