diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-04-30 11:48:20 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-04-30 11:57:48 +0100 |
commit | b7d95ea80be40c5ee468a5549d84e058a21fc62c (patch) | |
tree | 92dfd62b9f3ebf2d73a0bfcaf2b59c513191aead | |
parent | 91ca22c7b9141364aa4bebc61e46ae1518b793f3 (diff) | |
download | gcc-b7d95ea80be40c5ee468a5549d84e058a21fc62c.zip gcc-b7d95ea80be40c5ee468a5549d84e058a21fc62c.tar.gz gcc-b7d95ea80be40c5ee468a5549d84e058a21fc62c.tar.bz2 |
Add initial support for defaults on generic parameters
In the case that the GenericArgs to a type/fn are less than the expected
number of required substitutions we need to look for what is the min
number of required substitutions which might be zero if each TypeParam
has a default.
In the event we have less than expected arguments we can substitute the
defaults if available as the GenericArgumentMappings.
Addresses: #307
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 6 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 18 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 20 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/generics23.rs | 6 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/generics24.rs | 34 |
5 files changed, 83 insertions, 1 deletions
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index dbbc743..648999b 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -117,6 +117,12 @@ public: return type; } + Analysis::NodeMapping get_type_mappings () const + { + rust_assert (type != nullptr); + return type->get_mappings (); + } + protected: // Clone function implementation as (not pure) virtual method TypeParam *clone_generic_param_impl () const override diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index be56dc7..3e9098d 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -233,7 +233,7 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args) return SubstitutionArgumentMappings::error (); } - if (args.get_type_args ().size () < substitutions.size ()) + if (args.get_type_args ().size () < min_required_substitutions ()) { RichLocation r (args.get_locus ()); r.add_range (substitutions.front ().get_param_locus ()); @@ -260,6 +260,22 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args) mappings.push_back (std::move (subst_arg)); } + // we must need to fill out defaults + size_t left_over + = num_required_substitutions () - min_required_substitutions (); + if (left_over > 0) + { + for (size_t offs = mappings.size (); offs < substitutions.size (); offs++) + { + SubstitutionParamMapping ¶m = substitutions.at (offs); + rust_assert (param.param_has_default_ty ()); + + BaseType *resolved = param.get_default_ty (); + SubstitutionArg subst_arg (¶m, resolved); + mappings.push_back (std::move (subst_arg)); + } + } + return SubstitutionArgumentMappings (mappings, args.get_locus ()); } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 5beedda..d6a3aef 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -449,6 +449,12 @@ public: bool param_has_default_ty () const { return generic.has_type (); } + BaseType *get_default_ty () const + { + TyVar var (generic.get_type_mappings ().get_hirid ()); + return var.get_tyty (); + } + private: const HIR::TypeParam &generic; ParamType *param; @@ -643,6 +649,7 @@ public: return used_arguments; } + // this is the count of type params that are not substituted fuly size_t num_required_substitutions () const { size_t n = 0; @@ -654,6 +661,19 @@ public: return n; } + // this is the count of type params that need substituted taking into account + // possible defaults + size_t min_required_substitutions () const + { + size_t n = 0; + for (auto &p : substitutions) + { + if (p.needs_substitution () && !p.param_has_default_ty ()) + 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/generics23.rs b/gcc/testsuite/rust.test/compile/generics23.rs new file mode 100644 index 0000000..2169e36 --- /dev/null +++ b/gcc/testsuite/rust.test/compile/generics23.rs @@ -0,0 +1,6 @@ +struct Foo<A = f32>(A); + +fn main() { + let a: Foo; + a = Foo(123f32); +} diff --git a/gcc/testsuite/rust.test/compile/generics24.rs b/gcc/testsuite/rust.test/compile/generics24.rs new file mode 100644 index 0000000..9d24bce --- /dev/null +++ b/gcc/testsuite/rust.test/compile/generics24.rs @@ -0,0 +1,34 @@ +struct Foo<A = (isize, char)> { + a: A, +} + +impl Foo<isize> { + fn bar(self) -> isize { + self.a + } +} + +impl Foo<char> { + fn bar(self) -> char { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + self.a + } +} + +impl Foo { + fn bar(self) { + let a: (isize, char) = self.a; + let b = a.0; + let c = a.1; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + let aa: Foo<isize> = Foo { a: b }; + let bb: isize = aa.bar(); + // { dg-warning "unused name" "" { target *-*-* } .-1 } + } +} + +fn main() { + let a = Foo { a: (123, 'a') }; + a.bar(); +} |