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 identifier syntax to items.md and subchapters #1599

Merged
merged 4 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/items.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Items

r[items]

r[items.syntax]
> **<sup>Syntax:<sup>**\
> _Item_:\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>\
Expand Down Expand Up @@ -28,15 +31,17 @@
> &nbsp;&nbsp; &nbsp;&nbsp; [_MacroInvocationSemi_]\
> &nbsp;&nbsp; | [_MacroRulesDefinition_]


r[items.intro]
An _item_ is a component of a crate. Items are organized within a crate by a
nested set of [modules]. Every crate has a single "outermost" anonymous module;
all further items within the crate have [paths] within the module tree of the
crate.

r[items.static-def]
Items are entirely determined at compile-time, generally remain fixed during
execution, and may reside in read-only memory.

r[items.kinds]
There are several kinds of items:

* [modules]
Expand All @@ -53,11 +58,19 @@ There are several kinds of items:
* [implementations]
* [`extern` blocks]

r[items.locations]
Items may be declared in the [root of the crate], a [module][modules], or a [block expression].

r[items.associated-locations]
A subset of items, called [associated items], may be declared in [traits] and [implementations].

r[items.extern-locations]
A subset of items, called external items, may be declared in [`extern` blocks].

r[items.decl-order]
Items may be defined in any order, with the exception of [`macro_rules`] which has its own scoping behavior.

r[items.name-resolution]
[Name resolution] of item names allows items to be defined before or after where the item is referred to in the module or block.

See [item scopes] for information on the scoping rules of items.
Expand Down
86 changes: 72 additions & 14 deletions src/items/associated-items.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,62 @@
# Associated Items

r[items.associated]

r[items.associated.syntax]
> **<sup>Syntax</sup>**\
> _AssociatedItem_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup> (\
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_MacroInvocationSemi_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | ( [_Visibility_]<sup>?</sup> ( [_TypeAlias_] | [_ConstantItem_] | [_Function_] ) )\
> &nbsp;&nbsp; )

r[items.associated.intro]
*Associated Items* are the items declared in [traits] or defined in
[implementations]. They are called this because they are defined on an associate
type &mdash; the type in the implementation. They are a subset of the kinds of
items you can declare in a module. Specifically, there are [associated
functions] (including methods), [associated types], and [associated constants].
type &mdash; the type in the implementation.

r[items.associated.kinds]
They are a subset of the kinds of items you can declare in a module.
Specifically, there are [associated functions] (including methods), [associated types], and [associated constants].

[associated functions]: #associated-functions-and-methods
[associated types]: #associated-types
[associated constants]: #associated-constants

r[items.associated.related]
Associated items are useful when the associated item logically is related to the
associating item. For example, the `is_some` method on `Option` is intrinsically
related to Options, so should be associated.

r[items.associated.decl-def]
Every associated item kind comes in two varieties: definitions that contain the
actual implementation and declarations that declare signatures for
definitions.

r[items.associated.trait-items]
It is the declarations that make up the contract of traits and what is available
on generic types.

## Associated functions and methods

r[items.associated.fn]

r[items.associated.fn.intro]
*Associated functions* are [functions] associated with a type.

r[items.associated.fn.decl]
An *associated function declaration* declares a signature for an associated
function definition. It is written as a function item, except the
function body is replaced with a `;`.

The identifier is the name of the function. The generics, parameter list,
return type, and where clause of the associated function must be the same as the
r[items.associated.name]
The identifier is the name of the function.

r[items.associated.same-signature]
The generics, parameter list, return type, and where clause of the associated function must be the same as the
associated function declarations's.

r[items.associated.fn.def]
An *associated function definition* defines a function associated with another
type. It is written the same as a [function item].

