aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-04-30 12:07:52 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-04-30 15:50:16 +0100
commitfeaafdfecf4aa0575768deaa837323c3d86f678f (patch)
tree17a411358cdcfc8d6a0ff62655a76b82c0764ce5 /gcc
parent0276ec39a9c3b839c47ce28838a8d5af25fbf598 (diff)
downloadgcc-feaafdfecf4aa0575768deaa837323c3d86f678f.zip
gcc-feaafdfecf4aa0575768deaa837323c3d86f678f.tar.gz
gcc-feaafdfecf4aa0575768deaa837323c3d86f678f.tar.bz2
Apply defaults if available to type substitutions
When we get defaults specified to Type parameters we must resolve the type before insert the name into the name scope otherwise we can end up with forward declared type parameters being resolved. When we need to apply defaults during substitution we must check if they themseleves need substitutions also with the mappings we have generated so far. Fixes #307
Diffstat (limited to 'gcc')
-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/generics9.rs11
4 files changed, 40 insertions, 6 deletions
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/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;
+}