diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-27 14:39:54 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-27 14:39:54 +0000 |
commit | 6647bc65b1a2d3ba581674a9ca22d4ef7a959914 (patch) | |
tree | 73d105263d6fbf23eea1ea94a97af950eaf9bb03 /gcc | |
parent | a24a14371b16c316a815a9440b1d960cd3f885dd (diff) | |
parent | 3df65d5b4ec06c7ac1ec39d8d1a1c268b024531c (diff) | |
download | gcc-6647bc65b1a2d3ba581674a9ca22d4ef7a959914.zip gcc-6647bc65b1a2d3ba581674a9ca22d4ef7a959914.tar.gz gcc-6647bc65b1a2d3ba581674a9ca22d4ef7a959914.tar.bz2 |
Merge #394
394: Partial substitions of generic data types r=philberty a=philberty
Handle the case where we have a generic type:
```rust
struct Foo<A,B>(A,B);
impl<T> Foo<i32, T> { ... }
```
In this case the impl block only defines 1 type parameter but the generic datatype has two type parameters.
Fixes #386
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 11 | ||||
-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 |
6 files changed, 82 insertions, 14 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 5643ad6..5dafd64 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -811,8 +811,15 @@ public: else if (expr.get_num_segments () == 1) { Location locus = expr.get_segments ().back ().get_locus (); - if (tyseg->needs_generic_substitutions ()) - tyseg = SubstMapper::InferSubst (tyseg, locus); + + bool is_big_self + = expr.get_segments ().front ().get_segment ().as_string ().compare ( + "Self") + == 0; + if (!is_big_self && tyseg->needs_generic_substitutions ()) + { + tyseg = SubstMapper::InferSubst (tyseg, locus); + } infered = tyseg; return; 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); +} |