Expand All @@ -64,6 +81,7 @@ fn main () {
}
```

r[items.associated.fn.qualified-self]
When the associated function is declared on a trait, the function can also be
called with a [path] that is a path to the trait appended by the name of the
trait. When this happens, it is substituted for `<_ as Trait>::function_name`.
Expand All @@ -86,10 +104,14 @@ let _: f64 = f64::from_i32(42);

### Methods

r[items.associated.fn.method]

r[items.associated.fn.method.intro]
Associated functions whose first parameter is named `self` are called *methods*
and may be invoked using the [method call operator], for example, `x.foo()`, as
well as the usual function call notation.

r[items.associated.fn.method.self-ty]
If the type of the `self` parameter is specified, it is limited to types resolving
to one generated by the following grammar (where `'lt` denotes some arbitrary
lifetime):
Expand Down Expand Up @@ -127,6 +149,7 @@ impl Example {
}
```

r[associated.fn.method.self-pat-shorthands]
Shorthand syntax can be used without specifying a type, which have the
following equivalents:

Expand All @@ -138,6 +161,7 @@ Shorthand | Equivalent

> **Note**: Lifetimes can be, and usually are, elided with this shorthand.

r[associated.fn.method.self-pat-mut]
If the `self` parameter is prefixed with `mut`, it becomes a mutable variable,
similar to regular parameters using a `mut` [identifier pattern]. For example:

Expand Down Expand Up @@ -189,21 +213,30 @@ let circle_shape = Circle::new();
let bounding_box = circle_shape.bounding_box();
```

r[items.associated.fn.params.edition2015]
> **Edition differences**: In the 2015 edition, it is possible to declare trait
> methods with anonymous parameters (e.g. `fn foo(u8)`). This is deprecated and
> an error as of the 2018 edition. All parameters must have an argument name.

#### Attributes on method parameters

r[items.associated.fn.param-attributes]

Attributes on method parameters follow the same rules and restrictions as
[regular function parameters].

## Associated Types

*Associated types* are [type aliases] associated with another type. Associated
types cannot be defined in [inherent implementations] nor can they be given a
r[items.associated.type]

r[items.associated.type.intro]
*Associated types* are [type aliases] associated with another type.

r[items.associated.type.restrictions]
Associated types cannot be defined in [inherent implementations] nor can they be given a
default implementation in traits.

r[items.associated.type.decl]
An *associated type declaration* declares a signature for associated type
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,
Expand All @@ -221,13 +254,21 @@ type Assoc<Params> where WhereBounds;
type Assoc<Params>: Bounds where WhereBounds;
```

The identifier is the name of the declared type alias. The optional trait bounds
must be fulfilled by the implementations of the type alias.
r[items.associated.type.name]
The identifier is the name of the declared type alias.

r[items.associated.type.impl-fulfillment]
The optional trait bounds must be fulfilled by the implementations of the type alias.

r[items.associated.type.sized]
There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound.

r[items.associated.type.def]
An *associated type definition* defines a type alias for the implementation
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`:
of a trait on a type

r[items.associated.type.def.restriction]
They are written similarly to an *associated type declaration*, but cannot contain `Bounds`, but instead must contain a `Type`:

<!-- ignore: illustrative example forms -->
```rust,ignore
Expand All @@ -237,11 +278,15 @@ type Assoc<Params> = Type where WhereBounds;
type Assoc<Params> where WhereBounds = Type; // deprecated, prefer the form above
```

r[items.associated.type.alias]
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 type definition

r[items.associated.type.param]
Furthermore, if `Item` is a type parameter, then `Item::Assoc` can be used in type parameters.

r[items.associated.type.generic]
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
Expand Down Expand Up @@ -300,7 +345,6 @@ fn borrow<'a, T: Lend>(array: &'a mut T) -> <T as Lend>::Lender<'a> {
array.lend()
}


