Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2769545
specify s390x target features
folkertdev Aug 20, 2025
4ec04bc
Revise `s390x` codegen text
traviscross Aug 20, 2025
ea013b5
feat: guarantee the binary representation of `isize` explicitly
AudaciousAxiom Oct 25, 2025
32b22e8
Merge pull request #1972 from folkertdev/s390x-target-features
ehuss Nov 9, 2025
07be87e
const_eval.md: be more clear where link leads to
tshepang Nov 10, 2025
0e9e11d
Merge pull request #2083 from tshepang/patch-3
ehuss Nov 11, 2025
7e7ae6c
Unwrap the no_std attribute
ehuss May 31, 2025
a5a160d
Add names.preludes.extern.no_std.syntax
ehuss May 31, 2025
acb4347
Remove duplicate link definition
ehuss May 31, 2025
dea61cb
Add example to no_std intro
ehuss May 31, 2025
4f50d52
Move note and warning to the intro
ehuss May 31, 2025
e464933
Rewrite no_std
ehuss May 31, 2025
d6e0a9f
Add a rule for `std` injection in edition 2018
ehuss May 31, 2025
f7d9d84
Add names.preludes.extern.no_std.duplicates
ehuss May 31, 2025
97ea130
Minor update of `no_std`
ehuss Sep 22, 2025
9d79e59
Align `no_std` intro language better and reword
traviscross Nov 9, 2025
ae893d6
Revise `no_std` text to increase parallelism
traviscross Nov 11, 2025
8d7877e
Revise `no_std` intro WRT the preludes
traviscross Nov 11, 2025
b15b601
Revise `no_std` warning
traviscross Nov 11, 2025
97f3e33
Revise `no_std` text WRT `macro_use`
traviscross Nov 11, 2025
bbb5cc6
Merge pull request #1913 from ehuss/no_std
traviscross Nov 11, 2025
2f10103
Unwrap no_implicit_prelude
ehuss May 31, 2025
0fe507d
Add an example for no_implicit_prelude
ehuss May 31, 2025
b5e3e26
Add explicit rules for no_implicit_prelude
ehuss May 31, 2025
a2b8f93
Rewrite no_implicit_prelude to move to a specific rule
ehuss May 31, 2025
0ed80f7
Be explicit in the wording here
ehuss May 31, 2025
70fa8bd
Minor update of `no_implicit_prelude`
ehuss Sep 22, 2025
9ca5c57
Fix no_implicit_prelude to document the *current* edition in the main…
ehuss Nov 9, 2025
69707f4
Wrap and reword `no_implicit_prelude` code comments
traviscross Nov 11, 2025
60b7586
Revise `no_implicit_prelude.allowed-positions` text
traviscross Nov 11, 2025
ee80656
Revise `no_implicit_prelude.excluded-preludes` text
traviscross Nov 11, 2025
a5a9f03
Bring `no_implicit_prelude.edition2018` into present
traviscross Nov 11, 2025
3ba86bf
Merge pull request #1914 from ehuss/no_implicit_prelude
traviscross Nov 11, 2025
9753ddb
Merge pull request #2064 from AudaciousAxiom/feat/isize-repr-guarantee
ehuss Nov 12, 2025
eecf819
cool beans
lcnr Aug 20, 2025
a686c04
nyaa
lcnr Aug 27, 2025
62d1539
Update src/trait-bounds.md
lcnr Sep 10, 2025
c35b728
rarw
lcnr Sep 17, 2025
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
27 changes: 25 additions & 2 deletions src/attributes/codegen.md
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,30 @@ Feature | Implicitly Enables | Description
[tail-call]: https://github.com/webassembly/tail-call
[multivalue]: https://github.com/webassembly/multi-value

r[attributes.codegen.target_feature.s390x]
#### `s390x`

On `s390x` targets, use of functions with the `#[target_feature]` attribute follows the [above restrictions][attributes.codegen.target_feature.safety-restrictions].

