Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic GATs reference information #1265

Merged
merged 11 commits into from
Oct 19, 2022
38 changes: 29 additions & 9 deletions src/items/associated-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,26 +205,46 @@ types cannot be defined in [inherent implementations] nor can they be given a
default implementation in traits.

An *associated type declaration* declares a signature for associated type
definitions. It is written as `type`, then an [identifier], and
finally an optional list of trait bounds.
definitions. It is written in one of the following forms, where `Assoc` is the
name of the associated type, `Params` is a comma-separated list of type,
lifetime or const parameters, `Bounds` is a plus-separated list of trait bounds
on the associated type, and `WhereBounds` is a comma-separated list of bounds on
parameters:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lifetime or const parameters, `Bounds` is a plus-separated list of trait bounds
on the associated type, and `WhereBounds` is a comma-separated list of bounds on
parameters:
lifetime or const parameters, `Bounds` is a plus-separated list of trait bounds
that the associated type must meet, and `WhereBounds` is a comma-separated list of bounds that the parameters must meet:


```rust,ignore
jackh726 marked this conversation as resolved.
Show resolved Hide resolved
type Assoc;
type Assoc: Bounds;
type Assoc<Params>;
type Assoc<Params>: Bounds;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It occurs to me that it would be worth clarifying the distinction between Bounds and WhereBounds!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is stated in the paragraph above? Should we be more detailed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could be more explicit. Left some suggestions. WDYT?

type Assoc<Params> where WhereBounds;
type Assoc<Params>: Bounds where WhereBounds;
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something like

Relationship between Bounds and WhereBounds

In this example:

trait Example {
    type Output<T>: Ord where T: Debug
}

Given a reference to the associated type like <X as Example>::Output<Y>, the associated type itself must be Ord, and the type Y must be Debug.


The identifier is the name of the declared type alias. The optional trait bounds
must be fulfilled by the implementations of the type alias.
There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound.

An *associated type definition* defines a type alias on another type. It is
written as `type`, then an [identifier], then an `=`, and finally a [type].
An *associated type definition* defines a type alias on for the implementation
jackh726 marked this conversation as resolved.
Show resolved Hide resolved
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
of a trait on a type. They are written similarly to an *associated type declaration*,
but cannot contain `Bounds`, but instead must contain a `Type`:

```rust,ignore
jackh726 marked this conversation as resolved.
Show resolved Hide resolved
type Assoc = Type;
type Assoc<Params> = Type<Params>;
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
type Assoc<Params> where WhereBounds = Type;
type Assoc<Params> = Type where WhereBounds;
jackh726 marked this conversation as resolved.
Show resolved Hide resolved
```

If a type `Item` has an associated type `Assoc` from a trait `Trait`, then
`<Item as Trait>::Assoc` is a type that is an alias of the type specified in the
associated type definition. Furthermore, if `Item` is a type parameter, then
`Item::Assoc` can be used in type parameters.

Associated types may include [generic parameters] or [where clauses]; these may
be referred to as generic associated types, or GATs. If the type `Thing` has an
associated type `Item` from a trait `Trait` with the generics `<'a>` , the type
can be named like `<Thing as Trait>::Item<'x>`, where `'x` is some lifetime in
scope. In this case, `'x` will be used wherever `'a` appears in the associated
Associated types may include [generic parameters] and [where clauses]; these are
often referred to as *generic associated types*, or *GATs*. If the type `Thing`
has an associated type `Item` from a trait `Trait` with the generics `<'a>` , the
type can be named like `<Thing as Trait>::Item<'x>`, where `'x` is some lifetime
in scope. In this case, `'x` will be used wherever `'a` appears in the associated
type definitions on impls.

```rust
Expand Down
1 change: 1 addition & 0 deletions src/items/traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Object safe traits can be the base trait of a [trait object]. A trait is
* All [supertraits] must also be object safe.
* `Sized` must not be a [supertrait][supertraits]. In other words, it must not require `Self: Sized`.
* It must not have any associated constants.
* It must not have any associated types with generics.
* All associated functions must either be dispatchable from a trait object or be explicitly non-dispatchable:
* Dispatchable functions require:
* Not have any type parameters (although lifetime parameters are allowed),
Expand Down
10 changes: 7 additions & 3 deletions src/items/type-aliases.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
> _TypeAlias_ :\
> &nbsp;&nbsp; `type` [IDENTIFIER]&nbsp;[_GenericParams_]<sup>?</sup>
> ( `:` [_TypeParamBounds_] )<sup>?</sup>
> [_WhereClause_]<sup>?</sup> ( `=` [_Type_] )<sup>?</sup> [_WhereClause_]<sup>?</sup> `;`
> [_WhereClause_]<sup>?</sup> ( `=` [_Type_] [_WhereClause_]<sup>?</sup>)<sup>?</sup> `;`

A _type alias_ defines a new name for an existing [type]. Type aliases are
declared with the keyword `type`. Every value has a single, specific type, but
Expand Down Expand Up @@ -34,11 +34,15 @@ let _ = TypeAlias(5); // Doesn't work
A type alias without the [_Type_] specification may only appear as an
[associated type] in a [trait].

A type alias with the [_Type_] specification may only appear as an
[associated type] in a [trait impl].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This clause by itself doesn't seem to be correct to me. It seems to imply that the following is not allowed:

type X = i32;

Perhaps this could be turned around so that it specifically says what a trait impl associated type needs? A sentence could be added to the previous paragraph, since they are talking about the same thing. Maybe something like this:

A type alias without the [Type] specification may only appear as an [associated type] in a [trait].
Associated types in a [trait impl] must include the [Type] specification.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made a separate paragraph for each for of type aliases, to be specific about what is allow, what is required, and what isn't allowed in each.


A type alias with [_TypeParamBounds_] may only specified when used as
an [associated type] in a [trait].

A type alias with where clauses after the equals sign may only appear as an
[associated type] in a [trait] or a [trait impl].
Where clauses before the equals sign on a type alias in a [trait impl] (like
jackh726 marked this conversation as resolved.
Show resolved Hide resolved
`type TypeAlias<T> where T: Foo = Bar<T>`) are deprecated. Where clauses after
the equals sign (like `type TypeAlias<T> where T: Foo = Bar<T>`) are preferred.

[IDENTIFIER]: ../identifiers.md
[_GenericParams_]: generics.md
Expand Down