fn main() {
let mut array = [0usize; 16];
let lender = borrow(&mut array);
Expand Down Expand Up @@ -352,11 +396,15 @@ Given a reference to the associated type like `<X as Example>::Output<Y>`, the a

### Required where clauses on generic associated types

r[items.associated.type.generic-where-clause]

r[items.associated.type.generic-where-clause.intro]
Generic associated type declarations on traits currently may require a list of
where clauses, dependent on functions in the trait and how the GAT is used. These
rules may be loosened in the future; updates can be found [on the generic
associated types initiative repository](https://rust-lang.github.io/generic-associated-types-initiative/explainer/required_bounds.html).

r[items.associated.type.generic-where-clause.valid-fn]
In a few words, these where clauses are required in order to maximize the allowed
definitions of the associated type in impls. To do this, any clauses that *can be
proven to hold* on functions (using the parameters of the function or trait)
Expand All @@ -373,6 +421,7 @@ In the above, on the `next` function, we can prove that `Self: 'a`, because of
the implied bounds from `&'a mut self`; therefore, we must write the equivalent
bound on the GAT itself: `where Self: 'x`.

r[items.associated.type.generic-where-clause.intersection]
When there are multiple functions in a trait that use the GAT, then the
*intersection* of the bounds from the different functions are used, rather than
the union.
Expand All @@ -390,6 +439,7 @@ know that `T: 'a` on `create_checker`, we do not know that on `do_check`. Howeve
if `do_check` was commented out, then the `where T: 'x` bound would be required
on `Checker`.

r[items.associated.type.generic-where-clause.forward]
The bounds on associated types also propagate required where clauses.

```rust
Expand All @@ -404,6 +454,7 @@ Here, `where Self: 'a` is required on `Item` because of `iter`. However, `Item`
is used in the bounds of `Iterator`, the `where Self: 'a` clause is also required
there.

r[items.associated.type.generic-where-clause.static]
Finally, any explicit uses of `'static` on GATs in the trait do not count towards
the required bounds.

Expand All @@ -416,18 +467,25 @@ trait StaticReturn {

## Associated Constants

r[items.associated.const]

r[items.associated.const.intro]
*Associated constants* are [constants] associated with a type.

r[items.associated.const.decl]
An *associated constant declaration* declares a signature for associated
constant definitions. It is written as `const`, then an identifier,
then `:`, then a type, finished by a `;`.

r[items.associated.const.name]
The identifier is the name of the constant used in the path. The type is the
type that the definition has to implement.

r[items.associated.const.def]
An *associated constant definition* defines a constant associated with a
type. It is written the same as a [constant item].

r[items.associated.const.eval]
Associated constant definitions undergo [constant evaluation] only when
referenced. Further, definitions that include [generic parameters] are
evaluated after monomorphization.
Expand Down
22 changes: 20 additions & 2 deletions src/items/constant-items.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
# Constant items

r[items.const]

r[items.const.syntax]
> **<sup>Syntax</sup>**\
> _ConstantItem_ :\
> &nbsp;&nbsp; `const` ( [IDENTIFIER] | `_` ) `:` [_Type_] ( `=` [_Expression_] )<sup>?</sup> `;`

r[items.const.intro]
A *constant item* is an optionally named _[constant value]_ which is not associated
with a specific memory location in the program. Constants are essentially inlined
wherever they are used, meaning that they are copied directly into the relevant
with a specific memory location in the program.

r[items.const.behavior]
Constants are essentially inlined wherever they are used, meaning that they are copied directly into the relevant
context when used. This includes usage of constants from external crates, and
non-[`Copy`] types. References to the same constant are not necessarily
guaranteed to refer to the same memory address.

r[items.const.namespace]
The constant declaration defines the constant value in the [value namespace] of the module or block where it is located.

r[items.const.static]
Constants must be explicitly typed. The type must have a `'static` lifetime: any
references in the initializer must have `'static` lifetimes. References
in the type of a constant default to `'static` lifetime; see [static lifetime
elision].

r[items.const.static-temporary]
A reference to a constant will have `'static` lifetime if the constant value is eligible for
[promotion]; otherwise, a temporary will be created.

Expand All @@ -39,10 +48,13 @@ const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
};
```

r[items.const.expr-omission]
The constant expression may only be omitted in a [trait definition].

## Constants with Destructors

r[items.const.destructor]

Constants can contain destructors. Destructors are run when the value goes out
of scope.

Expand All @@ -66,6 +78,9 @@ fn create_and_drop_zero_with_destructor() {

## Unnamed constant

r[items.const.unnamed]

r[items.const.unnamed.intro]
Unlike an [associated constant], a [free] constant may be unnamed by using
an underscore instead of the name. For example:

Expand All @@ -76,6 +91,7 @@ const _: () = { struct _SameNameTwice; };
const _: () = { struct _SameNameTwice; };
```

r[items.const.unnamed.repetition]
As with [underscore imports], macros may safely emit the same unnamed constant in
the same scope more than once. For example, the following should not produce an error:

Expand All @@ -92,6 +108,8 @@ m!(const _: () = (););

## Evaluation

r[items.const.eval]

[Free][free] constants are always [evaluated][const_eval] at compile-time to surface
panics. This happens even within an unused function:

Expand Down
Loading