aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-11 09:40:31 +0000
committerGitHub <noreply@github.com>2021-05-11 09:40:31 +0000
commit7c45fcb6e23f86a7f69ef4136099d5a8541afde6 (patch)
tree43459717de6d35d858dce11932a29700444967d6 /gcc/rust
parent7e66d683186ffdcca835bad1a90081fe56be8822 (diff)
parent99d1330b79a6b8457b45bba2a7b9940b1f2e9acd (diff)
downloadgcc-7c45fcb6e23f86a7f69ef4136099d5a8541afde6.zip
gcc-7c45fcb6e23f86a7f69ef4136099d5a8541afde6.tar.gz
gcc-7c45fcb6e23f86a7f69ef4136099d5a8541afde6.tar.bz2
Merge #424
424: Support Impl items to also be generic r=philberty a=philberty Handle inherited type arguments for methods MethodCallExpr's support generic arguments so we need to handle adjusting any inherited type arguments from the receiver and apply them to the func. This changes the handle_substitutions function for ADT, FnType and Params to be permissive that we can send single arguments to partially substitute the type such as the case when we inherit arguments in methods calls. This is safe because the other interfaces enforce the type checking and number of arguments etc. Fixes #423 #417 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/hir/rust-ast-lower-implitem.h12
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h6
-rw-r--r--gcc/rust/hir/tree/rust-hir.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h8
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h15
-rw-r--r--gcc/rust/typecheck/rust-hir-method-resolve.h67
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h104
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h4
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc169
-rw-r--r--gcc/rust/typecheck/rust-tyty.h67
11 files changed, 263 insertions, 193 deletions
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h
index 3ddc62c..2581d68e 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.h
+++ b/gcc/rust/hir/rust-ast-lower-implitem.h
@@ -86,7 +86,6 @@ public:
void visit (AST::Function &function) override
{
// ignore for now and leave empty
- std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
std::vector<HIR::Attribute> outer_attrs;
std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
@@ -95,6 +94,11 @@ public:
HIR::Visibility vis = HIR::Visibility::create_public ();
// need
+ std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ if (function.has_generics ())
+ {
+ generic_params = lower_generic_params (function.get_generic_params ());
+ }
Identifier function_name = function.get_function_name ();
Location locus = function.get_locus ();
@@ -165,7 +169,6 @@ public:
void visit (AST::Method &method) override
{
// ignore for now and leave empty
- std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
std::vector<HIR::Attribute> outer_attrs;
std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
@@ -174,6 +177,11 @@ public:
HIR::Visibility vis = HIR::Visibility::create_public ();
// need
+ std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ if (method.has_generics ())
+ {
+ generic_params = lower_generic_params (method.get_generic_params ());
+ }
Identifier method_name = method.get_method_name ();
Location locus = method.get_locus ();
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 648999b..fc67d60 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -745,6 +745,8 @@ public:
Location get_locus () const { return locus; }
+ Location get_impl_locus () const final { return get_locus (); }
+
std::unique_ptr<BlockExpr> &get_function_body () { return function_body; }
const std::unique_ptr<BlockExpr> &get_function_body () const
{
@@ -1366,6 +1368,8 @@ public:
Location get_locus () const { return locus; }
+ Location get_impl_locus () const final { return get_locus (); }
+
void accept_vis (HIRVisitor &vis) override;
Analysis::NodeMapping get_impl_mappings () const override
@@ -2266,6 +2270,8 @@ public:
Location get_locus () const { return locus; }
+ Location get_impl_locus () const final { return get_locus (); }
+
void accept_vis (HIRVisitor &vis) override;
Type *get_type () { return type.get (); }
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 244ff3d..f6fa62d 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -1295,6 +1295,8 @@ public:
virtual void accept_vis (HIRVisitor &vis) = 0;
virtual Analysis::NodeMapping get_impl_mappings () const = 0;
+
+ virtual Location get_impl_locus () const = 0;
};
// Abstract base class for items used in a trait impl
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index fbf05f2..f163ef5b 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -23,6 +23,7 @@
#include "rust-ast-full.h"
#include "rust-ast-resolve-struct-expr-field.h"
#include "rust-ast-verify-assignee.h"
+#include "rust-ast-resolve-type.h"
namespace Rust {
namespace Resolver {
@@ -92,6 +93,13 @@ public:
void visit (AST::MethodCallExpr &expr) override
{
ResolveExpr::go (expr.get_receiver_expr ().get (), expr.get_node_id ());
+
+ if (expr.get_method_name ().has_generic_args ())
+ {
+ AST::GenericArgs &args = expr.get_method_name ().get_generic_args ();
+ ResolveTypeToCanonicalPath::type_resolve_generic_args (args);
+ }
+
expr.iterate_params ([&] (AST::Expr *p) mutable -> bool {
ResolveExpr::go (p, expr.get_node_id ());
return true;
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index 27f5305..dc16573 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -200,14 +200,22 @@ public:
void visit (AST::Method &method) override
{
- if (method.has_return_type ())
- ResolveType::go (method.get_return_type ().get (), method.get_node_id ());
-
NodeId scope_node_id = method.get_node_id ();
resolver->get_name_scope ().push (scope_node_id);
resolver->get_type_scope ().push (scope_node_id);
+ resolver->get_label_scope ().push (scope_node_id);
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
+ resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
+
+ if (method.has_generics ())
+ {
+ for (auto &generic : method.get_generic_params ())
+ ResolveGenericParam::go (generic.get (), method.get_node_id ());
+ }
+
+ if (method.has_return_type ())
+ ResolveType::go (method.get_return_type ().get (), method.get_node_id ());
// self turns into (self: Self) as a function param
AST::SelfParam &self_param = method.get_self_param ();
@@ -248,6 +256,7 @@ public:
resolver->get_name_scope ().pop ();
resolver->get_type_scope ().pop ();
+ resolver->get_label_scope ().pop ();
}
private:
diff --git a/gcc/rust/typecheck/rust-hir-method-resolve.h b/gcc/rust/typecheck/rust-hir-method-resolve.h
deleted file mode 100644
index b2391e3..0000000
--- a/gcc/rust/typecheck/rust-hir-method-resolve.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2020 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_HIR_METHOD_RESOLVE_H
-#define RUST_HIR_METHOD_RESOLVE_H
-
-#include "rust-hir-type-check-base.h"
-#include "rust-hir-full.h"
-#include "rust-tyty.h"
-#include "rust-hir-path-probe.h"
-#include "rust-substitution-mapper.h"
-
-namespace Rust {
-namespace Resolver {
-
-class MethodResolution : public TypeCheckBase
-{
- using Rust::Resolver::TypeCheckBase::visit;
-
-public:
- static std::vector<PathProbeCandidate>
- Probe (std::vector<PathProbeCandidate> &path_candidates)
- {
- MethodResolution probe;
- for (auto &c : path_candidates)
- probe.process_candidate (c);
-
- return probe.candidates;
- }
-
- void process_candidate (PathProbeCandidate &candidate)
- {
- is_method_flag = false;
- candidate.impl_item->accept_vis (*this);
-
- if (is_method_flag)
- candidates.push_back (candidate);
- }
-
- void visit (HIR::Method &method) override { is_method_flag = true; }
-
-private:
- MethodResolution () : TypeCheckBase () {}
-
- bool is_method_flag;
- std::vector<PathProbeCandidate> candidates;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_HIR_METHOD_RESOLVE_H
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index d82e82b..3e081ec 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -24,7 +24,6 @@
#include "rust-tyty.h"
#include "rust-tyty-call.h"
#include "rust-hir-type-check-struct-field.h"
-#include "rust-hir-method-resolve.h"
#include "rust-hir-path-probe.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-const-fold.h"
@@ -221,46 +220,105 @@ public:
"failed to resolve the PathExprSegment to any Method");
return;
}
-
- // filter all methods
- auto possible_methods = MethodResolution::Probe (candidates);
- if (possible_methods.size () == 0)
- {
- rust_error_at (expr.get_method_name ().get_locus (),
- "no method named %s found in scope",
- expr.get_method_name ().as_string ().c_str ());
- return;
- }
- else if (possible_methods.size () > 1)
+ else if (candidates.size () > 1)
{
ReportMultipleCandidateError::Report (
- possible_methods, expr.get_method_name ().get_segment (),
+ candidates, expr.get_method_name ().get_segment (),
expr.get_method_name ().get_locus ());
return;
}
- auto resolved_candidate = possible_methods.at (0);
+ auto resolved_candidate = candidates.at (0);
HIR::InherentImplItem *resolved_method = resolved_candidate.impl_item;
TyTy::BaseType *lookup_tyty = resolved_candidate.ty;
+ if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
+ {
+ RichLocation r (expr.get_method_name ().get_locus ());
+ r.add_range (resolved_method->get_impl_locus ());
+ rust_error_at (r, "associated impl item is not a method");
+ return;
+ }
+
TyTy::BaseType *lookup = lookup_tyty;
- if (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF)
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
+ if (!fn->is_method ())
{
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
- if (receiver_tyty->get_kind () == TyTy::TypeKind::ADT)
+ RichLocation r (expr.get_method_name ().get_locus ());
+ r.add_range (resolved_method->get_impl_locus ());
+ rust_error_at (r, "associated function is not a method");
+ return;
+ }
+
+ if (receiver_tyty->get_kind () == TyTy::TypeKind::ADT)
+ {
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver_tyty);
+ if (adt->has_substitutions () && fn->needs_substitution ())
{
- TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver_tyty);
- if (adt->has_substitutions () && fn->needs_substitution ())
+ // consider the case where we have:
+ //
+ // struct Foo<X,Y>(X,Y);
+ //
+ // impl<T> Foo<T, i32> {
+ // fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
+ // }
+ //
+ // In this case we end up with an fn type of:
+ //
+ // fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
+ //
+ // This means the instance or self we are calling this method for
+ // will be substituted such that we can get the inherited type
+ // arguments but then need to use the turbo fish if available or
+ // infer the remaining arguments. Luckily rust does not allow for
+ // default types GenericParams on impl blocks since these must
+ // always be at the end of the list
+
+ auto s = fn->get_self_type ();
+ rust_assert (s->can_eq (adt));
+ rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *self_adt = static_cast<TyTy::ADTType *> (s);
+
+ // we need to grab the Self substitutions as the inherit type
+ // parameters for this
+ if (self_adt->needs_substitution ())
{
rust_assert (adt->was_substituted ());
- auto used_args_in_prev_segment = GetUsedSubstArgs::From (adt);
- lookup
- = SubstMapperInternal::Resolve (fn,
- used_args_in_prev_segment);
+
+ TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
+ = GetUsedSubstArgs::From (adt);
+
+ TyTy::SubstitutionArgumentMappings inherit_type_args
+ = self_adt->solve_mappings_from_receiver_for_self (
+ used_args_in_prev_segment);
+
+ // there may or may not be inherited type arguments
+ if (!inherit_type_args.is_error ())
+ {
+ // need to apply the inherited type arguments to the
+ // function
+ lookup = fn->handle_substitions (inherit_type_args);
+ }
}
}
}
+ // apply any remaining generic arguments
+ if (expr.get_method_name ().has_generic_args ())
+ {
+ HIR::GenericArgs &args = expr.get_method_name ().get_generic_args ();
+ lookup
+ = SubstMapper::Resolve (lookup, expr.get_method_name ().get_locus (),
+ &args);
+ if (lookup->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+ else if (lookup->needs_generic_substitutions ())
+ {
+ lookup = SubstMapper::InferSubst (lookup,
+ expr.get_method_name ().get_locus ());
+ }
+
TyTy::BaseType *function_ret_tyty
= TyTy::TypeCheckMethodCallExpr::go (lookup, expr, context);
if (function_ret_tyty == nullptr
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index 2a3e9f9..f961bba 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -112,7 +112,7 @@ public:
}
auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
- std::move (params), ret_type,
+ false, std::move (params), ret_type,
std::move (substitutions));
context->insert_type (function.get_mappings (), fnType);
}
@@ -189,7 +189,7 @@ public:
context->insert_type (param.get_mappings (), param_tyty);
}
- auto fnType = new TyTy::FnType (method.get_mappings ().get_hirid (),
+ auto fnType = new TyTy::FnType (method.get_mappings ().get_hirid (), true,
std::move (params), ret_type,
std::move (substitutions));
context->insert_type (method.get_mappings (), fnType);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
index 6be1552..ef940c1 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -229,7 +229,7 @@ public:
}
auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
- std::move (params), ret_type,
+ false, std::move (params), ret_type,
std::move (substitutions));
context->insert_type (function.get_mappings (), fnType);
}
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index dcf9203..e74ab93 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -247,6 +247,9 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
return SubstitutionArgumentMappings::error ();
}
+ // for inherited arguments
+ size_t offs = used_arguments.size ();
+
std::vector<SubstitutionArg> mappings;
for (auto &arg : args.get_type_args ())
{
@@ -257,8 +260,8 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
return SubstitutionArgumentMappings::error ();
}
- SubstitutionArg subst_arg (&substitutions.at (mappings.size ()),
- resolved);
+ SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
+ offs++;
mappings.push_back (std::move (subst_arg));
}
@@ -345,6 +348,31 @@ SubstitutionRef::adjust_mappings_for_this (
mappings.get_locus ());
}
+// this function assumes that the mappings being passed are for the same type as
+// this new substitution reference so ordering matters here
+SubstitutionArgumentMappings
+SubstitutionRef::solve_mappings_from_receiver_for_self (
+ SubstitutionArgumentMappings &mappings)
+{
+ std::vector<SubstitutionArg> resolved_mappings;
+
+ rust_assert (mappings.size () == get_num_substitutions ());
+ for (size_t i = 0; i < get_num_substitutions (); i++)
+ {
+ SubstitutionParamMapping &param_mapping = substitutions.at (i);
+ SubstitutionArg &arg = mappings.get_mappings ().at (i);
+
+ if (param_mapping.needs_substitution ())
+ {
+ SubstitutionArg adjusted (&param_mapping, arg.get_tyty ());
+ resolved_mappings.push_back (std::move (adjusted));
+ }
+ }
+
+ return SubstitutionArgumentMappings (resolved_mappings,
+ mappings.get_locus ());
+}
+
void
ADTType::accept_vis (TyVisitor &vis)
{
@@ -457,13 +485,6 @@ ADTType::clone ()
ADTType *
ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
{
- if (subst_mappings.size () != get_num_substitutions ())
- {
- rust_error_at (subst_mappings.get_locus (),
- "invalid number of generic arguments to generic ADT type");
- return nullptr;
- }
-
ADTType *adt = static_cast<ADTType *> (clone ());
adt->set_ty_ref (mappings->get_next_hir_id ());
adt->used_arguments = subst_mappings;
@@ -473,8 +494,8 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
SubstitutionArg arg = SubstitutionArg::error ();
bool ok
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
- rust_assert (ok);
- sub.fill_param_ty (arg.get_tyty ());
+ if (ok)
+ sub.fill_param_ty (arg.get_tyty ());
}
adt->iterate_fields ([&] (StructFieldType *field) mutable -> bool {
@@ -486,27 +507,22 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
SubstitutionArg arg = SubstitutionArg::error ();
bool ok = subst_mappings.get_argument_for_symbol (p, &arg);
- if (!ok)
- {
- rust_error_at (subst_mappings.get_locus (),
- "Failed to resolve parameter type: %s",
- p->as_string ().c_str ());
- return false;
- }
-
- auto argt = arg.get_tyty ();
- bool arg_is_param = argt->get_kind () == TyTy::TypeKind::PARAM;
- bool arg_is_concrete = argt->get_kind () != TyTy::TypeKind::INFER;
-
- if (arg_is_param || arg_is_concrete)
- {
- auto new_field = argt->clone ();
- new_field->set_ref (fty->get_ref ());
- field->set_field_type (new_field);
- }
- else
+ if (ok)
{
- field->get_field_type ()->set_ty_ref (argt->get_ref ());
+ auto argt = arg.get_tyty ();
+ bool arg_is_param = argt->get_kind () == TyTy::TypeKind::PARAM;
+ bool arg_is_concrete = argt->get_kind () != TyTy::TypeKind::INFER;
+
+ if (arg_is_param || arg_is_concrete)
+ {
+ auto new_field = argt->clone ();
+ new_field->set_ref (fty->get_ref ());
+ field->set_field_type (new_field);
+ }
+ else
+ {
+ field->get_field_type ()->set_ty_ref (argt->get_ref ());
+ }
}
}
else if (fty->has_subsititions_defined ()
@@ -687,22 +703,14 @@ FnType::clone ()
cloned_params.push_back (
std::pair<HIR::Pattern *, BaseType *> (p.first, p.second->clone ()));
- return new FnType (get_ref (), get_ty_ref (), std::move (cloned_params),
- get_return_type ()->clone (), clone_substs (),
- get_combined_refs ());
+ return new FnType (get_ref (), get_ty_ref (), is_method_flag,
+ std::move (cloned_params), get_return_type ()->clone (),
+ clone_substs (), get_combined_refs ());
}
FnType *
FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
{
- if (subst_mappings.size () != get_num_substitutions ())
- {
- rust_error_at (
- subst_mappings.get_locus (),
- "invalid number of generic arguments to generic Function type");
- return nullptr;
- }
-
FnType *fn = static_cast<FnType *> (clone ());
fn->set_ty_ref (mappings->get_next_hir_id ());
fn->used_arguments = subst_mappings;
@@ -713,8 +721,8 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
bool ok
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
- rust_assert (ok);
- sub.fill_param_ty (arg.get_tyty ());
+ if (ok)
+ sub.fill_param_ty (arg.get_tyty ());
}
auto fty = fn->get_return_type ();
@@ -725,27 +733,22 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
SubstitutionArg arg = SubstitutionArg::error ();
bool ok = subst_mappings.get_argument_for_symbol (p, &arg);
- if (!ok)
+ if (ok)
{
- rust_error_at (subst_mappings.get_locus (),
- "Failed to resolve parameter type: %s",
- p->as_string ().c_str ());
- return nullptr;
- }
-
- auto argt = arg.get_tyty ();
- bool arg_is_param = argt->get_kind () == TyTy::TypeKind::PARAM;
- bool arg_is_concrete = argt->get_kind () != TyTy::TypeKind::INFER;
+ auto argt = arg.get_tyty ();
+ bool arg_is_param = argt->get_kind () == TyTy::TypeKind::PARAM;
+ bool arg_is_concrete = argt->get_kind () != TyTy::TypeKind::INFER;
- if (arg_is_param || arg_is_concrete)
- {
- auto new_field = argt->clone ();
- new_field->set_ref (fty->get_ref ());
- fn->type = new_field;
- }
- else
- {
- fty->set_ty_ref (argt->get_ref ());
+ if (arg_is_param || arg_is_concrete)
+ {
+ auto new_field = argt->clone ();
+ new_field->set_ref (fty->get_ref ());
+ fn->type = new_field;
+ }
+ else
+ {
+ fty->set_ty_ref (argt->get_ref ());
+ }
}
}
else if (fty->needs_generic_substitutions ()
@@ -778,27 +781,22 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
SubstitutionArg arg = SubstitutionArg::error ();
bool ok = subst_mappings.get_argument_for_symbol (p, &arg);
- if (!ok)
+ if (ok)
{
- rust_error_at (subst_mappings.get_locus (),
- "Failed to resolve parameter type: %s",
- p->as_string ().c_str ());
- return nullptr;
- }
-
- auto argt = arg.get_tyty ();
- bool arg_is_param = argt->get_kind () == TyTy::TypeKind::PARAM;
- bool arg_is_concrete = argt->get_kind () != TyTy::TypeKind::INFER;
-
- if (arg_is_param || arg_is_concrete)
- {
- auto new_field = argt->clone ();
- new_field->set_ref (fty->get_ref ());
- param.second = new_field;
- }
- else
- {
- fty->set_ty_ref (argt->get_ref ());
+ auto argt = arg.get_tyty ();
+ bool arg_is_param = argt->get_kind () == TyTy::TypeKind::PARAM;
+ bool arg_is_concrete = argt->get_kind () != TyTy::TypeKind::INFER;
+
+ if (arg_is_param || arg_is_concrete)
+ {
+ auto new_field = argt->clone ();
+ new_field->set_ref (fty->get_ref ());
+ param.second = new_field;
+ }
+ else
+ {
+ fty->set_ty_ref (argt->get_ref ());
+ }
}
}
else if (fty->has_subsititions_defined ()
@@ -1396,9 +1394,8 @@ ParamType::handle_substitions (SubstitutionArgumentMappings mappings)
SubstitutionArg arg = SubstitutionArg::error ();
bool ok = mappings.get_argument_for_symbol (this, &arg);
- rust_assert (ok);
-
- p->set_ty_ref (arg.get_tyty ()->get_ref ());
+ if (ok)
+ p->set_ty_ref (arg.get_tyty ()->get_ref ());
return p;
}
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 442b23b..7425030 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -638,8 +638,16 @@ public:
bool needs_substitution () const
{
- return has_substitutions ()
- && (used_arguments.is_error () || !used_arguments.is_concrete ());
+ if (!has_substitutions ())
+ return false;
+
+ if (used_arguments.is_error ())
+ return true;
+
+ if (used_arguments.size () != get_num_substitutions ())
+ return true;
+
+ return !used_arguments.is_concrete ();
}
bool was_substituted () const { return !needs_substitution (); }
@@ -690,13 +698,36 @@ public:
SubstitutionArgumentMappings
adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
+ // struct Foo<A, B>(A, B);
+ //
+ // impl<T> Foo<T, f32>;
+ // -> fn test<X>(self, a: X) -> X
+ //
+ // We might invoke this via:
+ //
+ // a = Foo(123, 456f32);
+ // b = a.test::<bool>(false);
+ //
+ // we need to figure out relevant generic arguemts for self to apply to the
+ // fntype
+ SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
+ SubstitutionArgumentMappings &mappings);
+
BaseType *infer_substitions (Location locus)
{
std::vector<SubstitutionArg> args;
- for (auto &sub : get_substs ())
+ for (auto &p : get_substs ())
{
- TyVar infer_var = TyVar::get_implicit_infer_var (locus);
- args.push_back (SubstitutionArg (&sub, infer_var.get_tyty ()));
+ if (p.needs_substitution ())
+ {
+ TyVar infer_var = TyVar::get_implicit_infer_var (locus);
+ args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
+ }
+ else
+ {
+ args.push_back (
+ SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
+ }
}
SubstitutionArgumentMappings infer_arguments (std::move (args), locus);
@@ -819,23 +850,24 @@ private:
class FnType : public BaseType, public SubstitutionRef
{
public:
- FnType (HirId ref, std::vector<std::pair<HIR::Pattern *, BaseType *> > params,
+ FnType (HirId ref, bool is_method,
+ std::vector<std::pair<HIR::Pattern *, BaseType *> > params,
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),
SubstitutionArgumentMappings::error ()),
- params (std::move (params)), type (type)
+ params (std::move (params)), type (type), is_method_flag (is_method)
{}
- FnType (HirId ref, HirId ty_ref,
+ FnType (HirId ref, HirId ty_ref, bool is_method,
std::vector<std::pair<HIR::Pattern *, BaseType *> > params,
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),
SubstitutionArgumentMappings::error ()),
- params (params), type (type)
+ params (params), type (type), is_method_flag (is_method)
{}
void accept_vis (TyVisitor &vis) override;
@@ -851,6 +883,22 @@ public:
size_t num_params () const { return params.size (); }
+ bool is_method () const
+ {
+ if (num_params () == 0)
+ return false;
+
+ return is_method_flag;
+ }
+
+ // get the Self type for the method
+ BaseType *get_self_type () const
+ {
+ rust_assert (is_method ());
+ // FIXME this will need updated when we support coercion for & mut self etc
+ return get_params ().at (0).second;
+ }
+
std::vector<std::pair<HIR::Pattern *, BaseType *> > &get_params ()
{
return params;
@@ -893,6 +941,7 @@ public:
private:
std::vector<std::pair<HIR::Pattern *, BaseType *> > params;
BaseType *type;
+ bool is_method_flag;
};
class FnPtr : public BaseType