From b7d95ea80be40c5ee468a5549d84e058a21fc62c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 30 Apr 2021 11:48:20 +0100 Subject: 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 --- gcc/rust/hir/tree/rust-hir-item.h | 6 +++++ gcc/rust/typecheck/rust-tyty.cc | 18 +++++++++++++- gcc/rust/typecheck/rust-tyty.h | 20 ++++++++++++++++ gcc/testsuite/rust.test/compile/generics23.rs | 6 +++++ gcc/testsuite/rust.test/compile/generics24.rs | 34 +++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust.test/compile/generics23.rs create mode 100644 gcc/testsuite/rust.test/compile/generics24.rs (limited to 'gcc') 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 into Struct Foo {} // in the case of Foo{...} // 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); + +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: A, +} + +impl Foo { + fn bar(self) -> isize { + self.a + } +} + +impl Foo { + 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 = Foo { a: b }; + let bb: isize = aa.bar(); + // { dg-warning "unused name" "" { target *-*-* } .-1 } + } +} + +fn main() { + let a = Foo { a: (123, 'a') }; + a.bar(); +} -- cgit v1.1