Further documentation on these features can be found in the "Additions to z/Architecture" section of Chapter 1 of the *[z/Architecture Principles of Operation]*.

Feature | Implicitly Enables | Description
---------------------------------------|---------------------------------------|---------------------
`vector` | | 128-bit vector instructions
`vector-enhancements-1` | `vector` | vector enhancements 1
`vector-enhancements-2` | `vector-enhancements-1` | vector enhancements 2
`vector-enhancements-3` | `vector-enhancements-2` | vector enhancements 3
`vector-packed-decimal` | `vector` | vector packed-decimal
`vector-packed-decimal-enhancement` | `vector-packed-decimal` | vector packed-decimal enhancement
`vector-packed-decimal-enhancement-2` | `vector-packed-decimal-enhancement-2` | vector packed-decimal enhancement 2
`vector-packed-decimal-enhancement-3` | `vector-packed-decimal-enhancement-3` | vector packed-decimal enhancement 3
`nnp-assist` | `vector` | nnp assist
`miscellaneous-extensions-2` | | miscellaneous extensions 2
`miscellaneous-extensions-3` | | miscellaneous extensions 3
`miscellaneous-extensions-4` | | miscellaneous extensions 4

[z/Architecture Principles of Operation]: https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf

r[attributes.codegen.target_feature.info]
### Additional information

Expand All @@ -588,8 +612,7 @@ that this option is not affected by the `target_feature` attribute, and is
only driven by the features enabled for the entire crate.

r[attributes.codegen.target_feature.remark-rt]
See the [`is_x86_feature_detected`] or [`is_aarch64_feature_detected`] macros
in the standard library for runtime feature detection on these platforms.
Whether a feature is enabled can be checked at runtime using a platform-specific macro from the standard library, for instance [`is_x86_feature_detected`] or [`is_aarch64_feature_detected`].

> [!NOTE]
> `rustc` has a default set of features enabled for each target and CPU. The CPU may be chosen with the [`-C target-cpu`] flag. Individual features may be enabled or disabled for an entire crate with the [`-C target-feature`] flag.
Expand Down
4 changes: 2 additions & 2 deletions src/const_eval.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ r[const-eval.const-expr.array]
* [Array expressions].

r[const-eval.const-expr.constructor]
* [Struct] expressions.
* [Struct expressions].

