diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index d472c4db..7eb98daf 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -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 @@ -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. diff --git a/src/const_eval.md b/src/const_eval.md index 7cb85dc2..04146adf 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -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. @@ -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 diff --git a/src/items/generics.md b/src/items/generics.md index a8cb27ba..807ef87b 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -310,6 +310,12 @@ struct Foo<#[my_flexible_clone(unbounded)] H> { } ``` +r[items.generics.instantiation] +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. + + [array repeat expression]: ../expressions/array-expr.md [arrays]: ../types/array.md [slices]: ../types/slice.md diff --git a/src/names/preludes.md b/src/names/preludes.md index 97c1ba77..3a2c3ff1 100644 --- a/src/names/preludes.md +++ b/src/names/preludes.md @@ -76,35 +76,46 @@ See https://github.com/rust-lang/rust/issues/57288 for more about the alloc/test limitation. --> + 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] +> +> ```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 @@ -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. + 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 @@ -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 diff --git a/src/trait-bounds.md b/src/trait-bounds.md index f31265fb..15a4fec1 100644 --- a/src/trait-bounds.md +++ b/src/trait-bounds.md @@ -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. + 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. ```rust -# type Surface = i32; -trait Shape { - fn draw(&self, surface: Surface); - fn name() -> &'static str; +trait Trait { + type Assoc: Clone; } -fn draw_twice(surface: Surface, sh: T) { - sh.draw(surface); // Can call method because T: Shape - sh.draw(surface); +fn foo(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(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, S); +We also consider the item bounds of the self type of aliases to satisfy trait bounds. -fn name_figure( - figure: Figure, // Type Figure is well-formed because U: Shape -) { - println!( - "Figure of two {}", - U::name(), // Can use associated function - ); +```rust +trait Trait { + type Assoc: Iterator + where + ::Item: Clone; + // equivalent to + // type Assoc: Iterator; } -``` -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(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. + +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]. diff --git a/src/types.md b/src/types.md index de67050a..70507606 100644 --- a/src/types.md +++ b/src/types.md @@ -149,6 +149,31 @@ enum List { let a: List = 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. + +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. + [Array]: types/array.md [Boolean]: types/boolean.md [Closures]: types/closure.md diff --git a/src/types/alias-types.md b/src/types/alias-types.md new file mode 100644 index 00000000..d10ab761 --- /dev/null +++ b/src/types/alias-types.md @@ -0,0 +1,35 @@ +r[type.alias] + +- associated types +- opaque types + - link from "impl-trait type" to this or param + +r[type.alias.rigid] + +Aliases might be treated as *rigid* in their current environment. In this case they behave like other types. +Their equality is structural, *rigid* aliases are only equal if both have the same type constructor and equal corresponding arguments. + +r[type.alias.normalization] + +Alias types can be normalized to their underlying type. +- for associated types this is the type provided by the corresponding impl +- opaque types + +r[type.alias.normalization.assoc-type] + +Similar to how trait bounds get satisfied, associated types can be normalized via +multiple different candidates + +- impl (also builtin) +- projection bound in the environment TODO: where do we talk about them +- alias bound of their self type + +candidate preference: +- normalizing an alias relies on the candidate group used to prove their corresponding trait bound +- if corresponding trait bound has been proven via a where-bound or an alias-bound, we do not consider impls + - if there is no remaining candidate, the associated type is rigid + +For all applicable candidates we +- prefer where-bounds +- then alias bounds +- then impls diff --git a/src/types/numeric.md b/src/types/numeric.md index 73c61991..5b796e41 100644 --- a/src/types/numeric.md +++ b/src/types/numeric.md @@ -44,7 +44,7 @@ platform's pointer type. It can represent every memory address in the process. > For more information, see the documentation for [type cast expressions], [`std::ptr`], and [provenance][std::ptr#provenance] in particular. r[type.numeric.int.size.isize] -The `isize` type is a signed integer type with the same number of bits as the +The `isize` type is a signed two's complement integer type with the same number of bits as the platform's pointer type. The theoretical upper bound on object and array size is the maximum `isize` value. This ensures that `isize` can be used to calculate differences between pointers into an object or array and can address every byte