Skip to content

Commit

Permalink
Merge pull request #1599 from chorman0773/spec-add-identifiers-items
Browse files Browse the repository at this point in the history
Add identifier syntax to items.md and subchapters
  • Loading branch information
ehuss authored Oct 31, 2024
2 parents 85c4a7a + 9e4d726 commit 604e682
Show file tree
Hide file tree
Showing 16 changed files with 692 additions and 50 deletions.
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

0 comments on commit 604e682

Please sign in to comment.