r[const-eval.const-expr.block]
* [Block expressions], including `unsafe` and `const` blocks.
Expand Down Expand Up @@ -332,7 +332,7 @@ The types of a const function's parameters and return type are restricted to tho
[range expressions]: expressions/range-expr.md
[slice]: types/slice.md
[statics]: items/static-items.md
[struct]: expressions/struct-expr.md
[Struct expressions]: expressions/struct-expr.md
[temporary lifetime extension]: destructors.scope.lifetime-extension
[tuple enum variant]: items/enumerations.md
[tuple expressions]: expressions/tuple-expr.md
Expand Down
6 changes: 6 additions & 0 deletions src/items/generics.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,12 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
}
```

r[items.generics.instantiation]
Copy link
Member

Choose a reason for hiding this comment

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

This section feels hard :/

Do we define "instantiation" anywhere? I feel like could just be worded as

When using an item all occurrences of the its generics parameters are replaced with either the explicitly provided argument or a new inference variable.

Though, this is very imprecise, and kind of overlaps with other statements (e.g. items.fn.generics.mono).

(Quite note, but " with either the explicitly provided argument" isn't quite right? We substitute with all new inference variables, but some are later unified with known arguments? Certainly, there's a semantic identity and I think it's more clear to talk about it this way. I bring it up because I'll use it below.)

I almost kind of would expect a bit more of a baseline definition - what is monomorphization and that all generics must be defined for monomorphization to occur. Then, discuss how this happens: substitution. And for that, I would like go more technical (and, my example doesn't quite align with the technical wording we use elsewhere, but I imagine we want to it, just giving a rough example):

For an item with generic parameters `<P0..Pn>`, we define a _substitution_ `[S0, ..., Sn]` consisting of a new inference variable for each generic parameter. Then, occurrences of each parameter are substituted with the variable defined in the substitution: `P0 => S0, ..., Pn => Sn`.

Explicitly provided arguments are unified with their respective inference variables. 

When using an item its generic parameters have to get instantiated. This replaces all occurances of the parameter with either the explicitly provided argument or a new unconstrained inference variable.

Instantiating the generic parameters of an item generally requires proving its where clauses.
Copy link
Member

Choose a reason for hiding this comment

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

Likely, the word "generally" here will want to be elaborated here - or the statement should be changed around a bit.

I could imagine us wanting to change this around a bit - focusing instead of what we want to ensure happens by proving its where clauses. I.e. what are the invariants we want to hold by proving its where clauses. Where clause solving during impl selection is also probably a specific thing we want to call out.



[array repeat expression]: ../expressions/array-expr.md
[arrays]: ../types/array.md
[slices]: ../types/slice.md
Expand Down
92 changes: 66 additions & 26 deletions src/names/preludes.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,35 +76,46 @@ See https://github.com/rust-lang/rust/issues/57288 for more about the
alloc/test limitation.
-->

<!-- template:attributes -->
r[names.preludes.extern.no_std]
### The `no_std` attribute

r[names.preludes.extern.no_std.intro]
By default, the standard library is automatically included in the crate root
module. The [`std`] crate is added to the root, along with an implicit
[`macro_use` attribute] pulling in all macros exported from `std` into the
[`macro_use` prelude]. Both [`core`] and [`std`] are added to the [extern
prelude].
The *`no_std` [attribute][attributes]* causes the [`std`] crate to not be linked automatically, the [standard library prelude] to instead use the `core` prelude, and the [`macro_use` prelude] to instead use the macros exported from the `core` crate.

> [!EXAMPLE]
> <!-- ignore: test infrastructure can't handle no_std -->
> ```rust,ignore
> #![no_std]
> ```

> [!NOTE]
> Using `no_std` is useful when either the crate is targeting a platform that does not support the standard library or is purposefully not using the capabilities of the standard library. Those capabilities are mainly dynamic memory allocation (e.g. `Box` and `Vec`) and file and network capabilities (e.g. `std::fs` and `std::io`).

> [!WARNING]
> Using `no_std` does not prevent the standard library from being linked. It is still valid to write `extern crate std` in the crate or in one of its dependencies; this will cause the compiler to link the `std` crate into the program.

r[names.preludes.extern.no_std.syntax]
The `no_std` attribute uses the [MetaWord] syntax.

r[names.preludes.extern.no_std.allowed-positions]
The *`no_std` [attribute]* may be applied at the crate level to prevent the
[`std`] crate from being automatically added into scope.
The `no_std` attribute may only be applied to the crate root.

It does three things:
r[names.preludes.extern.no_std.duplicates]
The `no_std` attribute may be used any number of times on a form.

> [!NOTE]
> `rustc` lints against any use following the first.

r[names.preludes.extern.no_std.extern]
* Prevents `std` from being added to the [extern prelude](#extern-prelude).
r[names.preludes.extern.no_std.module]
* Affects which module is used to make up the [standard library prelude] (as described above).
r[names.preludes.extern.no_std.core]
* Injects the [`core`] crate into the crate root instead of [`std`], and pulls
in all macros exported from `core` in the [`macro_use` prelude].
The `no_std` attribute changes the [standard library prelude] to use the `core` prelude instead of the `std` prelude.

> [!NOTE]
> Using the core prelude over the standard prelude is useful when either the crate is targeting a platform that does not support the standard library or is purposefully not using the capabilities of the standard library. Those capabilities are mainly dynamic memory allocation (e.g. `Box` and `Vec`) and file and network capabilities (e.g. `std::fs` and `std::io`).
r[names.preludes.extern.no_std.macro_use]
By default, all macros exported from the `std` crate are added to the [`macro_use` prelude]. If the `no_std` attribute is specified, then all macros exported from the `core` crate are placed into the [`macro_use` prelude] instead.

> [!WARNING]
> Using `no_std` does not prevent the standard library from being linked in. It is still valid to put `extern crate std;` into the crate and dependencies can also link it in.
r[names.preludes.extern.no_std.edition2018]
> [!EDITION-2018]
> Before the 2018 edition, `std` is injected into the crate root by default. If `no_std` is specified, `core` is injected instead. Starting with the 2018 edition, regardless of `no_std` being specified, neither is injected into the crate root.

r[names.preludes.lang]
## Language prelude
Expand Down Expand Up @@ -140,27 +151,56 @@ r[names.preludes.tool.intro]
The tool prelude includes tool names for external tools in the [type
namespace]. See the [tool attributes] section for more details.

<!-- template:attributes -->
r[names.preludes.no_implicit_prelude]
## The `no_implicit_prelude` attribute

r[names.preludes.no_implicit_prelude.intro]
The *`no_implicit_prelude` [attribute]* may be applied at the crate level or
on a module to indicate that it should not automatically bring the [standard
library prelude], [extern prelude], or [tool prelude] into scope for that
module or any of its descendants.
The *`no_implicit_prelude` [attribute]* is used to prevent implicit preludes from being brought into scope.

> [!EXAMPLE]
> ```rust
> // The attribute can be applied to the crate root to affect
> // all modules.
> #![no_implicit_prelude]
>
> // Or it can be applied to a module to only affect that module
> // and its descendants.
> #[no_implicit_prelude]
> mod example {
> // ...
> }
> ```

r[names.preludes.no_implicit_prelude.syntax]
The `no_implicit_prelude` attribute uses the [MetaWord] syntax.

r[names.preludes.no_implicit_prelude.allowed-positions]
The `no_implicit_prelude` attribute may only be applied to the crate or to a module.

> [!NOTE]
> `rustc` ignores use in other positions but lints against it. This may become an error in the future.

r[names.preludes.no_implicit_prelude.duplicates]
The `no_implicit_prelude` attribute may be used any number of times on a form.

> [!NOTE]
> `rustc` lints against any use following the first.

r[names.preludes.no_implicit_prelude.excluded-preludes]
The `no_implicit_prelude` attribute prevents the [standard library prelude], [extern prelude], [`macro_use` prelude], and the [tool prelude] from being brought into scope for the module and its descendants.

r[names.preludes.no_implicit_prelude.lang]
This attribute does not affect the [language prelude].
The `no_implicit_prelude` attribute does not affect the [language prelude].

r[names.preludes.no_implicit_prelude.edition2018]
> [!EDITION-2018]
> In the 2015 edition, the `no_implicit_prelude` attribute does not affect the [`macro_use` prelude], and all macros exported from the standard library are still included in the `macro_use` prelude. Starting in the 2018 edition, it will remove the `macro_use` prelude.
> In the 2015 edition, the `no_implicit_prelude` attribute does not affect the [`macro_use` prelude], and all macros exported from the standard library are still included in the `macro_use` prelude. Starting in the 2018 edition, the attribute does remove the `macro_use` prelude.

[`extern crate`]: ../items/extern-crates.md
[`macro_use` attribute]: ../macros-by-example.md#the-macro_use-attribute
[`macro_use` prelude]: #macro_use-prelude
[`no_std` attribute]: #the-no_std-attribute
[`no_std` attribute]: #the-no_std-attribute
[attribute]: ../attributes.md
[Boolean type]: ../types/boolean.md
[Built-in attributes]: ../attributes.md#built-in-attributes-index
Expand All @@ -171,7 +211,7 @@ r[names.preludes.no_implicit_prelude.edition2018]
[Machine-dependent integer types]: ../types/numeric.md#machine-dependent-integer-types
[Macro namespace]: namespaces.md
[name resolution]: name-resolution.md
[Standard library prelude]: #standard-library-prelude
[standard library prelude]: names.preludes.std
[Textual types]: ../types/textual.md
[tool attributes]: ../attributes.md#tool-attributes
[Tool prelude]: #tool-prelude
Expand Down
115 changes: 68 additions & 47 deletions src/trait-bounds.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,68 +44,89 @@ certain common cases:
`trait A { type B: Copy; }` is equivalent to
`trait A where Self::B: Copy { type B; }`.

r[bound.global]

Bounds which does not use the item's parameters or any higher-ranked lifetimes are considered global.

An error is emitted if a global bound cannot be satisfied in an empty environment.
Copy link
Member

Choose a reason for hiding this comment

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

I'd probably reword this like:

"Global bounds must be satisfiable without relying on any where clauses."


r[bound.satisfaction]
Bounds on an item must be satisfied when using the item. When type checking and
borrow checking a generic item, the bounds can be used to determine that a
trait is implemented for a type. For example, given `Ty: Trait`

* In the body of a generic function, methods from `Trait` can be called on `Ty`
values. Likewise associated constants on the `Trait` can be used.
* Associated types from `Trait` can be used.
* Generic functions and types with a `T: Trait` bounds can be used with `Ty`
being used for `T`.
The bounds of an item must be satisfied when using that item.

r[bound.satisfaction.impl]

A trait bound can be satisfied by using an implementation of that trait. An implementation is applicable if,
after instantiating its generic parameters with new inference variables, the self type and trait arguments are
equal to the trait bound and the where-bounds of the impl can be recursively satisfied.

r[bound.satisfaction.impl.builtin]

There exist impls which are automatically generated by the compiler.

- `Sized`,`Copy`, `Clone`,...


- alternative: mention this in item-kind impl

r[bound.satisfaction.impl.builtin.trait-object]

Trait objects implement their trait if TODO: lookup conditions, something something project bounds make sense

r[bound.satisfaction.bounds]

While inside of a generic item, trait bounds can be satisfied by using the where-bounds of the current item as the item is able to assume that its bounds are satisfied. For this, higher-ranked where-bounds can be instantiated with inference variables. The where-bound is then equated with the trait bound that needs to be satisfied.

r[bound.satisfaction.alias-bounds]

If an alias type is rigid in the current environment, trait bounds using this alias as a self type can be satisfied by using its item bounds.
Copy link
Member

Choose a reason for hiding this comment

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

Oh, these are some of the code examples I had mentioned above. Would probably want to see this discussed outside of a "when an alias is rigid" example.


```rust
# type Surface = i32;
trait Shape {
fn draw(&self, surface: Surface);
fn name() -> &'static str;
trait Trait {
type Assoc: Clone;
}

fn draw_twice<T: Shape>(surface: Surface, sh: T) {
sh.draw(surface); // Can call method because T: Shape
sh.draw(surface);
fn foo<T: Trait>(x: &T::Assoc) -> T::Assoc {
// The where-bound `T::Assoc: Clone` is satisfied using the `Clone` item-bound.
x.clone()
}
```

fn copy_and_draw_twice<T: Copy>(surface: Surface, sh: T) where T: Shape {
let shape_copy = sh; // doesn't move sh because T: Copy
draw_twice(surface, sh); // Can use generic function because T: Shape
}
r[bound.satisfaction.alias-bounds.nested]

struct Figure<S: Shape>(S, S);
We also consider the item bounds of the self type of aliases to satisfy trait bounds.

fn name_figure<U: Shape>(
figure: Figure<U>, // Type Figure<U> is well-formed because U: Shape
) {
println!(
"Figure of two {}",
U::name(), // Can use associated function
);
```rust
trait Trait {
type Assoc: Iterator
where
<Self::Assoc as Iterator>::Item: Clone;
// equivalent to
// type Assoc: Iterator<Item: Clone>;
}
```

r[bound.trivial]
Bounds that don't use the item's parameters or [higher-ranked lifetimes] are checked when the item is defined.
It is an error for such a bound to be false.

r[bound.special]
[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic types when using the item, even if the use does not provide a concrete type.
It is an error to have `Copy` or `Clone` as a bound on a mutable reference, [trait object], or [slice].
It is an error to have `Sized` as a bound on a trait object or slice.

```rust,compile_fail
struct A<'a, T>
where
i32: Default, // Allowed, but not useful
i32: Iterator, // Error: `i32` is not an iterator
&'a mut T: Copy, // (at use) Error: the trait bound is not satisfied
[T]: Sized, // (at use) Error: size cannot be known at compilation
{
f: &'a T,
fn item_is_clone<T: Trait>(iter: T::Assoc) {
for item in iter {
let _ = item.clone();
}
}
struct UsesA<'a, T>(A<'a, T>);
```


r[bound.satisfaction.candidate-preference]

> This is purely descriptive. Candidate preference behavior may change in future releases and must not be relied upon for correctness or soundness.
Copy link
Member

Choose a reason for hiding this comment

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

Ah, great! Probably should just link the other section to this, then split this across aliases and trait bounds.


If there are multiple ways to satisfy a trait bound, some groups of candidate are preferred over others. In case a single group has multiple different candidates, the bound remains ambiguous. Candidate preference has the following order
- builtin implementations of `Sized`
- if there are any non-global where-bounds, all where-bounds
- alias-bounds
- impls
- In case the goal trait bound does not contain any inference variables, we prefer builtin trait object impls over user-written impls. TODO: that's unsound jank
- global where-bounds (only relevant if it does not hold)

> note: this candidate preference can result in incorrect errors and type mismatches, e.g. ...

r[bound.trait-object]
Trait and lifetime bounds are also used to name [trait objects].

Expand Down
25 changes: 25 additions & 0 deletions src/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,31 @@ enum List<T> {
let a: List<i32> = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil))));
```

## Equality of types

r[types.equality]

Equality and subtyping of types is generally structural; if the outermost type constructors are the same,
their corresponding generic arguments are pairwise compared. We say types with this equality behavior are *rigid*. The only exceptions from this rule are higher ranked types and alias types.
Comment on lines +156 to +157
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, okay, this is sort of what I meant in a previous comment on wanting to see this split out.

I'd probably just rephrase this as:

Two types are structurally equal if the following conditions are met:
- their type constructors are the same
- each generic parameter are pair-wise structurally equal

(q: is this second point too strong - do we structurally equate parameters, or do general equality?)

We say types with this equality behavior are rigid.

Kind of weird use of this terminology, but I guess not incorrect. It's pretty confusing that we refer to this as both "rigid" and "structural". We should probably decide on the precise definitions of these as a team.

The only exceptions from this rule are higher ranked types and alias types.

This probably deserves to be in an "intro" paragraph (and leave the definition of structural equality as it's own paragraph.


r[types.equality.rigid]

r[types.equality.aliases]

Aliases are compared by first normalizing them to a *rigid* type and then equating their type constructors and recursing into their generic arguments.

r[types.equality.higher-ranked]

Function pointers and trait objects may be higher-ranked.

r[types.equality.higher-ranked.sub]

Subtyping is checked by instantiating the `for` of the subtype with inference variables and the `for` of the supertype with placeholders before relating them as normal.

r[types.equality.higher-ranked.eq]

Equality is checked by both instantiating the `for` of the lhs with inference variables and the `for` of the rhs with placeholders before equating them, and also doing the opposite.
Copy link
Member

Choose a reason for hiding this comment

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

Do we define "placeholders" anywhere? I'm really afraid that these are kind of "just" words without a lot of "meaning" of what someone unfamiliar without the specifics of how our type system works would understand.


[Array]: types/array.md
[Boolean]: types/boolean.md
[Closures]: types/closure.md
Expand Down
Loading
Loading