diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-04-30 12:07:52 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-04-30 15:50:16 +0100 |
commit | feaafdfecf4aa0575768deaa837323c3d86f678f (patch) | |
tree | 17a411358cdcfc8d6a0ff62655a76b82c0764ce5 /gcc | |
parent | 0276ec39a9c3b839c47ce28838a8d5af25fbf598 (diff) | |
download | gcc-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.h | 12 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 14 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/generics25.rs | 9 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/generics9.rs | 11 |
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 (¶m, 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; +} |