aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-03-26 15:23:57 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-03-27 18:55:14 +0000
commite4ea09d6b8e501dc7bd7046da641b70e02814b09 (patch)
treea01041da77d9276a52d0dbcb08d6a5c3913b03fe /gcc
parent380c8295051c6b42adb4f703268c7465aed57c44 (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-path.h15
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h15
-rw-r--r--gcc/rust/backend/rust-compile.cc19
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h7
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h7
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h13
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc81
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-test.cc3
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h49
-rw-r--r--gcc/rust/typecheck/rust-hir-method-resolve.h20
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h48
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h21
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h56
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h1
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc7
-rw-r--r--gcc/rust/typecheck/rust-tyty.h47
-rw-r--r--gcc/testsuite/rust.test/compile/generics9.rs22
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> > &params);
+
+ 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> > &params)
- {
- 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> > &params)
+{
+ 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();
+}