aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-04-30 16:16:38 +0000
committerGitHub <noreply@github.com>2021-04-30 16:16:38 +0000
commitb1dcbc3d8e2fedd7b0c2f42554f4c2297469dabe (patch)
tree6ac4d268325bf75dfc747c12ff18122826a5c151
parent0276ec39a9c3b839c47ce28838a8d5af25fbf598 (diff)
parent2216cab0c9f694016d6cc220cfa8f5c23ba5f465 (diff)
downloadgcc-b1dcbc3d8e2fedd7b0c2f42554f4c2297469dabe.zip
gcc-b1dcbc3d8e2fedd7b0c2f42554f4c2297469dabe.tar.gz
gcc-b1dcbc3d8e2fedd7b0c2f42554f4c2297469dabe.tar.bz2
Merge #401
401: Add defaults support for generics r=philberty a=philberty This adds in the basic support for default arguments for generics such as: ```rust struct Foo<A,B=f32>(A,B); ``` or recursive type params such as: ```rust struct Foo<A, B = (A, A)>(A, B); ``` Fixes #307 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h23
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h12
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc14
-rw-r--r--gcc/testsuite/rust.test/compile/generics25.rs9
-rw-r--r--gcc/testsuite/rust.test/xfail_compile/generics10.rs12
-rw-r--r--gcc/testsuite/rust.test/xfail_compile/generics9.rs11
6 files changed, 75 insertions, 6 deletions
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index 18ead3c..fe0b791 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -349,6 +349,29 @@ public:
{
generic_params
= lower_generic_params (impl_block.get_generic_params ());
+
+ for (auto &generic_param : generic_params)
+ {
+ switch (generic_param->get_kind ())
+ {
+ case HIR::GenericParam::GenericKind::TYPE: {
+ const HIR::TypeParam &t
+ = static_cast<const HIR::TypeParam &> (*generic_param);
+
+ if (t.has_type ())
+ {
+ // see https://github.com/rust-lang/rust/issues/36887
+ rust_error_at (
+ t.get_locus (),
+ "defaults for type parameters are not allowed here");
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
}
HIR::Type *trait_type
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
index d249c43..a1dcb4c 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -262,6 +262,12 @@ public:
{
ok = true;
+ // if it has a type lets resolve it
+ if (param.has_type ())
+ {
+ ResolveType::go (param.get_type ().get (), param.get_node_id ());
+ }
+
// for now lets focus on handling the basics: like struct<T> { a:T, ....}
resolver->get_type_scope ().insert (
CanonicalPath (param.get_type_representation ()), param.get_node_id (),
@@ -271,12 +277,6 @@ public:
"generic param redefined multiple times");
rust_error_at (locus, "was defined here");
});
-
- // if it has a type lets resolve it
- if (param.has_type ())
- {
- ResolveType::go (param.get_type ().get (), param.get_node_id ());
- }
}
private:
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 3e9098d..f5daf3a 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -271,6 +271,20 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
rust_assert (param.param_has_default_ty ());
BaseType *resolved = param.get_default_ty ();
+ if (resolved->get_kind () == TypeKind::ERROR)
+ return SubstitutionArgumentMappings::error ();
+
+ // this resolved default might already contain default parameters
+ if (resolved->contains_type_parameters ())
+ {
+ SubstitutionArgumentMappings intermediate (mappings,
+ args.get_locus ());
+ resolved = Resolver::SubstMapperInternal::Resolve (resolved,
+ intermediate);
+ if (resolved->get_kind () == TypeKind::ERROR)
+ return SubstitutionArgumentMappings::error ();
+ }
+
SubstitutionArg subst_arg (&param, resolved);
mappings.push_back (std::move (subst_arg));
}
diff --git a/gcc/testsuite/rust.test/compile/generics25.rs b/gcc/testsuite/rust.test/compile/generics25.rs
new file mode 100644
index 0000000..e7792e3
--- /dev/null
+++ b/gcc/testsuite/rust.test/compile/generics25.rs
@@ -0,0 +1,9 @@
+struct Foo<A, B = (A, A)>(A, B);
+
+fn main() {
+ let a: Foo<bool>;
+ a = Foo::<bool>(true, (false, true));
+
+ let b: (bool, bool);
+ b = a.1;
+}
diff --git a/gcc/testsuite/rust.test/xfail_compile/generics10.rs b/gcc/testsuite/rust.test/xfail_compile/generics10.rs
new file mode 100644
index 0000000..a734fa8
--- /dev/null
+++ b/gcc/testsuite/rust.test/xfail_compile/generics10.rs
@@ -0,0 +1,12 @@
+struct Foo<A, B>(A, B);
+
+impl<X = i32> Foo<X, f32> { // { dg-error "defaults for type parameters are not allowed here" }
+ fn new(a: X, b: f32) -> Self {
+ Self(a, b)
+ }
+}
+
+fn main() {
+ let a;
+ a = Foo::new(123, 456f32);
+}
diff --git a/gcc/testsuite/rust.test/xfail_compile/generics9.rs b/gcc/testsuite/rust.test/xfail_compile/generics9.rs
new file mode 100644
index 0000000..c1ff89b
--- /dev/null
+++ b/gcc/testsuite/rust.test/xfail_compile/generics9.rs
@@ -0,0 +1,11 @@
+// { dg-excess-errors "Noisy error and debug" }
+struct Foo<A, B = (A, B)>(A, B);
+// { dg-error "failed to resolve TypePath: B" "" { target { *-*-* } } .-1 }
+
+fn main() {
+ let a: Foo<bool>;
+ a = Foo::<bool>(true, (false, true));
+
+ let b: (bool, bool);
+ b = a.1;
+}