diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-04-25 15:41:56 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-04-27 13:52:34 +0100 |
commit | 3df65d5b4ec06c7ac1ec39d8d1a1c268b024531c (patch) | |
tree | 73d105263d6fbf23eea1ea94a97af950eaf9bb03 | |
parent | f1c6f7da67ff2417e9100e2d43c1571b482c9e82 (diff) | |
download | gcc-3df65d5b4ec06c7ac1ec39d8d1a1c268b024531c.zip gcc-3df65d5b4ec06c7ac1ec39d8d1a1c268b024531c.tar.gz gcc-3df65d5b4ec06c7ac1ec39d8d1a1c268b024531c.tar.bz2 |
Support partial substitution's
When we have a generic data type with 2 type parameters A,B but then
add an impl block for this type and this impl block only defines 1 Type
parameter and substitutes the other type parameter with a concrete type
we need to use the passed in mappings and the existing mappings to figure
out how to adjust the type parameters to complete the substitution.
Fixes: #386
-rw-r--r-- | gcc/rust/typecheck/rust-substitution-mapper.h | 4 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 35 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 22 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/generics19.rs | 12 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/generics20.rs | 12 |
5 files changed, 73 insertions, 12 deletions
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 37a82c4..d022019 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -133,6 +133,8 @@ public: { TyTy::SubstitutionArgumentMappings adjusted = type.adjust_mappings_for_this (mappings); + if (adjusted.is_error ()) + return; TyTy::BaseType *concrete = type.handle_substitions (adjusted); if (concrete != nullptr) @@ -143,6 +145,8 @@ public: { TyTy::SubstitutionArgumentMappings adjusted = type.adjust_mappings_for_this (mappings); + if (adjusted.is_error ()) + return; TyTy::BaseType *concrete = type.handle_substitions (adjusted); if (concrete != nullptr) diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index baa997b..8cc9089 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -242,15 +242,6 @@ SubstitutionArgumentMappings SubstitutionRef::adjust_mappings_for_this ( SubstitutionArgumentMappings &mappings) { - if (substitutions.size () > mappings.size ()) - { - rust_error_at (mappings.get_locus (), - "not enough type arguments: subs %s vs mappings %s", - subst_as_string ().c_str (), - mappings.as_string ().c_str ()); - return SubstitutionArgumentMappings::error (); - } - Analysis::Mappings *mappings_table = Analysis::Mappings::get (); std::vector<SubstitutionArg> resolved_mappings; @@ -259,13 +250,33 @@ SubstitutionRef::adjust_mappings_for_this ( auto &subst = substitutions.at (i); SubstitutionArg arg = SubstitutionArg::error (); - bool ok = mappings.get_argument_at (0, &arg); + if (mappings.size () == substitutions.size ()) + { + mappings.get_argument_at (i, &arg); + } + else + { + if (subst.needs_substitution ()) + { + // get from passed in mappings + mappings.get_argument_for_symbol (subst.get_param_ty (), &arg); + } + else + { + // we should already have this somewhere + used_arguments.get_argument_for_symbol (subst.get_param_ty (), + &arg); + } + } + + bool ok = !arg.is_error (); if (!ok) { rust_error_at (mappings_table->lookup_location ( subst.get_param_ty ()->get_ref ()), - "failed to find parameter type: %s", - subst.get_param_ty ()->as_string ().c_str ()); + "failed to find parameter type: %s vs mappings [%s]", + subst.get_param_ty ()->as_string ().c_str (), + mappings.as_string ().c_str ()); return SubstitutionArgumentMappings::error (); } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index bc4c9c4..f3ff609 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -408,6 +408,15 @@ public: void override_context (); + bool needs_substitution () const + { + auto p = get_param_ty (); + if (!p->can_resolve ()) + return true; + + return p->resolve ()->get_kind () == TypeKind::PARAM; + } + private: std::unique_ptr<HIR::GenericParam> &generic; ParamType *param; @@ -437,6 +446,8 @@ public: static SubstitutionArg error () { return SubstitutionArg (nullptr, nullptr); } + bool is_error () const { return param == nullptr || argument == nullptr; } + bool is_conrete () const { return argument != nullptr && argument->get_kind () != TyTy::TypeKind::ERROR @@ -600,6 +611,17 @@ public: return used_arguments; } + size_t num_required_substitutions () const + { + size_t n = 0; + for (auto &p : substitutions) + { + if (p.needs_substitution ()) + n++; + } + return n; + } + // We are trying to subst <i32, f32> into Struct Foo<X,Y> {} // in the case of Foo<i32,f32>{...} // diff --git a/gcc/testsuite/rust.test/compile/generics19.rs b/gcc/testsuite/rust.test/compile/generics19.rs new file mode 100644 index 0000000..9a5b4cb --- /dev/null +++ b/gcc/testsuite/rust.test/compile/generics19.rs @@ -0,0 +1,12 @@ +struct Foo<X, Y>(X, Y); + +impl<T> Foo<u32, T> { + fn new(a: T) -> Self { + Self(123, a) + } +} + +fn main() { + let a; + a = Foo::new(false); +} diff --git a/gcc/testsuite/rust.test/compile/generics20.rs b/gcc/testsuite/rust.test/compile/generics20.rs new file mode 100644 index 0000000..8fe1cff --- /dev/null +++ b/gcc/testsuite/rust.test/compile/generics20.rs @@ -0,0 +1,12 @@ +struct Foo<A, B>(A, B); + +impl<T> Foo<T, T> { + fn new(a: T, b: T) -> Self { + Self(a, b) + } +} + +fn main() { + let a; + a = Foo::new(123, 456); +} |