Skip to content

Commit

Permalink
Merge #401
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bors[bot] and philberty committed Apr 30, 2021
2 parents 0276ec3 + 2216cab commit b1dcbc3
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 6 deletions.
23 changes: 23 additions & 0 deletions gcc/rust/hir/rust-ast-lower-item.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,29 @@ class ASTLoweringItem : public ASTLoweringBase
{
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
Expand Down
12 changes: 6 additions & 6 deletions gcc/rust/resolve/rust-ast-resolve-type.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ class ResolveGenericParam : public ResolverBase
{
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 (),
Expand All @@ -271,12 +277,6 @@ class ResolveGenericParam : public ResolverBase
"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:
Expand Down
14 changes: 14 additions & 0 deletions gcc/rust/typecheck/rust-tyty.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
9 changes: 9 additions & 0 deletions gcc/testsuite/rust.test/compile/generics25.rs
Original file line number Diff line number Diff line change
@@ -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;
}
12 changes: 12 additions & 0 deletions gcc/testsuite/rust.test/xfail_compile/generics10.rs
Original file line number Diff line number Diff line change
@@ -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);
}
11 changes: 11 additions & 0 deletions gcc/testsuite/rust.test/xfail_compile/generics9.rs
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit b1dcbc3

Please sign in to comment.